| git.druid.rocks | index | druid520 | kaboom | src/ | kernel/ | gdt_asm.s |
src/kernel/gdt_asm.s
/*
* lgdt plus the mandatory segment-register reload. `lgdt` alone only
* changes what the gdtr points at -- it does not refresh the hidden
* descriptor-cache state already loaded into cs/ds/es/ss/fs/gs, so
* every segment register has to be explicitly reloaded afterward or
* the cpu keeps using the OLD table's cached descriptor for whatever
* it doesn't reload. data segments reload with a plain mov; cs can't
* be loaded with mov at all (no such instruction) -- the standard
* trick is a far return: push the target selector and a return
* address, then lretq pops both and does a real far jump into the new
* cs.
*/
.section .text
.global load_gdt
.type load_gdt, @function
load_gdt:
lgdt (%rdi)
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
pushq $0x08
leaq 1f(%rip), %rax
pushq %rax
lretq
1:
ret