Load kernels at non-standard base addresses. Also real-mode assembly. [rsc] --rw-rw-r-- M 140560 glenda sys 8421 Nov 1 18:20 sys/src/boot/pc/boot.c /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/boot.c:149,155 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/boot.c:149,155 if(php->type != LOAD) continue; offset = php->offset; - paddr = (char*)(php->paddr & ~0xF0000000); + paddr = (char*)PADDR(php->paddr); if(offset < curoff){ /* * Can't (be bothered to) rewind the /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/boot.c:215,221 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/boot.c:215,221 if(php->filesz < php->memsz){ print("%lud", php->memsz-php->filesz); elftotal += php->memsz-php->filesz; - memset((char*)((php->paddr & ~0xF0000000)+php->filesz), 0, php->memsz-php->filesz); + memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz); } curoff = php->offset+php->filesz; curphdr++; /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/boot.c:326,332 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/boot.c:326,332 case READ9TEXT: ep = &b->exec; b->state = READ9DATA; - b->bp = (char*)PGROUND(GLLONG(ep->entry)+GLLONG(ep->text)); + b->bp = (char*)PGROUND(PADDR(GLLONG(ep->entry))+GLLONG(ep->text)); b->wp = b->bp; b->ep = b->wp + GLLONG(ep->data); print("+%ld", GLLONG(ep->data)); /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/boot.c:432,438 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/boot.c:432,438 } /* relocate data to start at page boundary */ - memmove((void*)PGROUND(entry+text), (void*)(entry+text), data); + memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data); print("entry: %lux\n", entry); warp9(PADDR(entry)); [rsc] --rw-rw-r-- M 140560 glenda sys 4273 Nov 1 18:20 sys/src/boot/pc/fns.h /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/fns.h:106,111 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/fns.h:106,113 int spllo(void); void splx(int); void trapinit(void); + void trapdisable(void); + void trapenable(void); void uartdrain(void); void uartspecial(int, void (*)(int), int (*)(void), int); void uartputs(IOQ*, char*, int); /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/fns.h:130,136 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/fns.h:132,138 #define PLLONG(p,v) (p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24 #define KADDR(a) ((void*)((ulong)(a)|KZERO)) - #define PADDR(a) ((ulong)(a)&~KZERO) + #define PADDR(a) ((ulong)(a)&~0xF0000000) #define HOWMANY(x, y) (((x)+((y)-1))/(y)) #define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) [rsc] --rw-rw-r-- M 140560 glenda sys 18115 Nov 1 18:20 sys/src/boot/pc/l.s /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/l.s:356,367 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/l.s:356,370 LONG $(0xFFFF) LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */ + LONG $(0xFFFF) + LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) + /* * pointer to initial gdt */ TEXT tgdtptr(SB),$0 - - WORD $(3*8) + WORD $(4*8) LONG $tgdt-KZERO(SB) /* /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/l.s:847,849 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/l.s:850,1079 #else DATA pxe+0(SB)/4, $0 #endif /* PXE */ + + /* + * Save registers. + */ + TEXT saveregs(SB), $0 + /* appease 8l */ + SUBL $32, SP + POPL AX + POPL AX + POPL AX + POPL AX + POPL AX + POPL AX + POPL AX + POPL AX + + PUSHL AX + PUSHL BX + PUSHL CX + PUSHL DX + PUSHL BP + PUSHL DI + PUSHL SI + PUSHFL + + XCHGL 32(SP), AX /* swap return PC and saved flags */ + XCHGL 0(SP), AX + XCHGL 32(SP), AX + RET + + TEXT restoreregs(SB), $0 + /* appease 8l */ + PUSHL AX + PUSHL AX + PUSHL AX + PUSHL AX + PUSHL AX + PUSHL AX + PUSHL AX + PUSHL AX + ADDL $32, SP + + XCHGL 32(SP), AX /* swap return PC and saved flags */ + XCHGL 0(SP), AX + XCHGL 32(SP), AX + + POPFL + POPL SI + POPL DI + POPL BP + POPL DX + POPL CX + POPL BX + POPL AX + RET + + /* + * Assumed to be in protected mode at time of call. + * Switch to real mode, execute an interrupt, and + * then switch back to protected mode. + * + * Assumes: + * + * - no device interrupts are going to come in + * - 0-16MB is identity mapped in page tables + * - can use code segment 0x1000 in real mode + * to get at l.s code + */ + TEXT realmodeidtptr(SB), $0 + WORD $(4*256-1) + LONG $0 + + TEXT realmode0(SB), $0 + CALL saveregs(SB) + + /* switch to low code address */ + LEAL physcode-KZERO(SB), AX + JMP *AX + + TEXT physcode(SB), $0 + + /* switch to low stack */ + MOVL SP, AX + MOVL $0x7C00, SP + PUSHL AX + + /* load IDT with real-mode version; GDT already fine */ + MOVL realmodeidtptr(SB), IDTR + + /* edit INT $0x00 instruction below */ + MOVL realmodeintr(SB), AX + MOVB AX, realmodeintrinst+1(SB) + + /* disable paging */ + MOVL CR0, AX + ANDL $0x7FFFFFFF, AX + MOVL AX, CR0 + /* JMP .+2 to clear prefetch queue*/ + BYTE $0xEB; BYTE $0x00 + + /* jump to 16-bit code segment */ + /* JMPFAR SELECTOR(3, SELGDT, 0):$again16bit(SB) /**/ + BYTE $0xEA + LONG $again16bit-KZERO(SB) + WORD $SELECTOR(3, SELGDT, 0) + + TEXT again16bit(SB), $0 + /* + * Now in 16-bit compatibility mode. + * These are 32-bit instructions being interpreted + * as 16-bit instructions. I'm being lazy and + * not using the macros because I know when + * the 16- and 32-bit instructions look the same + * or close enough. + */ + + /* disable protected mode and jump to real mode cs */ + OPSIZE; MOVL CR0, AX + OPSIZE; XORL BX, BX + OPSIZE; INCL BX + OPSIZE; XORL BX, AX + OPSIZE; MOVL AX, CR0 + + /* JMPFAR 0x1000:now16real */ + BYTE $0xEA + WORD $now16real-KZERO(SB) + WORD $0x1000 + + TEXT now16real(SB), $0 + /* copy the registers for the bios call */ + LWI(0x1000, rAX) + MOVW AX,SS + LWI(realmoderegs(SB), rBP) + + /* offsets are in Ureg */ + LXW(44, xBP, rAX) + MOVW AX, DS + LXW(40, xBP, rAX) + MOVW AX, ES + + OPSIZE; LXW(0, xBP, rDI) + OPSIZE; LXW(4, xBP, rSI) + OPSIZE; LXW(16, xBP, rBX) + OPSIZE; LXW(20, xBP, rDX) + OPSIZE; LXW(24, xBP, rCX) + OPSIZE; LXW(28, xBP, rAX) + + CLC + + TEXT realmodeintrinst(SB), $0 + INT $0x00 + + /* save the registers after the call */ + + LWI(0x7bfc, rSP) + OPSIZE; PUSHFL + OPSIZE; PUSHL AX + + LWI(0x1000, rAX) + MOVW AX,SS + LWI(realmoderegs(SB), rBP) + + OPSIZE; SXW(rDI, 0, xBP) + OPSIZE; SXW(rSI, 4, xBP) + OPSIZE; SXW(rBX, 16, xBP) + OPSIZE; SXW(rDX, 20, xBP) + OPSIZE; SXW(rCX, 24, xBP) + OPSIZE; POPL AX + OPSIZE; SXW(rAX, 28, xBP) + + MOVW DS, AX + OPSIZE; SXW(rAX, 44, xBP) + MOVW ES, AX + OPSIZE; SXW(rAX, 40, xBP) + + OPSIZE; POPL AX + OPSIZE; SXW(rAX, 64, xBP) /* flags */ + + /* re-enter protected mode and jump to 32-bit code */ + OPSIZE; MOVL $1, AX + OPSIZE; MOVL AX, CR0 + + /* JMPFAR SELECTOR(2, SELGDT, 0):$again32bit(SB) /**/ + OPSIZE + BYTE $0xEA + LONG $again32bit-KZERO(SB) + WORD $SELECTOR(2, SELGDT, 0) + + TEXT again32bit(SB), $0 + MOVW $SELECTOR(1, SELGDT, 0),AX + MOVW AX,DS + MOVW AX,SS + MOVW AX,ES + MOVW AX,FS + MOVW AX,GS + + /* enable paging and jump to kzero-address code */ + MOVL CR0, AX + ORL $0x80000000, AX + MOVL AX, CR0 + LEAL again32kzero(SB), AX + JMP* AX + + TEXT again32kzero(SB), $0 + /* breathe a sigh of relief - back in 32-bit protected mode */ + + /* switch to old stack */ + PUSHL AX /* match popl below for 8l */ + MOVL $0x7BFC, SP + POPL SP + + /* restore idt */ + MOVL idtptr(SB),IDTR + + CALL restoreregs(SB) + RET + + TEXT realmoderegs(SB), $0 + LONG $0; LONG $0; LONG $0; LONG $0 + LONG $0; LONG $0; LONG $0; LONG $0 + LONG $0; LONG $0; LONG $0; LONG $0 + LONG $0; LONG $0; LONG $0; LONG $0 + LONG $0; LONG $0; LONG $0; LONG $0 + + TEXT realmodeintr(SB), $0 + LONG $0 + [rsc] --rw-rw-r-- M 140560 glenda sys 8932 Nov 1 18:20 sys/src/boot/pc/load.c /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/load.c:548,553 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/load.c:548,557 sddetach(); consdrain(); + + splhi(); + trapdisable(); + /* * This is where to push things on the stack to * boot *BSD systems, e.g. [rsc] --rw-rw-r-- M 140560 glenda sys 3371 Nov 1 18:20 sys/src/boot/pc/mem.h /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/mem.h:6,17 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/mem.h:6,17 * Sizes */ #define BI2BY 8 /* bits per byte */ - #define BI2WD 32 /* bits per word */ + #define BI2WD 32 /* bits per word */ #define BY2WD 4 /* bytes per word */ #define BY2PG 4096 /* bytes per page */ #define WD2PG (BY2PG/BY2WD) /* words per page */ #define PGSHIFT 12 /* log(BY2PG) */ - #define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1)) + #define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1)) #define MAXMACH 1 /* max # cpus system can run */ /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/mem.h:102,112 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/mem.h:102,112 */ #define PTEVALID (1<<0) #define PTEUNCACHED 0 /* everything is uncached */ - #define PTEWRITE (1<<1) + #define PTEWRITE (1<<1) #define PTERONLY (0<<1) #define PTEKERNEL (0<<2) #define PTEUSER (1<<2) - #define PTESIZE (1<<7) + #define PTESIZE (1<<7) /* * flag register bits that we care about [rsc] --rw-rw-r-- M 140560 glenda sys 7501 Nov 1 18:20 sys/src/boot/pc/trap.c /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/trap.c:99,104 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/trap.c:99,119 } } + void + trapdisable(void) + { + outb(Int0aux, 0xFF); + outb(Int1aux, 0xFF); + } + + void + trapenable(void) + { + outb(Int0aux, int0mask); + outb(Int1aux, int1mask); + } + + /* * set up the interrupt/trap gates */ /n/sourcesdump/2005/1101/plan9/sys/src/boot/pc/trap.c:298,301 - /n/sourcesdump/2005/1102/plan9/sys/src/boot/pc/trap.c:313,331 (*h->r)(ur, h->arg); h = h->next; } while(h); + } + + void + realmode(int intr, Ureg *ureg) + { + extern void realmode0(void); /* in l.s */ + extern int realmodeintr; + extern Ureg realmoderegs; + + realmoderegs = *ureg; + realmodeintr = intr; + trapdisable(); + realmode0(); + trapenable(); + *ureg = realmoderegs; }