2 * Memory and machine-specific definitions. Used in C and assembler.
8 #define BI2BY 8 /* bits per byte */
9 #define BI2WD 32 /* bits per word */
10 #define BY2WD 4 /* bytes per word */
11 #define BY2PG 4096 /* bytes per page */
12 #define WD2PG (BY2PG/BY2WD) /* words per page */
13 #define PGSHIFT 12 /* log(BY2PG) */
14 #define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
16 #define MAXMACH 1 /* max # cpus system can run */
21 #define HZ (20) /* clock frequency */
22 #define MS2HZ (1000/HZ) /* millisec per clock tick */
23 #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
24 #define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
25 #define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
28 * Fundamental addresses
35 * Kernel is at 2GB-4GB
37 * To avoid an extra page map, both the user stack (USTKTOP) and
38 * the temporary user stack (TSTKTOP) should be in the the same
41 #define UZERO 0 /* base of user address space */
42 #define UTZERO (UZERO+BY2PG) /* first address in user text */
43 #define KZERO 0x80000000 /* base of kernel address space */
44 #define KTZERO KZERO /* first address in kernel text */
45 #define USERADDR 0xC0000000 /* struct User */
46 #define UREGADDR (USERADDR+BY2PG-4*19)
47 #define TSTKTOP USERADDR /* end of new stack in sysexec */
49 #define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
50 #define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */
51 #define ROMBIOS (KZERO|0xF0000)
55 #define isphys(x) (((ulong)x)&KZERO)
58 * known 80386 segments (in GDT) and their selectors
60 #define NULLSEG 0 /* null segment */
61 #define KDSEG 1 /* kernel data/stack */
62 #define KESEG 2 /* kernel executable */
63 #define UDSEG 3 /* user data/stack */
64 #define UESEG 4 /* user executable */
65 #define TSSSEG 5 /* task segment */
67 #define SELGDT (0<<3) /* selector is in gdt */
68 #define SELLDT (1<<3) /* selector is in ldt */
70 #define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
72 #define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
73 #define KESEL SELECTOR(KESEG, SELGDT, 0)
74 #define KDSEL SELECTOR(KDSEG, SELGDT, 0)
75 #define UESEL SELECTOR(UESEG, SELGDT, 3)
76 #define UDSEL SELECTOR(UDSEG, SELGDT, 3)
77 #define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
80 * fields in segment descriptors
82 #define SEGDATA (0x10<<8) /* data/stack segment */
83 #define SEGEXEC (0x18<<8) /* executable segment */
84 #define SEGTSS (0x9<<8) /* TSS segment */
85 #define SEGCG (0x0C<<8) /* call gate */
86 #define SEGIG (0x0E<<8) /* interrupt gate */
87 #define SEGTG (0x0F<<8) /* task gate */
88 #define SEGTYPE (0x1F<<8)
90 #define SEGP (1<<15) /* segment present */
91 #define SEGPL(x) ((x)<<13) /* priority level */
92 #define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
93 #define SEGG (1<<23) /* granularity 1==4k (for other) */
94 #define SEGE (1<<10) /* expand down */
95 #define SEGW (1<<9) /* writable (for data/stack) */
96 #define SEGR (1<<9) /* readable (for code) */
97 #define SEGD (1<<22) /* default 1==32bit (for code) */
102 #define PTEMAPMEM (1024*1024) /* ??? */
103 #define SEGMAPSIZE 16 /* ??? */
104 #define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */
105 #define PPN(x) ((x)&~(BY2PG-1))
110 #define PTEVALID (1<<0)
111 #define PTEUNCACHED 0 /* everything is uncached */
112 #define PTEWRITE (1<<1)
113 #define PTERONLY (0<<1)
114 #define PTEKERNEL (0<<2)
115 #define PTEUSER (1<<2)
118 * flag register bits that we care about
122 #define OP16 BYTE $0x66
125 * about to walk all over ms/dos - turn off interrupts
133 * This part of l.s is used only in the boot kernel.
134 * It assumes that we are in real address mode, i.e.,
135 * that we look like an 8086.
138 * relocate everything to a half meg and jump there
139 * - looks wierd because it is being assembled by a 32 bit
140 * assembler for a 16 bit world
150 /* JMPFAR 0X8000:$lowcore(SB) /**/
158 * now that we're in low core, update the DS
164 * goto protected mode
166 /* MOVL tgdtptr(SB),GDTR /**/
176 * clear prefetch queue (wierd code to avoid optimizations)
186 /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
189 WORD $SELECTOR(1, SELGDT, 0)
196 /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
199 LONG $mode32bit-KZERO(SB)
200 WORD $SELECTOR(2, SELGDT, 0)
202 TEXT mode32bit(SB),$0
209 LEAL edata-KZERO(SB),SI
214 LEAL end-KZERO(SB),CX
220 * make a bottom level page table page that maps the first
221 * 16 meg of physical memory
223 LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
224 ADDL $(BY2PG-1),AX /* must be page aligned */
225 ANDL $(~(BY2PG-1)),AX /* ... */
226 MOVL $(4*1024),CX /* pte's per page */
227 MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
230 SUBL $(1<<PGSHIFT),BX
234 * make a top level page table page that maps the first
235 * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
239 ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
241 MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
244 MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
247 MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
250 MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
253 * point processor to top level page & turn on paging
258 ANDL $~(0x8|0x2),AX /* TS=0, MP=0 */
262 * use a jump to an absolute location to get the PC into
276 ADDL $(MACHSIZE-4),SP /* start stack under machine struct */
291 GLOBL mach0+0(SB), $MACHSIZE
294 GLOBL tpt(SB), $(BY2PG*6)
297 * gdt to get us to 32-bit/segmented/unpaged mode
301 /* null descriptor */
305 /* data segment descriptor for 4 gigabytes (PL 0) */
307 LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
309 /* exec segment descriptor for 4 gigabytes (PL 0) */
311 LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
314 * pointer to initial gdt
342 * input a string of shorts from a port
352 * output a string of shorts to a port
358 CLD; REP; OP16; OUTSL
371 * routines to load/read various system registers
374 TEXT putidt(SB),$0 /* interrupt descriptor table */
383 TEXT putgdt(SB),$0 /* global descriptor table */
391 TEXT putcr3(SB),$0 /* top level page table pointer */
396 TEXT puttr(SB),$0 /* task register */
401 TEXT getcr0(SB),$0 /* coprocessor bits */
405 TEXT getcr2(SB),$0 /* fault address */
412 ORL $0x4,AX /* EM=1 */;\
417 ANDL $~0x4,AX /* EM=0 */;\
420 TEXT fpoff(SB),$0 /* turn off floating point */
424 TEXT fpinit(SB),$0 /* turn on & init the floating point */
429 FLDCW 0(SP) /* ignore underflow/precision, signal others */
434 TEXT fpsave(SB),$0 /* save floating point state and turn off */
441 TEXT fprestore(SB),$0 /* turn on floating point and restore regs */
448 TEXT fpstatus(SB),$0 /* get floating point status */
608 ADDL $8,SP /* error code and trap type */
629 ADDL $8,SP /* error code and trap type */
633 * interrupt level is interrupts on or off
654 * do nothing whatsoever till interrupt happens
661 * label consists of a stack pointer and a PC
663 TEXT gotolabel(SB),$0
665 MOVL 0(AX),SP /* restore sp */
666 MOVL 4(AX),AX /* put return pc on the stack */
668 MOVL $1,AX /* return 1 */
673 MOVL SP,0(AX) /* store sp */
674 MOVL 0(SP),BX /* store return pc */
676 MOVL $0,AX /* return 0 */
680 * Used to get to the first process.
681 * Set up an interrupt return frame and IRET to user level.
684 PUSHL $(UDSEL) /* old ss */
685 PUSHL $(USTKTOP) /* old sp */
686 PUSHFL /* old flags */
687 PUSHL $(UESEL) /* old cs */
688 PUSHL $(UTZERO+32) /* old pc */
697 * set configuration register