#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" /* * Back the processor into real mode to run a BIOS call, * then return. This must be used carefully, since it * completely disables hardware interrupts (e.g., the i8259) * while running. It is *not* using VM86 mode. * Maybe that's really the right answer, but real mode * is fine for now. We don't expect to use this very much -- * just for BIOS INT 13 disk i/o. */ void realmode0(void); /* in realmode0.s */ void realmodeintrinst(void); /* in realmode0.s */ void realmodeend(void); /* in realmode0.s */ extern ushort rmseg; /* in realmode0.s */ static Ureg rmu; static QLock rmlock; static int beenhere; void realmode(Ureg *ureg) { int s, sz; ulong cr3; uchar *ip; qlock(&rmlock); if (!beenhere) iprint("into bios in real mode..."); *(Ureg *)RMUADDR = *ureg; /* * in pxe-loaded bootstraps, the l.s real-mode code is already * below 64K, but for pbs-loaded bootstraps, we need to copy it there. */ ip = (void *)realmodeintrinst; /* the INT instruction */ ip[1] = ureg->trap; /* insert INT number */ coherence(); if ((uintptr)KTZERO == KZERO+PXEBASE) /* pxe-loaded? */ rmseg = 0; /* into JMPFAR instr. */ else { /* copy l.s so that it can be run from 16-bit mode */ sz = (char *)realmodeend - (char *)KTZERO; if (sz > RMSIZE) panic("real mode code %d bytes > %d", sz, RMSIZE); rmseg = (RMCODE - KZERO) >> 4; /* into JMPFAR instr. */ memmove((void*)RMCODE, (void*)KTZERO, sz); } coherence(); s = splhi(); m->pdb[PDX(0)] = m->pdb[PDX(KZERO)]; /* identity map low */ cr3 = getcr3(); putcr3(PADDR(m->pdb)); if (arch) arch->introff(); else i8259off(); realmode0(); splhi(); /* who knows what the bios did */ if(m->tss){ /* * Called from memory.c before initialization of mmu. * Don't turn interrupts on before the kernel is ready! */ if (arch) arch->intron(); else i8259on(); } m->pdb[PDX(0)] = 0; /* remove low mapping */ putcr3(cr3); splx(s); *ureg = *(Ureg *)RMUADDR; if (!beenhere) { beenhere = 1; iprint("and back\n"); } qunlock(&rmlock); }