diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 887e73f..b55581d 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -9,6 +9,7 @@ CFLAGS+=-Wall \ -Wno-unused-variable \ -Wno-language-extension-token \ -Wno-gnu-zero-variadic-macro-arguments \ + -O0 \ -ggdb ifdef KERNEL_TEST_MODE diff --git a/include/sys/amd64/asm/asm_cpu.h b/include/sys/amd64/asm/asm_cpu.h index 64a80dc..2e8b668 100644 --- a/include/sys/amd64/asm/asm_cpu.h +++ b/include/sys/amd64/asm/asm_cpu.h @@ -10,4 +10,14 @@ #define get_cpu(off) \ (cpu + off)(%rip) #endif + +// To be used in interrupt handlers +// DIRECTLY AFTER ENTRY without prior stack modification +.macro swapgs_if_needed + cmpq $0x08, 0x08(%rsp) + je 1f + swapgs +1: +.endm + #endif diff --git a/include/sys/amd64/cpu.h b/include/sys/amd64/cpu.h index c28a2c5..e29bba4 100644 --- a/include/sys/amd64/cpu.h +++ b/include/sys/amd64/cpu.h @@ -11,6 +11,7 @@ struct cpu { struct thread *thread; // 0x08 uint64_t ticks; // 0x10 amd64_tss_t *tss; // 0x18 + uint64_t syscall_rsp; // 0x20 // No need to define offsets for these: ther're not accessed // from assembly diff --git a/sys/amd64/hw/irq0.S b/sys/amd64/hw/irq0.S index a3ed25f..03fb923 100644 --- a/sys/amd64/hw/irq0.S +++ b/sys/amd64/hw/irq0.S @@ -5,7 +5,13 @@ amd64_irq0: cli - swapgs + // Stack: + // ss + // rsp + // rflags + // cs + // rip + swapgs_if_needed // Interrupt entry: // rsp should be one of the following: @@ -45,7 +51,7 @@ amd64_irq0: irq_pop_ctx - swapgs + swapgs_if_needed iretq _fmt0: diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index e2ba27e..1cb46f7 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -18,16 +18,37 @@ static char t_stack3[IDLE_STACK * AMD64_MAX_SMP] = {0}; #endif static struct thread t_idle[AMD64_MAX_SMP] = {0}; +void func0(uintptr_t id, int state) { + uint16_t attr = (id + 0x2) << 8; + uint16_t letter = '0' + id; + *((uint16_t *) MM_VIRTUALIZE(0xB8000) + 80 * 0 + id) = state * attr | letter; + asm volatile ("syscall"); +} + void idle_func(uintptr_t id) { #if defined(AMD64_IDLE_RING3) int state = 0; - uint16_t attr = (id + 0x2) << 8; - uint16_t letter = '0' + id; + uintptr_t a0 = 0, a1 = 0; + *((uint16_t *) MM_VIRTUALIZE(0xB8000) + 80 * 1 + id) = (id + 'A') | ((id + 0x9) << 8); + + { + register uintptr_t rsp asm ("rsp"); + a0 = rsp; + } asm volatile ("syscall"); + { + register uintptr_t rsp asm ("rsp"); + a1 = rsp; + } + + if (a0 != a1) { + while (1); + } while (1) { - *((uint16_t *) MM_VIRTUALIZE(0xB8000) + 80 * 23 + id) = state * attr | letter; + func0(id, state); + asm volatile ("syscall"); state = !state; for (size_t i = 0; i < 10000000; ++i); } diff --git a/sys/amd64/syscall_s.S b/sys/amd64/syscall_s.S index 97ad092..30c9b9a 100644 --- a/sys/amd64/syscall_s.S +++ b/sys/amd64/syscall_s.S @@ -1,3 +1,5 @@ +#include "sys/amd64/asm/asm_cpu.h" + .section .text .global amd64_syscall_init @@ -40,5 +42,34 @@ amd64_syscall_init: // Entrypoint of SYSCALL instruction amd64_syscall_entry: - xchgw %bx, %bx + // R11 = rflags3 + // RSP = rsp3 + // RCX = rip3 + + swapgs + + // // 1. Switch to kernel context + // // 1.1. Store rsp3 in CPU struct + movq %rsp, get_cpu(0x20) + // 1.2. Load rsp0 from CPU struct + movq get_cpu(0x08), %rsp + movq (%rsp), %rsp + + pushq %rax + movq get_cpu(0x20), %rax + pushq %rax + + movq $100000000, %rax + sti + +1: + decq %rax + jnz 1b + cli + + popq %rdi + popq %rax + movq %rdi, %rsp + + swapgs sysretq