#include "/sys/src/boot/pc/x16.h" #include "mem.h" #define KB 1024 #define MB (1024*1024) #define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */ #define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */ #define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */ #define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */ TEXT _start32v(SB),$0 CLI MOVL $edata(SB), DI XORL AX, AX MOVL $end(SB), CX SUBL DI, CX /* end-edata bytes */ SHRL $2, CX /* end-edata doublewords */ CLD REP; STOSL /* clear BSS */ MOVL CR3, AX /* 1+LOWPTEPAGES zeroed pages at (AX): pdb, pte */ ADDL $KZERO, AX /* VA of PDB */ MOVL AX, mach0pdb(SB) ADDL $((1+LOWPTEPAGES)*BY2PG), AX /* skip pdb & n pte */ MOVL AX, memstart(SB) /* start of available memory */ /* 2 zeroed pages at CPU0MACH: mach, gdt */ MOVL $CPU0MACH, AX MOVL AX, mach0m(SB) /* ... VA of Mach */ MOVL AX, m(SB) /* initialise global Mach pointer */ MOVL $0, 0(AX) /* initialise m->machno */ ADDL $MACHSIZE, AX MOVL AX, SP /* switch to new stack in Mach */ MOVL $CPU0GDT, mach0gdt(SB) MOVL $0x240000, AX /* try to set Id|Ac in EFLAGS */ PUSHL AX POPFL PUSHFL /* retrieve EFLAGS -> BX */ POPL BX MOVL $0, AX /* clear Id|Ac, EFLAGS initialised */ PUSHL AX POPFL PUSHFL /* retrieve EFLAGS -> AX */ XORL BX, (SP) /* togglable bits */ CALL main(SB) /* * Park a processor. Should never fall through a return from main to here, * should only be called by application processors when shutting down. */ TEXT idle(SB), $0 _idle: STI HLT JMP _idle TEXT hlt(SB), $0 STI HLT RET #ifdef UNUSED /* */ TEXT _warp9o(SB), $0 MOVL entry+0(FP), CX MOVL multibootheader-KZERO(SB), BX /* multiboot data pointer */ MOVL $0x2badb002, AX /* multiboot magic */ CLI JMP* CX JMP _idle /* * Macro for calculating offset within the page directory base. * Note that this is assembler-specific hence the '<<2'. */ #define PDO(a) (((((a))>>22) & 0x03FF)<<2) /* */ TEXT _warp9(SB), $0 CLI MOVL entry+0(FP), BP MOVL CR3, CX /* load address of PDB */ ADDL $KZERO, CX MOVL PDO(KZERO)(CX), DX /* double-map KZERO at 0 */ MOVL DX, PDO(0)(CX) MOVL CR3, CX MOVL CX, CR3 /* load and flush the mmu */ MOVL $_start32id<>-KZERO(SB), AX JMP* AX /* jump to identity-map */ TEXT _start32id<>(SB), $0 MOVL CR0, DX /* turn off paging */ ANDL $~PG, DX MOVL $_stop32pg<>-KZERO(SB), AX MOVL DX, CR0 JMP* AX /* forward into the past */ TEXT _stop32pg<>(SB), $0 MOVL multibootheader-KZERO(SB), BX /* multiboot data pointer */ MOVL $0x2badb002, AX /* multiboot magic */ JMP* BP JMP _idle #endif /* * input a byte */ TEXT inb(SB),$0 MOVL p+0(FP),DX XORL AX,AX INB RET /* * input a short from a port */ TEXT ins(SB), $0 MOVL p+0(FP), DX XORL AX, AX OPSIZE; INL RET /* * input a long from a port */ TEXT inl(SB), $0 MOVL p+0(FP), DX XORL AX, AX INL RET /* * output a byte */ TEXT outb(SB),$0 MOVL p+0(FP),DX MOVL b+4(FP),AX OUTB RET /* * output a short to a port */ TEXT outs(SB), $0 MOVL p+0(FP), DX MOVL s+4(FP), AX OPSIZE; OUTL RET /* * output a long to a port */ TEXT outl(SB), $0 MOVL p+0(FP), DX MOVL s+4(FP), AX OUTL RET /* * input a string of bytes from a port */ TEXT insb(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),DI MOVL c+8(FP),CX CLD; REP; INSB RET /* * input a string of shorts from a port */ TEXT inss(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),DI MOVL c+8(FP),CX CLD REP; OPSIZE; INSL RET /* * output a string of bytes to a port */ TEXT outsb(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),SI MOVL c+8(FP),CX CLD; REP; OUTSB RET /* * output a string of shorts to a port */ TEXT outss(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),SI MOVL c+8(FP),CX CLD REP; OPSIZE; OUTSL RET /* * input a string of longs from a port */ TEXT insl(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),DI MOVL c+8(FP),CX CLD; REP; INSL RET /* * output a string of longs to a port */ TEXT outsl(SB),$0 MOVL p+0(FP),DX MOVL a+4(FP),SI MOVL c+8(FP),CX CLD; REP; OUTSL RET /* * routines to load/read various system registers */ GLOBL idtptr(SB),$6 TEXT putidt(SB),$0 /* interrupt descriptor table */ MOVL t+0(FP),AX MOVL AX,idtptr+2(SB) MOVL l+4(FP),AX MOVW AX,idtptr(SB) MOVL idtptr(SB),IDTR RET TEXT lgdt(SB), $0 /* GDTR - global descriptor table */ MOVL gdtptr+0(FP), AX MOVL (AX), GDTR RET TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */ MOVL idtptr+0(FP), AX MOVL (AX), IDTR RET TEXT putcr3(SB),$0 /* top level page table pointer */ MOVL t+0(FP),AX MOVL AX,CR3 RET TEXT getcr0(SB),$0 /* coprocessor bits */ MOVL CR0,AX RET TEXT getcr2(SB),$0 /* fault address */ MOVL CR2,AX RET TEXT getcr3(SB),$0 /* page directory base */ MOVL CR3,AX RET TEXT getcr4(SB), $0 /* CR4 - extensions */ MOVL CR4, AX RET TEXT putcr4(SB), $0 MOVL cr4+0(FP), AX MOVL AX, CR4 RET TEXT _cycles(SB), $0 /* time stamp counter */ RDTSC MOVL vlong+0(FP), CX /* &vlong */ MOVL AX, 0(CX) /* lo */ MOVL DX, 4(CX) /* hi */ RET TEXT rdmsr(SB), $0 /* model-specific register */ MOVL index+0(FP), CX RDMSR MOVL vlong+4(FP), CX /* &vlong */ MOVL AX, 0(CX) /* lo */ MOVL DX, 4(CX) /* hi */ RET TEXT wrmsr(SB), $0 MOVL index+0(FP), CX MOVL lo+4(FP), AX MOVL hi+8(FP), DX WRMSR RET /* * memory barriers */ TEXT mb386(SB), $0 POPL AX /* return PC */ PUSHFL PUSHL CS PUSHL AX IRETL TEXT mb586(SB), $0 XORL AX, AX CPUID RET TEXT sfence(SB), $0 BYTE $0x0f BYTE $0xae BYTE $0xf8 RET TEXT lfence(SB), $0 BYTE $0x0f BYTE $0xae BYTE $0xe8 RET TEXT mfence(SB), $0 BYTE $0x0f BYTE $0xae BYTE $0xf0 RET /* * special traps */ TEXT intr0(SB),$0 PUSHL $0 PUSHL $0 JMP intrcommon TEXT intr1(SB),$0 PUSHL $0 PUSHL $1 JMP intrcommon TEXT intr2(SB),$0 PUSHL $0 PUSHL $2 JMP intrcommon TEXT intr3(SB),$0 PUSHL $0 PUSHL $3 JMP intrcommon TEXT intr4(SB),$0 PUSHL $0 PUSHL $4 JMP intrcommon TEXT intr5(SB),$0 PUSHL $0 PUSHL $5 JMP intrcommon TEXT intr6(SB),$0 PUSHL $0 PUSHL $6 JMP intrcommon TEXT intr7(SB),$0 PUSHL $0 PUSHL $7 JMP intrcommon TEXT intr8(SB),$0 PUSHL $8 JMP intrcommon TEXT intr9(SB),$0 PUSHL $0 PUSHL $9 JMP intrcommon TEXT intr10(SB),$0 PUSHL $10 JMP intrcommon TEXT intr11(SB),$0 PUSHL $11 JMP intrcommon TEXT intr12(SB),$0 PUSHL $12 JMP intrcommon TEXT intr13(SB),$0 PUSHL $13 JMP intrcommon TEXT intr14(SB),$0 PUSHL $14 JMP intrcommon TEXT intr15(SB),$0 PUSHL $0 PUSHL $15 JMP intrcommon TEXT intr16(SB),$0 PUSHL $0 PUSHL $16 JMP intrcommon TEXT intr24(SB),$0 PUSHL $0 PUSHL $24 JMP intrcommon TEXT intr25(SB),$0 PUSHL $0 PUSHL $25 JMP intrcommon TEXT intr26(SB),$0 PUSHL $0 PUSHL $26 JMP intrcommon TEXT intr27(SB),$0 PUSHL $0 PUSHL $27 JMP intrcommon TEXT intr28(SB),$0 PUSHL $0 PUSHL $28 JMP intrcommon TEXT intr29(SB),$0 PUSHL $0 PUSHL $29 JMP intrcommon TEXT intr30(SB),$0 PUSHL $0 PUSHL $30 JMP intrcommon TEXT intr31(SB),$0 PUSHL $0 PUSHL $31 JMP intrcommon TEXT intr32(SB),$0 PUSHL $0 PUSHL $32 JMP intrcommon TEXT intr33(SB),$0 PUSHL $0 PUSHL $33 JMP intrcommon TEXT intr34(SB),$0 PUSHL $0 PUSHL $34 JMP intrcommon TEXT intr35(SB),$0 PUSHL $0 PUSHL $35 JMP intrcommon TEXT intr36(SB),$0 PUSHL $0 PUSHL $36 JMP intrcommon TEXT intr37(SB),$0 PUSHL $0 PUSHL $37 JMP intrcommon TEXT intr38(SB),$0 PUSHL $0 PUSHL $38 JMP intrcommon TEXT intr39(SB),$0 PUSHL $0 PUSHL $39 JMP intrcommon TEXT intr64(SB),$0 PUSHL $0 PUSHL $64 JMP intrcommon TEXT intrbad(SB),$0 PUSHL $0 PUSHL $0x1ff JMP intrcommon intrcommon: PUSHL DS PUSHL ES PUSHL FS PUSHL GS PUSHAL MOVL $(KDSEL),AX MOVW AX,DS MOVW AX,ES LEAL 0(SP),AX PUSHL AX CALL trap(SB) POPL AX POPAL POPL GS POPL FS POPL ES POPL DS ADDL $8,SP /* error code and trap type */ IRETL /* * interrupt level is interrupts on or off. * kprof knows that spllo to spldone is splx routines. */ TEXT spllo(SB),$0 PUSHFL POPL AX STI RET TEXT splhi(SB),$0 PUSHFL POPL AX CLI RET TEXT splx(SB),$0 MOVL s+0(FP),AX PUSHL AX POPFL RET TEXT spldone(SB), $0 RET TEXT islo(SB), $0 PUSHFL POPL AX ANDL $0x200, AX /* interrupt enable flag */ RET /* * basic timing loop to determine CPU frequency */ TEXT aamloop(SB),$0 MOVL c+0(FP),CX aaml1: AAM LOOP aaml1 RET