diff options
Diffstat (limited to 'arch/x86_64/hal/msr.c')
| -rw-r--r-- | arch/x86_64/hal/msr.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/x86_64/hal/msr.c b/arch/x86_64/hal/msr.c new file mode 100644 index 0000000..f27e303 --- /dev/null +++ b/arch/x86_64/hal/msr.c @@ -0,0 +1,52 @@ +#include "msr.h" +#include "gdt.h" + +void +msr_read(uint32_t msr, uint32_t *lo, uint32_t *hi) +{ + __asm__ volatile("rdmsr": "=a"(*lo), "=d"(*hi): "c"(msr)); +} + +void +msr_write(uint32_t msr, uint32_t lo, uint32_t hi) +{ + __asm__ volatile("wrmsr":: "a"(lo), "c"(msr), "d"(hi)); +} + +void +msr_set_gs_base(uintptr_t gs) +{ + union msr_gs_base gs_base = { .gs = gs }; + msr_write(MSR_GS_BASE, gs_base.v[0], gs_base.v[1]); +} + +uintptr_t +msr_get_gs_base(void) +{ + union msr_gs_base gs_base; + msr_read(MSR_GS_BASE, &gs_base.v[0], &gs_base.v[1]); + return gs_base.gs; +} + +void +msr_enable_sce(void) +{ + uint32_t efer[2]; + msr_read(MSR_EFER, &efer[0], &efer[1]); + + efer[0] |= MSR_EFER_SCE; + msr_write(MSR_EFER, efer[0], efer[1]); + + union msr_star star; + star.kcs = GDT_OFFSET(GDT_KERNEL_CODE); + star.ucs = GDT_OFFSET(GDT_USER_CODE); + msr_write(MSR_STAR, star.v[0], star.v[1]); +} + +void +msr_set_lstar(void *lstar_value) +{ + union msr_lstar lstar; + lstar.rip = lstar_value; + msr_write(MSR_LSTAR, lstar.v[0], lstar.v[1]); +} |
