📄 l.s
字号:
/* * Memory and machine-specific definitions. Used in C and assembler. *//* * Sizes */#define BI2BY 8 /* bits per byte */#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 MAXMACH 1 /* max # cpus system can run *//* * Time */#define HZ (20) /* clock frequency */#define MS2HZ (1000/HZ) /* millisec per clock tick */#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks *//* * Fundamental addresses *//* * Address spaces * * User is at 0-2GB * Kernel is at 2GB-4GB * * To avoid an extra page map, both the user stack (USTKTOP) and * the temporary user stack (TSTKTOP) should be in the the same * 4 meg. */#define UZERO 0 /* base of user address space */#define UTZERO (UZERO+BY2PG) /* first address in user text */#define KZERO 0x80000000 /* base of kernel address space */#define KTZERO KZERO /* first address in kernel text */#define USERADDR 0xC0000000 /* struct User */#define UREGADDR (USERADDR+BY2PG-4*19) #define TSTKTOP USERADDR /* end of new stack in sysexec */#define TSTKSIZ 10#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */#define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */#define ROMBIOS (KZERO|0xF0000)#define MACHSIZE 4096#define isphys(x) (((ulong)x)&KZERO)/* * known 80386 segments (in GDT) and their selectors */#define NULLSEG 0 /* null segment */#define KDSEG 1 /* kernel data/stack */#define KESEG 2 /* kernel executable */ #define UDSEG 3 /* user data/stack */#define UESEG 4 /* user executable */#define TSSSEG 5 /* task segment */#define SELGDT (0<<3) /* selector is in gdt */#define SELLDT (1<<3) /* selector is in ldt */#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)#define KESEL SELECTOR(KESEG, SELGDT, 0)#define KDSEL SELECTOR(KDSEG, SELGDT, 0)#define UESEL SELECTOR(UESEG, SELGDT, 3)#define UDSEL SELECTOR(UDSEG, SELGDT, 3)#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)/* * fields in segment descriptors */#define SEGDATA (0x10<<8) /* data/stack segment */#define SEGEXEC (0x18<<8) /* executable segment */#define SEGTSS (0x9<<8) /* TSS segment */#define SEGCG (0x0C<<8) /* call gate */#define SEGIG (0x0E<<8) /* interrupt gate */#define SEGTG (0x0F<<8) /* task gate */#define SEGTYPE (0x1F<<8)#define SEGP (1<<15) /* segment present */#define SEGPL(x) ((x)<<13) /* priority level */#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */#define SEGG (1<<23) /* granularity 1==4k (for other) */#define SEGE (1<<10) /* expand down */#define SEGW (1<<9) /* writable (for data/stack) */#define SEGR (1<<9) /* readable (for code) */#define SEGD (1<<22) /* default 1==32bit (for code) *//* * virtual MMU */#define PTEMAPMEM (1024*1024) /* ??? */ #define SEGMAPSIZE 16 /* ??? */#define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */#define PPN(x) ((x)&~(BY2PG-1))/* * physical MMU */#define PTEVALID (1<<0)#define PTEUNCACHED 0 /* everything is uncached */#define PTEWRITE (1<<1)#define PTERONLY (0<<1)#define PTEKERNEL (0<<2)#define PTEUSER (1<<2)/* * flag register bits that we care about */#define IFLAG 0x200#define OP16 BYTE $0x66/* * about to walk all over ms/dos - turn off interrupts */TEXT origin(SB),$0 CLI#ifdef BOOT/* * This part of l.s is used only in the boot kernel. * It assumes that we are in real address mode, i.e., * that we look like an 8086. *//* * relocate everything to a half meg and jump there * - looks wierd because it is being assembled by a 32 bit * assembler for a 16 bit world */ MOVL $0,BX INCL BX SHLL $15,BX MOVL BX,CX MOVW BX,ES MOVL $0,SI MOVL SI,DI CLD; REP; MOVSL/* JMPFAR 0X8000:$lowcore(SB) /**/ BYTE $0xEA WORD $lowcore(SB) WORD $0X8000TEXT lowcore(SB),$0/* * now that we're in low core, update the DS */ MOVW BX,DS/* * goto protected mode *//* MOVL tgdtptr(SB),GDTR /**/ BYTE $0x0f BYTE $0x01 BYTE $0x16 WORD $tgdtptr(SB) MOVL CR0,AX ORL $1,AX MOVL AX,CR0/* * clear prefetch queue (wierd code to avoid optimizations) */ CLC JCC flush MOVL AX,AXflush:/* * set all segs *//* MOVW $SELECTOR(1, SELGDT, 0),AX /**/ BYTE $0xc7 BYTE $0xc0 WORD $SELECTOR(1, SELGDT, 0) MOVW AX,DS MOVW AX,SS MOVW AX,ES MOVW AX,FS MOVW AX,GS/* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/ BYTE $0x66 BYTE $0xEA LONG $mode32bit-KZERO(SB) WORD $SELECTOR(2, SELGDT, 0)TEXT mode32bit(SB),$0#endif BOOT /* * 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 $(4*1024),CX /* pte's per page */ MOVL $((((4*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 $(4*BY2PG),AX ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX MOVL BX,0(AX) MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX) ADDL $BY2PG,BX MOVL BX,4(AX) MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX) ADDL $BY2PG,BX MOVL BX,8(AX) MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX) ADDL $BY2PG,BX MOVL BX,12(AX) MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX) /* * point processor to top level page & turn on paging */ MOVL AX,CR3 MOVL CR0,AX ORL $0X80000000,AX ANDL $~(0x8|0x2),AX /* 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*6)/* * 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/* * output a byte */TEXT outb(SB),$0 MOVL p+0(FP),DX MOVL b+4(FP),AX OUTB 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/* * 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/* * test and set */TEXT tas(SB),$0 MOVL $0xdeadead,AX MOVL l+0(FP),BX XCHGL AX,(BX) 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 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 $0x4,AX /* EM=1 */;\ MOVL AX,CR0#define FPON\ MOVL CR0,AX;\ ANDL $~0x4,AX /* EM=0 */;\ MOVL AX,CR0 TEXT fpoff(SB),$0 /* turn off floating point */ FPOFF RETTEXT fpinit(SB),$0 /* turn on & init the floating point */ FPON FINIT WAIT PUSHW $0x0330 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 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 $16 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 POPL GS POPL FS POPL ES POPL DS 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 POPL GS POPL FS POPL ES POPL DS 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 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 0(AX),SP /* restore sp */ MOVL 4(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,0(AX) /* store sp */ MOVL 0(SP),BX /* store return pc */ MOVL BX,4(AX) MOVL $0,AX /* return 0 */ RET/* * Used to get to the first process. * Set up an interrupt return frame and IRET to user level. */TEXT touser(SB),$0 PUSHL $(UDSEL) /* old ss */ PUSHL $(USTKTOP) /* old sp */ PUSHFL /* old flags */ PUSHL $(UESEL) /* old cs */ PUSHL $(UTZERO+32) /* old pc */ MOVL $(UDSEL),AX MOVW AX,DS MOVW AX,ES MOVW AX,GS MOVW AX,FS IRETL/* * set configuration register */TEXT config(SB),$0 MOVL l+0(FP),AX MOVL $0x3F3,DX OUTB OUTB RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -