github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/kernel/seg_amd64.go (about) 1 package kernel 2 3 import ( 4 "unsafe" 5 6 "github.com/icexin/eggos/kernel/sys" 7 ) 8 9 const ( 10 segDplKernel = 0x00 11 segDplUser = 0x60 12 ) 13 14 const ( 15 _KCODE_IDX = 1 16 _KDATA_IDX = 2 17 _UCODE_IDX = 3 18 _UDATA_IDX = 4 19 _TSS_IDX = 5 20 ) 21 22 var ( 23 gdt [7]gdtSegDesc 24 gdtptr [10]byte 25 26 idt [256]idtSetDesc 27 idtptr [10]byte 28 29 tss [26]uint32 30 ) 31 32 type gdtSegDesc [8]byte 33 34 type idtSetDesc struct { 35 Addr1 uint16 36 Selector uint16 37 Attr uint16 38 Addr2 uint16 39 Addr3 uint32 40 Reserved uint32 41 } 42 43 //go:nosplit 44 func lgdt(gdtptr uintptr) 45 46 //go:nosplit 47 func lidt(idtptr uintptr) 48 49 //go:nosplit 50 func ltr(sel uintptr) 51 52 //go:nosplit 53 func reloadCS() 54 55 //go:nosplit 56 func setGdtCodeDesc(desc *gdtSegDesc, dpl uint8) { 57 desc[5] |= dpl | 0x99 // P=1 C=0 58 desc[6] |= 0x20 // D=0 L=1 59 } 60 61 //go:nosplit 62 func setGdtDataDesc(desc *gdtSegDesc, dpl uint8) { 63 desc[5] |= dpl | 0x92 // P=1 W=1 64 } 65 66 //go:nosplit 67 func setTssDesc(lo, hi *gdtSegDesc, addr, limit uintptr) { 68 // tss limit 0-15 69 lo[0] = byte(limit) 70 lo[1] = byte(limit >> 8) 71 // tss base 0-15 72 lo[2] = byte(addr) 73 lo[3] = byte(addr >> 8) 74 // tss base 16-23 75 lo[4] = byte(addr >> 16) 76 // type 64 bit tss, P=1 77 lo[5] = 0x89 78 // limit 16-19 and AVL=1 79 lo[6] = 0x80 | byte(limit>>16)&0x07 80 // base addr 24-31 G=0 81 lo[7] = byte(addr >> 24) 82 83 // base addr 32-63 84 *(*uint32)(unsafe.Pointer(hi)) = uint32(addr >> 32) 85 } 86 87 //go:nosplit 88 func gdtInit() { 89 // leave gdt[0] untouched 90 setGdtCodeDesc(&gdt[_KCODE_IDX], segDplKernel) 91 setGdtDataDesc(&gdt[_KDATA_IDX], segDplKernel) 92 setGdtCodeDesc(&gdt[_UCODE_IDX], segDplUser) 93 setGdtDataDesc(&gdt[_UDATA_IDX], segDplUser) 94 tssAddr := uintptr(unsafe.Pointer(&tss[0])) 95 tssLimit := uintptr(unsafe.Sizeof(tss)) - 1 96 setTssDesc(&gdt[_TSS_IDX], &gdt[_TSS_IDX+1], tssAddr, tssLimit) 97 98 limit := (*uint16)(unsafe.Pointer(&gdtptr[0])) 99 base := (*uint64)(unsafe.Pointer(&gdtptr[2])) 100 *limit = uint16(unsafe.Sizeof(gdt) - 1) 101 *base = uint64(uintptr(unsafe.Pointer(&gdt[0]))) 102 lgdt(uintptr(unsafe.Pointer(&gdtptr[0]))) 103 ltr(_TSS_IDX << 3) 104 reloadCS() 105 } 106 107 //go:nosplit 108 func setIdtDesc(desc *idtSetDesc, addr uintptr, dpl byte) { 109 desc.Addr1 = uint16(addr & 0xffff) 110 desc.Selector = 8 111 desc.Attr = 0x8e00 | uint16(dpl)<<8 // P=1 TYPE=e interrupt gate 112 desc.Addr2 = uint16(addr >> 16 & 0xffff) 113 desc.Addr3 = uint32(addr>>32) & 0xffffffff 114 } 115 116 //go:nosplit 117 func idtInit() { 118 for i := 0; i < 256; i++ { 119 setIdtDesc(&idt[i], sys.FuncPC(vectors[i]), segDplKernel) 120 } 121 setIdtDesc(&idt[0x80], sys.FuncPC(vectors[0x80]), segDplUser) 122 123 limit := (*uint16)(unsafe.Pointer(&idtptr[0])) 124 base := (*uint64)(unsafe.Pointer(&idtptr[2])) 125 *limit = uint16(unsafe.Sizeof(idt) - 1) 126 *base = uint64(uintptr(unsafe.Pointer(&idt[0]))) 127 lidt(uintptr(unsafe.Pointer(&idtptr))) 128 } 129 130 //go:nosplit 131 func setTssSP0(addr uintptr) { 132 tss[1] = uint32(addr) 133 tss[2] = uint32(addr >> 32) 134 }