1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "ureg.h"
8 #include "../port/error.h"
9
10 /*
11 * Back the processor into real mode to run a BIOS call,
12 * then return. This must be used carefully, since it
13 * completely disables hardware interrupts (e.g., the i8259)
14 * while running. It is *not* using VM86 mode.
15 * Maybe that's really the right answer, but real mode
16 * is fine for now. We don't expect to use this very much --
17 * just for BIOS INT 13 disk i/o.
18 */
19
20 void realmode0(void); /* in realmode0.s */
21 void realmodeintrinst(void); /* in realmode0.s */
22 void realmodeend(void); /* in realmode0.s */
23
24 extern ushort rmseg; /* in realmode0.s */
25
26 static Ureg rmu;
27 static QLock rmlock;
28 static int beenhere;
29
30 void
realmode(Ureg * ureg)31 realmode(Ureg *ureg)
32 {
33 int s, sz;
34 ulong cr3;
35 uchar *ip;
36
37 qlock(&rmlock);
38 if (!beenhere)
39 iprint("into bios in real mode...");
40 *(Ureg *)RMUADDR = *ureg;
41
42 /*
43 * in pxe-loaded bootstraps, the l.s real-mode code is already
44 * below 64K, but for pbs-loaded bootstraps, we need to copy it there.
45 */
46 ip = (void *)realmodeintrinst; /* the INT instruction */
47 ip[1] = ureg->trap; /* insert INT number */
48 coherence();
49 if ((uintptr)KTZERO == KZERO+PXEBASE) /* pxe-loaded? */
50 rmseg = 0; /* into JMPFAR instr. */
51 else {
52 /* copy l.s so that it can be run from 16-bit mode */
53 sz = (char *)realmodeend - (char *)KTZERO;
54 if (sz > RMSIZE)
55 panic("real mode code %d bytes > %d", sz, RMSIZE);
56 rmseg = (RMCODE - KZERO) >> 4; /* into JMPFAR instr. */
57 memmove((void*)RMCODE, (void*)KTZERO, sz);
58 }
59 coherence();
60
61 s = splhi();
62 m->pdb[PDX(0)] = m->pdb[PDX(KZERO)]; /* identity map low */
63 cr3 = getcr3();
64 putcr3(PADDR(m->pdb));
65 if (arch)
66 arch->introff();
67 else
68 i8259off();
69
70 realmode0();
71 splhi(); /* who knows what the bios did */
72
73 if(m->tss){
74 /*
75 * Called from memory.c before initialization of mmu.
76 * Don't turn interrupts on before the kernel is ready!
77 */
78 if (arch)
79 arch->intron();
80 else
81 i8259on();
82 }
83 m->pdb[PDX(0)] = 0; /* remove low mapping */
84 putcr3(cr3);
85 splx(s);
86
87 *ureg = *(Ureg *)RMUADDR;
88 if (!beenhere) {
89 beenhere = 1;
90 iprint("and back\n");
91 }
92 qunlock(&rmlock);
93 }
94