📄 l.s
字号:
#include "mem.h"#define OP16 BYTE $0x66#define NOP XCHGL AX,AX#define CPUID BYTE $0x0F; BYTE $0xA2 /* CPUID, argument in AX */#define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */#define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */#define RDTSC BYTE $0x0F; BYTE $0x31TEXT origin(SB),$0 CLI /* * Clear BSS */ LEAL edata-KZERO(SB),SI MOVL SI,DI ADDL $4,DI MOVL $0,AX MOVL AX,(SI) LEAL end-KZERO(SB),CX SUBL DI,CX SHRL $2,CX CLD; REP; MOVSL /* * make a bottom level page table page that maps the first * 16 meg of physical memory */ LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */ ADDL $(BY2PG-1),AX /* must be page alligned */ ANDL $(~(BY2PG-1)),AX /* ... */ MOVL $(1024),CX /* pte's per page */ MOVL $((((1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BXsetpte: MOVL BX,-4(AX)(CX*4) SUBL $(1<<PGSHIFT),BX LOOP setpte /* * make a top level page table page that maps the first * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg */ MOVL AX,BX ADDL $(BY2PG),AX ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX MOVL BX,0(AX) MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX) /* * point processor to top level page & turn on paging & make * supervisor obey the R/W bit in the page map */ MOVL AX,CR3 MOVL CR0,AX ORL $0X80010000,AX ANDL $~(0x40000000|0x20000000|0x8|0x2),AX /* CD=0, NW=0, TS=0, MP=0 */ MOVL AX,CR0 /* * use a jump to an absolute location to get the PC into * KZERO. */ LEAL tokzero(SB),AX JMP* AXTEXT tokzero(SB),$0 /* * stack and mach */ MOVL $mach0(SB),SP MOVL SP,m(SB) MOVL $0,0(SP) ADDL $(MACHSIZE-4),SP /* start stack under machine struct */ MOVL $0, u(SB) /* * clear flags */ MOVL $0,AX PUSHL AX POPFL CALL main(SB)loop: JMP loopGLOBL mach0+0(SB), $MACHSIZEGLOBL u(SB), $4GLOBL m(SB), $4GLOBL tpt(SB), $(BY2PG*3)/* * gdt to get us to 32-bit/segmented/unpaged mode */TEXT tgdt(SB),$0 /* null descriptor */ LONG $0 LONG $0 /* data segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) /* exec segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)/* * pointer to initial gdt */TEXT tgdtptr(SB),$0 WORD $(3*8) LONG $tgdt-KZERO(SB)/* * input a byte */TEXT inb(SB),$0 MOVL p+0(FP),DX XORL AX,AX INB 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/* * output a byte */TEXT outb(SB),$0 MOVL p+0(FP),DX MOVL b+4(FP),AX OUTB 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/* * input a short from a port */TEXT ins(SB), $0 MOVL p+0(FP), DX XORL AX, AX OP16; INL 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; OP16; INSL RET/* * input a long from a port */TEXT inl(SB), $0 MOVL p+0(FP), DX XORL AX, AX INL 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 short to a port */TEXT outs(SB), $0 MOVL p+0(FP), DX MOVL s+4(FP), AX OP16; OUTL 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; OP16; OUTSL RET/* * output a long to a port */TEXT outl(SB), $0 MOVL p+0(FP), DX MOVL s+4(FP), AX OUTL 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/* * test and set */TEXT tas(SB),$0 MOVL $0xdeadead,AX MOVL l+0(FP),BX XCHGL AX,(BX) RETTEXT wbflush(SB), $0 XORL AX, AX CPUID RET/* * routines to load/read various system registers */GLOBL idtptr(SB),$6TEXT 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 RETGLOBL gdtptr(SB),$6TEXT putgdt(SB),$0 /* global descriptor table */ MOVL t+0(FP),AX MOVL AX,gdtptr+2(SB) MOVL l+4(FP),AX MOVW AX,gdtptr(SB) MOVL gdtptr(SB),GDTR RETTEXT putcr3(SB),$0 /* top level page table pointer */ MOVL t+0(FP),AX MOVL AX,CR3 RETTEXT getcr4(SB), $0 /* CR4 - extensions */ MOVL CR4, AX RETTEXT putcr4(SB), $0 MOVL cr4+0(FP), AX MOVL AX, CR4 RETTEXT puttr(SB),$0 /* task register */ MOVL t+0(FP),AX MOVW AX,TASK RETTEXT getcr0(SB),$0 /* coprocessor bits */ MOVL CR0,AX RETTEXT getcr2(SB),$0 /* fault address */ MOVL CR2,AX RET#define FPOFF\ WAIT;\ MOVL CR0,AX;\ ORL $0x24,AX /* EM=1, NE=1 */;\ MOVL AX,CR0#define FPON\ MOVL CR0,AX;\ ANDL $~0x4,AX /* EM=0 */;\ MOVL AX,CR0TEXT fpoff(SB),$0 /* turn off floating point */ FPOFF RETTEXT fpinit(SB),$0 /* turn on & init the floating point */ FPON FINIT WAIT PUSHW $0x033E FLDCW 0(SP) /* ignore underflow/precision, signal others */ POPW AX WAIT RETTEXT fpsave(SB),$0 /* save floating point state and turn off */ MOVL p+0(FP),AX WAIT FSAVE 0(AX) FPOFF RETTEXT fprestore(SB),$0 /* turn on floating point and restore regs */ FPON MOVL p+0(FP),AX FRSTOR 0(AX) WAIT RETTEXT fpstatus(SB),$0 /* get floating point status */ FSTSW AX RETTEXT fpenv(SB),$0 /* save floating point environment without waiting */ MOVL p+0(FP),AX FSTENV 0(AX) RET/* * special traps */TEXT intr0(SB),$0 PUSHL $0 PUSHL $0 JMP intrcommonTEXT intr1(SB),$0 PUSHL $0 PUSHL $1 JMP intrcommonTEXT intr2(SB),$0 PUSHL $0 PUSHL $2 JMP intrcommonTEXT intr3(SB),$0 PUSHL $0 PUSHL $3 JMP intrcommonTEXT intr4(SB),$0 PUSHL $0 PUSHL $4 JMP intrcommonTEXT intr5(SB),$0 PUSHL $0 PUSHL $5 JMP intrcommonTEXT intr6(SB),$0 PUSHL $0 PUSHL $6 JMP intrcommonTEXT intr7(SB),$0 PUSHL $0 PUSHL $7 JMP intrcommonTEXT intr8(SB),$0 PUSHL $8 JMP intrscommonTEXT intr9(SB),$0 PUSHL $0 PUSHL $9 JMP intrcommonTEXT intr10(SB),$0 PUSHL $10 JMP intrscommonTEXT intr11(SB),$0 PUSHL $11 JMP intrscommonTEXT intr12(SB),$0 PUSHL $12 JMP intrscommonTEXT intr13(SB),$0 PUSHL $13 JMP intrscommonTEXT intr14(SB),$0 PUSHL $14 JMP intrscommonTEXT intr15(SB),$0 PUSHL $0 PUSHL $15 JMP intrcommonTEXT intr16(SB),$0 PUSHL $0 PUSHL $16 JMP intrcommonTEXT intr24(SB),$0 PUSHL $0 PUSHL $24 JMP intrcommonTEXT intr25(SB),$0 PUSHL $0 PUSHL $25 JMP intrcommonTEXT intr26(SB),$0 PUSHL $0 PUSHL $26 JMP intrcommonTEXT intr27(SB),$0 PUSHL $0 PUSHL $27 JMP intrcommonTEXT intr28(SB),$0 PUSHL $0 PUSHL $28 JMP intrcommonTEXT intr29(SB),$0 PUSHL $0 PUSHL $29 JMP intrcommonTEXT intr30(SB),$0 PUSHL $0 PUSHL $30 JMP intrcommonTEXT intr31(SB),$0 PUSHL $0 PUSHL $31 JMP intrcommonTEXT intr32(SB),$0 PUSHL $0 PUSHL $32 JMP intrcommonTEXT intr33(SB),$0 PUSHL $0 PUSHL $33 JMP intrcommonTEXT intr34(SB),$0 PUSHL $0 PUSHL $34 JMP intrcommonTEXT intr35(SB),$0 PUSHL $0 PUSHL $35 JMP intrcommonTEXT intr36(SB),$0 PUSHL $0 PUSHL $36 JMP intrcommonTEXT intr37(SB),$0 PUSHL $0 PUSHL $37 JMP intrcommonTEXT intr38(SB),$0 PUSHL $0 PUSHL $38 JMP intrcommonTEXT intr39(SB),$0 PUSHL $0 PUSHL $39 JMP intrcommonTEXT intr64(SB),$0 PUSHL $0 PUSHL $64 JMP intrcommonTEXT intrbad(SB),$0 PUSHL $0 PUSHL $0x1ff JMP intrcommonintrcommon: 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 NOP POPL GS POPL FS POPL ES POPL DS NOP ADDL $8,SP /* error code and trap type */ IRETLintrscommon: 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 NOP POPL GS POPL FS POPL ES POPL DS NOP ADDL $8,SP /* error code and trap type */ IRETL/* * interrupt level is interrupts on or off */TEXT spllo(SB),$0 PUSHFL POPL AX STI RETTEXT splhi(SB),$0 PUSHFL POPL AX CLI RETTEXT splx(SB),$0 MOVL s+0(FP),AX PUSHL AX POPFL RETTEXT getstatus(SB),$0 PUSHFL POPL AX RETTEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */ RDTSC MOVL vlong+0(FP), CX /* &vlong */ MOVL AX, 0(CX) /* lo */ MOVL DX, 4(CX) /* hi */ RETTEXT rdmsr(SB), $0 /* model-specific register */ MOVL index+0(FP), CX RDMSR MOVL vlong+4(FP), CX /* &vlong */ MOVL AX, (CX) /* lo */ MOVL DX, 4(CX) /* hi */ RETTEXT wrmsr(SB), $0 MOVL index+0(FP), CX MOVL lo+4(FP), AX MOVL hi+8(FP), DX WRMSR RET/* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruciton can be used * to determine CPU identity and features. First have to check if it's * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be * toggled then it's an older 486 of some kind. * * cpuid(id[], &ax, &dx); */TEXT cpuid(SB), $0 MOVL $0x240000, AX PUSHL AX POPFL /* set Id|Ac */ PUSHFL POPL BX /* retrieve value */ MOVL $0, AX PUSHL AX POPFL /* clear Id|Ac, EFLAGS initialised */ PUSHFL POPL AX /* retrieve value */ XORL BX, AX TESTL $0x040000, AX /* Ac */ JZ _cpu386 /* can't set this bit on 386 */ TESTL $0x200000, AX /* Id */ JZ _cpu486 /* can't toggle this bit on some 486 */ MOVL $0, AX CPUID MOVL id+0(FP), BP MOVL BX, 0(BP) /* "Genu" "Auth" "Cyri" */ MOVL DX, 4(BP) /* "ineI" "enti" "xIns" */ MOVL CX, 8(BP) /* "ntel" "cAMD" "tead" */ MOVL $1, AX CPUID JMP _cpuid_cpu486: MOVL $0x400, AX MOVL $0, DX JMP _cpuid_cpu386: MOVL $0x300, AX MOVL $0, DX_cpuid: MOVL ax+4(FP), BP MOVL AX, 0(BP) MOVL dx+8(FP), BP MOVL DX, 0(BP) RET/* * basic timing loop to determine CPU frequency */TEXT aamloop(SB),$0 MOVL c+0(FP),CXaaml1: AAM LOOP aaml1 RET/* * do nothing whatsoever till interrupt happens */TEXT idle(SB),$0 HLT RET/* * label consists of a stack pointer and a PC */TEXT gotolabel(SB),$0 MOVL l+0(FP),AX MOVL 4(AX),SP /* restore sp */ MOVL 0(AX),AX /* put return pc on the stack */ MOVL AX,0(SP) MOVL $1,AX /* return 1 */ RETTEXT setlabel(SB),$0 MOVL l+0(FP),AX MOVL SP,4(AX) /* store sp */ MOVL 0(SP),BX /* store return pc */ MOVL BX,0(AX) MOVL $0,AX /* return 0 */ RETTEXT famd+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FADDF a+0(FP), F0 FMOVL c+8(FP), F0 FMULDP F0, F1 FMOVL d+12(FP), F0 FDIVDP F0, F1 FMOVFP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ RETTEXT fdf+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FDIVRF a+0(FP), F0 FMOVLP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -