155e95b16Srtm /* 255e95b16Srtm * This file contains definitions for the x86 memory management unit (MMU), 355e95b16Srtm * including paging- and segmentation-related data structures and constants, 455e95b16Srtm * the %cr0, %cr4, and %eflags registers, and traps. 555e95b16Srtm */ 655e95b16Srtm 755e95b16Srtm /* 8564f787eSrsc * Register flags and fundamental constants. 955e95b16Srtm */ 1055e95b16Srtm 1155e95b16Srtm #define PGSIZE 4096 // bytes mapped by a page 1255e95b16Srtm 1355e95b16Srtm // Eflags register 1455e95b16Srtm #define FL_CF 0x00000001 // Carry Flag 1555e95b16Srtm #define FL_PF 0x00000004 // Parity Flag 1655e95b16Srtm #define FL_AF 0x00000010 // Auxiliary carry Flag 1755e95b16Srtm #define FL_ZF 0x00000040 // Zero Flag 1855e95b16Srtm #define FL_SF 0x00000080 // Sign Flag 1955e95b16Srtm #define FL_TF 0x00000100 // Trap Flag 2055e95b16Srtm #define FL_IF 0x00000200 // Interrupt Flag 2155e95b16Srtm #define FL_DF 0x00000400 // Direction Flag 2255e95b16Srtm #define FL_OF 0x00000800 // Overflow Flag 2355e95b16Srtm #define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask 2455e95b16Srtm #define FL_IOPL_0 0x00000000 // IOPL == 0 2555e95b16Srtm #define FL_IOPL_1 0x00001000 // IOPL == 1 2655e95b16Srtm #define FL_IOPL_2 0x00002000 // IOPL == 2 2755e95b16Srtm #define FL_IOPL_3 0x00003000 // IOPL == 3 2855e95b16Srtm #define FL_NT 0x00004000 // Nested Task 2955e95b16Srtm #define FL_RF 0x00010000 // Resume Flag 3055e95b16Srtm #define FL_VM 0x00020000 // Virtual 8086 mode 3155e95b16Srtm #define FL_AC 0x00040000 // Alignment Check 3255e95b16Srtm #define FL_VIF 0x00080000 // Virtual Interrupt Flag 3355e95b16Srtm #define FL_VIP 0x00100000 // Virtual Interrupt Pending 3455e95b16Srtm #define FL_ID 0x00200000 // ID flag 3555e95b16Srtm 3655e95b16Srtm // Page fault error codes 3755e95b16Srtm #define FEC_PR 0x1 // Page fault caused by protection violation 3855e95b16Srtm #define FEC_WR 0x2 // Page fault caused by a write 3955e95b16Srtm #define FEC_U 0x4 // Page fault occured while in user mode 4055e95b16Srtm 4155e95b16Srtm /* 4255e95b16Srtm * 43564f787eSrsc * Segmentation data structures and constants. 4455e95b16Srtm * 4555e95b16Srtm */ 4655e95b16Srtm 4755e95b16Srtm #ifdef __ASSEMBLER__ 4855e95b16Srtm 4955e95b16Srtm /* 5055e95b16Srtm * Macros to build GDT entries in assembly. 5155e95b16Srtm */ 5255e95b16Srtm #define SEG_NULL \ 5355e95b16Srtm .word 0, 0; \ 5455e95b16Srtm .byte 0, 0, 0, 0 5555e95b16Srtm #define SEG(type,base,lim) \ 5655e95b16Srtm .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 5755e95b16Srtm .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 5855e95b16Srtm (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 5955e95b16Srtm 6055e95b16Srtm #else // not __ASSEMBLER__ 6155e95b16Srtm 6255e95b16Srtm // Segment Descriptors 63b5f17007Srsc struct segdesc { 64b5ee5165Srsc uint lim_15_0 : 16; // Low bits of segment limit 65b5ee5165Srsc uint base_15_0 : 16; // Low bits of segment base address 66b5ee5165Srsc uint base_23_16 : 8; // Middle bits of segment base address 67b5ee5165Srsc uint type : 4; // Segment type (see STS_ constants) 68b5ee5165Srsc uint s : 1; // 0 = system, 1 = application 69b5ee5165Srsc uint dpl : 2; // Descriptor Privilege Level 70b5ee5165Srsc uint p : 1; // Present 71b5ee5165Srsc uint lim_19_16 : 4; // High bits of segment limit 72b5ee5165Srsc uint avl : 1; // Unused (available for software use) 73b5ee5165Srsc uint rsv1 : 1; // Reserved 74b5ee5165Srsc uint db : 1; // 0 = 16-bit segment, 1 = 32-bit segment 75b5ee5165Srsc uint g : 1; // Granularity: limit scaled by 4K when set 76b5ee5165Srsc uint base_31_24 : 8; // High bits of segment base address 7755e95b16Srtm }; 7855e95b16Srtm // Null segment 79b5f17007Srsc #define SEG_NULL (struct segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 8055e95b16Srtm // Segment that is loadable but faults when used 81b5f17007Srsc #define SEG_FAULT (struct segdesc){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 } 8255e95b16Srtm // Normal segment 83b5f17007Srsc #define SEG(type, base, lim, dpl) (struct segdesc) \ 8455e95b16Srtm { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ 85b5ee5165Srsc type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1, \ 86b5ee5165Srsc (uint) (base) >> 24 } 87b5f17007Srsc #define SEG16(type, base, lim, dpl) (struct segdesc) \ 8855e95b16Srtm { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ 89b5ee5165Srsc type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0, \ 90b5ee5165Srsc (uint) (base) >> 24 } 9155e95b16Srtm 9255e95b16Srtm #endif /* !__ASSEMBLER__ */ 9355e95b16Srtm 9455e95b16Srtm // Application segment type bits 9555e95b16Srtm #define STA_X 0x8 // Executable segment 9655e95b16Srtm #define STA_E 0x4 // Expand down (non-executable segments) 9755e95b16Srtm #define STA_C 0x4 // Conforming code segment (executable only) 9855e95b16Srtm #define STA_W 0x2 // Writeable (non-executable segments) 9955e95b16Srtm #define STA_R 0x2 // Readable (executable segments) 10055e95b16Srtm #define STA_A 0x1 // Accessed 10155e95b16Srtm 10255e95b16Srtm // System segment type bits 10355e95b16Srtm #define STS_T16A 0x1 // Available 16-bit TSS 10455e95b16Srtm #define STS_LDT 0x2 // Local Descriptor Table 10555e95b16Srtm #define STS_T16B 0x3 // Busy 16-bit TSS 10655e95b16Srtm #define STS_CG16 0x4 // 16-bit Call Gate 10755e95b16Srtm #define STS_TG 0x5 // Task Gate / Coum Transmitions 10855e95b16Srtm #define STS_IG16 0x6 // 16-bit Interrupt Gate 10955e95b16Srtm #define STS_TG16 0x7 // 16-bit Trap Gate 11055e95b16Srtm #define STS_T32A 0x9 // Available 32-bit TSS 11155e95b16Srtm #define STS_T32B 0xB // Busy 32-bit TSS 11255e95b16Srtm #define STS_CG32 0xC // 32-bit Call Gate 11355e95b16Srtm #define STS_IG32 0xE // 32-bit Interrupt Gate 11455e95b16Srtm #define STS_TG32 0xF // 32-bit Trap Gate 11555e95b16Srtm 11655e95b16Srtm 11755e95b16Srtm /* 11855e95b16Srtm * 119564f787eSrsc * Traps. 12055e95b16Srtm * 12155e95b16Srtm */ 12255e95b16Srtm 12355e95b16Srtm #ifndef __ASSEMBLER__ 12455e95b16Srtm 12555e95b16Srtm // Task state segment format (as described by the Pentium architecture book) 126b5f17007Srsc struct taskstate { 12729270816Srtm uint link; // Old ts selector 128*11a9947fSrtm uint esp0; // Stack pointers and segment selectors 12929270816Srtm ushort ss0; // after an increase in privilege level 13029270816Srtm ushort padding1; 13129270816Srtm uint * esp1; 13229270816Srtm ushort ss1; 13329270816Srtm ushort padding2; 13429270816Srtm uint * esp2; 13529270816Srtm ushort ss2; 13629270816Srtm ushort padding3; 13729270816Srtm void * cr3; // Page directory base 13829270816Srtm uint * eip; // Saved state from last task switch 13929270816Srtm uint eflags; 14029270816Srtm uint eax; // More saved state (registers) 14129270816Srtm uint ecx; 14229270816Srtm uint edx; 14329270816Srtm uint ebx; 14429270816Srtm uint * esp; 14529270816Srtm uint * ebp; 14629270816Srtm uint esi; 14729270816Srtm uint edi; 14829270816Srtm ushort es; // Even more saved state (segment selectors) 14929270816Srtm ushort padding4; 15029270816Srtm ushort cs; 15129270816Srtm ushort padding5; 15229270816Srtm ushort ss; 15329270816Srtm ushort padding6; 15429270816Srtm ushort ds; 15529270816Srtm ushort padding7; 15629270816Srtm ushort fs; 15729270816Srtm ushort padding8; 15829270816Srtm ushort gs; 15929270816Srtm ushort padding9; 16029270816Srtm ushort ldt; 16129270816Srtm ushort padding10; 16229270816Srtm ushort t; // Trap on task switch 16329270816Srtm ushort iomb; // I/O map base address 16455e95b16Srtm }; 16555e95b16Srtm 16655e95b16Srtm // Gate descriptors for interrupts and traps 167b5f17007Srsc struct gatedesc { 168b5ee5165Srsc uint off_15_0 : 16; // low 16 bits of offset in segment 169b5ee5165Srsc uint ss : 16; // segment selector 170b5ee5165Srsc uint args : 5; // # args, 0 for interrupt/trap gates 171b5ee5165Srsc uint rsv1 : 3; // reserved(should be zero I guess) 172b5ee5165Srsc uint type : 4; // type(STS_{TG,IG32,TG32}) 173b5ee5165Srsc uint s : 1; // must be 0 (system) 174b5ee5165Srsc uint dpl : 2; // descriptor(meaning new) privilege level 175b5ee5165Srsc uint p : 1; // Present 176b5ee5165Srsc uint off_31_16 : 16; // high bits of offset in segment 17755e95b16Srtm }; 17855e95b16Srtm 17955e95b16Srtm // Set up a normal interrupt/trap gate descriptor. 18055e95b16Srtm // - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate. 18155e95b16Srtm // - sel: Code segment selector for interrupt/trap handler 18255e95b16Srtm // - off: Offset in code segment for interrupt/trap handler 18355e95b16Srtm // - dpl: Descriptor Privilege Level - 18455e95b16Srtm // the privilege level required for software to invoke 18555e95b16Srtm // this interrupt/trap gate explicitly using an int instruction. 186ef2bd07aSrsc #define SETGATE(gate, istrap, sel, off, d) \ 18755e95b16Srtm { \ 18829270816Srtm (gate).off_15_0 = (uint) (off) & 0xffff; \ 189ef2bd07aSrsc (gate).ss = (sel); \ 190ef2bd07aSrsc (gate).args = 0; \ 191ef2bd07aSrsc (gate).rsv1 = 0; \ 192ef2bd07aSrsc (gate).type = (istrap) ? STS_TG32 : STS_IG32; \ 193ef2bd07aSrsc (gate).s = 0; \ 194ef2bd07aSrsc (gate).dpl = (d); \ 195ef2bd07aSrsc (gate).p = 1; \ 19629270816Srtm (gate).off_31_16 = (uint) (off) >> 16; \ 19755e95b16Srtm } 19855e95b16Srtm 19955e95b16Srtm // Set up a call gate descriptor. 200ef2bd07aSrsc #define SETCALLGATE(gate, ss, off, d) \ 20155e95b16Srtm { \ 20229270816Srtm (gate).off_15_0 = (uint) (off) & 0xffff; \ 203ef2bd07aSrsc (gate).ss = (ss); \ 204ef2bd07aSrsc (gate).args = 0; \ 205ef2bd07aSrsc (gate).rsv1 = 0; \ 206ef2bd07aSrsc (gate).type = STS_CG32; \ 207ef2bd07aSrsc (gate).s = 0; \ 208ef2bd07aSrsc (gate).dpl = (d); \ 209ef2bd07aSrsc (gate).p = 1; \ 21029270816Srtm (gate).off_31_16 = (uint) (off) >> 16; \ 21155e95b16Srtm } 21255e95b16Srtm 21355e95b16Srtm #endif /* !__ASSEMBLER__ */ 21455e95b16Srtm 215