diff --git a/kernel-src/arch/x86-64/gdt.c b/kernel-src/arch/x86-64/gdt.c new file mode 100644 index 00000000..499e0513 --- /dev/null +++ b/kernel-src/arch/x86-64/gdt.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include + +static uint64_t template[7] = { + 0, // NULL 0x0 + 0x00af9b000000ffff, // code64 0x8 + 0x00af93000000ffff, // data64 0x10 + 0x00affb000000ffff, // ucode64 0x18 + 0x00aff3000000ffff, // udata64 0x20 + 0x0020890000000000, // low ist 0x28 + 0x0000000000000000 // high ist +}; + +typedef struct { + uint16_t size; + uint64_t address; +} __attribute__((packed)) gdtr_t; + +void arch_gdt_reload() { + memcpy(_cpu()->gdt, template, sizeof(template)); + uintptr_t istaddr = (uintptr_t)&_cpu()->ist; + + // add ist to gdt + _cpu()->gdt[5] |= ((istaddr & 0xff000000) << 32) | ((istaddr & 0xff0000) << 16) | ((istaddr & 0xffff) << 16) | sizeof(ist_t); + _cpu()->gdt[6] = (istaddr >> 32) & 0xffffffff; + + // reload gdt and ist + + gdtr_t gdtr = { + .size = sizeof(template) - 1, + .address = (uintptr_t)&_cpu()->gdt + }; + + asm volatile("lgdt (%%rax)" : : "a"(&gdtr) : "memory"); + asm volatile("ltr %%ax" : : "a"(0x28)); + asm volatile( + "swapgs;" + "mov $0, %%ax;" + "mov %%ax, %%gs;" + "mov %%ax, %%fs;" + "swapgs;" + "mov $0x10, %%ax;" + "mov %%ax, %%ds;" + "mov %%ax, %%es;" + "mov %%ax, %%ss;" + "pushq $0x8;" + "pushq $.reload;" + "retfq;" + ".reload:" + : : : "ax"); +} diff --git a/kernel-src/arch/x86-64/main.c b/kernel-src/arch/x86-64/main.c index 388d83bd..755c592d 100644 --- a/kernel-src/arch/x86-64/main.c +++ b/kernel-src/arch/x86-64/main.c @@ -1,7 +1,12 @@ #include #include +#include + +static cpu_t bsp_cpu; void kernel_entry() { + cpu_set(&bsp_cpu); logging_sethook(arch_e9_putc); + arch_gdt_reload(); __assert(!"kernel entry end"); } diff --git a/kernel-src/include/arch/cpu.h b/kernel-src/include/arch/cpu.h new file mode 100644 index 00000000..470ca745 --- /dev/null +++ b/kernel-src/include/arch/cpu.h @@ -0,0 +1,24 @@ +#ifndef _CPU_H +#define _CPU_H + +#include +#include + +#include +#include + +typedef struct { + uint64_t gdt[7]; + ist_t ist; + int lapicid; +} cpu_t; + +static inline cpu_t *_cpu() { + return (cpu_t *)rdmsr(MSR_GSBASE); +} + +static inline void cpu_set(cpu_t *ptr) { + wrmsr(MSR_GSBASE, (uint64_t)ptr); +} + +#endif diff --git a/kernel-src/include/arch/ist.h b/kernel-src/include/arch/ist.h new file mode 100644 index 00000000..c1e16e37 --- /dev/null +++ b/kernel-src/include/arch/ist.h @@ -0,0 +1,21 @@ +#ifndef _IST_H +#define _IST_H + +typedef struct { + uint32_t reserved; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t reserved2; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + uint32_t reserved3[3]; + uint32_t iopb; +} __attribute__((packed)) ist_t; + +#endif diff --git a/kernel-src/include/arch/msr.h b/kernel-src/include/arch/msr.h new file mode 100644 index 00000000..fb746fa5 --- /dev/null +++ b/kernel-src/include/arch/msr.h @@ -0,0 +1,27 @@ +#ifndef _MSR_H +#define _MSR_H + +#include + +#define MSR_EFER 0xC0000080 +#define MSR_STAR 0xC0000081 +#define MSR_LSTAR 0xC0000082 +#define MSR_CSTAR 0xC0000083 +#define MSR_FMASK 0xC0000084 +#define MSR_FSBASE 0xC0000100 +#define MSR_GSBASE 0xC0000101 +#define MSR_KERNELGSBASE 0xC0000102 + +static inline uint64_t rdmsr(uint32_t which) { + uint64_t low,high; + asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(which)); + return (high << 32) | low; +} + +static inline void wrmsr(uint32_t which, uint64_t value) { + uint32_t low = value & 0xFFFFFFFF; + uint32_t high = (value >> 32) & 0xFFFFFFFF; + asm volatile("wrmsr" : : "a"(low), "d"(high), "c"(which)); +} + +#endif diff --git a/kernel-src/include/string.h b/kernel-src/include/string.h new file mode 100644 index 00000000..3ee28a18 --- /dev/null +++ b/kernel-src/include/string.h @@ -0,0 +1,14 @@ +#ifndef _STRING_H +#define _STRING_H + +#include + +size_t strlen(const char *str); +char *strcpy(char *dest, const char *src); +char *strcat(char *dest, const char *str); +void *memcpy(void *dest, void *src, size_t size); +void *memset(void *dest, unsigned long what, size_t size); +int strcmp(const char *a, const char *b); +int strncmp(const char *a, const char *b, size_t c); + +#endif diff --git a/kernel-src/lib/string.c b/kernel-src/lib/string.c new file mode 100644 index 00000000..ea121713 --- /dev/null +++ b/kernel-src/lib/string.c @@ -0,0 +1,68 @@ +#include +#include +#include + +void *memcpy(void *d, void *s, size_t c) { + uint8_t *sc = (uint8_t *)s; + uint8_t *dc = (uint8_t *)d; + + while(c--) + *dc++ = *sc++; + + return d; +} + +void *memset(void *ptr, unsigned long value, size_t num) { + char *p = (char *)ptr; + while(num--) + *p++ = value; + + return ptr; +} + +char *strcat(char *dest, const char *src) { + dest += strlen(dest); + + strcpy(dest, src); + + return dest; + +} +int strcmp(const char *a, const char *b) { + while(*a && (*a == *b)) { + ++a; + ++b; + } + + return *(const unsigned char *)a - *(const unsigned char *)b; +} + +char *strcpy(char *p, const char *s) { + const char *temp1 = s; + char *temp2 = p; + while(*temp1 != '\0') { + *temp2 = *temp1; + temp1++; + temp2++; + } + *temp2 = '\0'; + return p; +} + +size_t strlen(const char *a) { + size_t s = 0; + + while(a[s] != '\0') + ++s; + + return s; +} + +int strncmp(const char *a, const char *b, size_t c) { + int diff = 0; + + while(c-- && diff == 0) + diff += *a++ - *b++; + + return diff; +}