diff options
| author | Ada Christine <adachristine18@gmail.com> | 2022-01-13 14:23:20 +0000 |
|---|---|---|
| committer | Ada Christine <adachristine18@gmail.com> | 2022-01-13 14:23:20 +0000 |
| commit | 7b45eb843e968b787b1ec367b41c98585227dbcd (patch) | |
| tree | bc1f0c59c1e9d9e56351ccc2868538f602cd98f1 /kc | |
| parent | 6dfbb3850ac99945de12251f99867c1edff9036c (diff) | |
msr_read() and msr_write(), rudimentary syscall thing
Diffstat (limited to 'kc')
| -rw-r--r-- | kc/core/cpu.c | 201 | ||||
| -rw-r--r-- | kc/core/cpu.h | 6 |
2 files changed, 149 insertions, 58 deletions
diff --git a/kc/core/cpu.c b/kc/core/cpu.c index ed1a04e..7b3b95b 100644 --- a/kc/core/cpu.c +++ b/kc/core/cpu.c @@ -1,14 +1,24 @@ #include "cpu.h" #include "exceptions.h" +#include "kprint.h" +#include "panic.h" #include <stdint.h> #define GDT_ENTRIES 16 #define IDT_ENTRIES 256 -#define CODE_SEG_INDEX 1 -#define DATA_SEG_INDEX 2 -#define TASK_SEG_INDEX 3 +#define CODE_SUPER_SEG_INDEX 1 +#define CODE_USER_SEG_INDEX 2 +#define DATA_SEG_INDEX 3 +#define TASK_SEG_INDEX 4 + +#define MSR_EFER 0xc0000080 +#define MSR_STAR 0xc0000081 +#define MSR_LSTAR 0xc0000082 +#define MSR_CSTAR 0xc0000083 +#define MSR_SFMASK 0xc0000084 + struct dtr64 { @@ -28,7 +38,8 @@ struct segment_descriptor enum segment_descriptor_type { - CODE64_SEG, + CODE64_SUPER_SEG, + CODE64_USER_SEG, DATA_SEG, TASK64_SEG, }; @@ -65,23 +76,33 @@ static struct segment_descriptor gdt[GDT_ENTRIES]; static struct gate_descriptor idt[IDT_ENTRIES]; static struct task64_segment tss; +static void syscall_entry(void) +{ + kputs("system call\n"); + halt(); +} + static void set_gdt(int index, - uint64_t base, - uint64_t limit, - enum segment_descriptor_type type) + uint64_t base, + uint64_t limit, + enum segment_descriptor_type type) { gdt[index].limit0 = limit & 0xffff; gdt[index].base0 = base & 0xffff; gdt[index].base16 = (base >> 16) & 0xff; gdt[index].flags_limit16 = (limit >> 16) & 0xf; gdt[index].base24 = (base >> 24) & 0xff; - + switch (type) { - case CODE64_SEG: + case CODE64_SUPER_SEG: gdt[index].access = 0x9a; gdt[index].flags_limit16 |= 0xa0; break; + case CODE64_USER_SEG: + gdt[index].access = 0xfa; + gdt[index].flags_limit16 |= 0xa0; + break; case DATA_SEG: gdt[index].access = 0x92; gdt[index].flags_limit16 |= 0xc0; @@ -96,9 +117,9 @@ static void set_gdt(int index, } static void set_idt(int vec, - uint16_t selector, - uint64_t offset, - enum gate_descriptor_type type) + uint16_t selector, + uint64_t offset, + enum gate_descriptor_type type) { idt[vec].offset0 = offset & 0xffff; idt[vec].selector = selector; @@ -124,61 +145,62 @@ void set_ist(int vec, int ist_index) static void gdt_init(void) { - set_gdt(CODE_SEG_INDEX, 0, (uint64_t)-1, CODE64_SEG); + set_gdt(CODE_SUPER_SEG_INDEX, 0, (uint64_t)-1, CODE64_SUPER_SEG); + set_gdt(CODE_USER_SEG_INDEX, 0, (uint64_t)-1, CODE64_USER_SEG); set_gdt(DATA_SEG_INDEX, 0, (uint64_t)-1, DATA_SEG); set_gdt(TASK_SEG_INDEX, (uint64_t)&tss, sizeof(tss) - 1, TASK64_SEG); struct dtr64 gdtr = {sizeof(gdt) - 1, (uint64_t)&gdt}; __asm__ volatile - ( - // can't have interrupts during GDT reload - // but don't re-enable interrupts if they were already disabled - "pushf\n" - "cli\n" - "lgdt %0\n" - "mov %w2, %%ds\n" - "mov %w2, %%es\n" - "mov %w2, %%fs\n" - "mov %w2, %%gs\n" - "mov %w2, %%ss\n" - // make a far return frame on the stack - // [ss] @rsp+8 - // [rip] @rsp - "pushq %1\n" - "lea .Lflush(%%rip), %%rax\n" - "push %%rax\n" - // far return, now we're in the code segment - // defined here. - "lretq\n" - ".Lflush:\n" - "ltr %w3\n" - "popf\n" - // dependency on pre-boot GDT is now gone - : - : "m"(gdtr), - "i"(CODE_SEG_INDEX << 3), - "r"(DATA_SEG_INDEX << 3), - "r"(TASK_SEG_INDEX << 3) - ); + ( + // can't have interrupts during GDT reload + // but don't re-enable interrupts if they were already disabled + "pushf\n" + "cli\n" + "lgdt %0\n" + "mov %w2, %%ds\n" + "mov %w2, %%es\n" + "mov %w2, %%fs\n" + "mov %w2, %%gs\n" + "mov %w2, %%ss\n" + // make a far return frame on the stack + // [ss] @rsp+8 + // [rip] @rsp + "pushq %1\n" + "lea .Lflush(%%rip), %%rax\n" + "push %%rax\n" + // far return, now we're in the code segment + // defined here. + "lretq\n" + ".Lflush:\n" + "ltr %w3\n" + "popf\n" + // dependency on pre-boot GDT is now gone + : + : "m"(gdtr), + "i"(CODE_SUPER_SEG_INDEX << 3), + "r"(DATA_SEG_INDEX << 3), + "r"(TASK_SEG_INDEX << 3) + ); } static void idt_init(void) { struct dtr64 idtr = {sizeof(idt) - 1, (uint64_t)&idt}; - + __asm__ volatile - ( - // can't have interrupts enabled during IDT reload--obviously. - // as with GDT don't re-enable interrupts if they were already - // disabled. - "pushf\n" - "cli\n" - "lidt %0\n" - "popf\n" - // much more straightforward than the gdt code. - :: "m"(idtr) - ); + ( + // can't have interrupts enabled during IDT reload--obviously. + // as with GDT don't re-enable interrupts if they were already + // disabled. + "pushf\n" + "cli\n" + "lidt %0\n" + "popf\n" + // much more straightforward than the gdt code. + :: "m"(idtr) + ); } void cpu_init(void) @@ -186,6 +208,41 @@ void cpu_init(void) gdt_init(); idt_init(); exceptions_init(); + + //TODO: fix rudimentary syscall stuff. + + uint64_t lstar_bits = (uintptr_t)syscall_entry; + msr_write(MSR_LSTAR, lstar_bits); + + union + { + struct + { + uint32_t eip32; + uint8_t syscall_ss; + uint8_t syscall_cs; + uint8_t sysret_ss; + uint8_t sysret_cs; + } + fields; + uint64_t raw; + } + star_bits = + { + { + 0, + DATA_SEG_INDEX, + CODE_SUPER_SEG_INDEX, + DATA_SEG_INDEX, + CODE_USER_SEG_INDEX + } + }; + + msr_write(MSR_STAR, star_bits.raw); + + uint64_t efer_bits = msr_read(MSR_EFER); + efer_bits |= 1; // enable syscall extensions + msr_write(MSR_EFER, efer_bits); } void exceptions_init(void) @@ -196,13 +253,13 @@ void exceptions_init(void) void isr_install(int vec, void (*isr)(void), int trap, int ist) { enum gate_descriptor_type type = INT64_GATE; - + if (trap) { type = TRAP64_GATE; } - - set_idt(vec, CODE_SEG_INDEX << 3, (uint64_t)isr, type); + + set_idt(vec, CODE_SUPER_SEG_INDEX << 3, (uint64_t)isr, type); if (ist) { set_ist(vec, ist); @@ -223,3 +280,31 @@ void int_disable(void) { __asm__ ("cli"); } + +uint64_t msr_read(uint32_t index) +{ + uint32_t low; + uint32_t high; + + __asm__ volatile + ( + "rdmsr\n\t" + : "=a"(low), "=d"(high) + : "c"(index) + ); + + return ((uint64_t)high << 32)|low; +} + +void msr_write(uint32_t index, uint64_t value) +{ + uint32_t low = value & 0xffffffff; + uint32_t high = value >> 32; + + __asm__ volatile + ( + "wrmsr\n\t" + :: "a"(low), "d"(high), "c"(index) + ); +} + diff --git a/kc/core/cpu.h b/kc/core/cpu.h index 56a4073..2d5e134 100644 --- a/kc/core/cpu.h +++ b/kc/core/cpu.h @@ -1,5 +1,7 @@ #pragma once +#include <stdint.h> + void cpu_init(void); void isr_install(int vec, void (*isr)(void), int ist, int trap); @@ -7,3 +9,7 @@ void ist_install(int ist, void *stack); void int_enable(void); void int_disable(void); + +uint64_t msr_read(uint32_t index); +void msr_write(uint32_t index, uint64_t value); + |
