From 48d47dea94cc1c5c11d2ad8836d4f1365dd7d2ca Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 11 Oct 2019 21:16:58 +0300 Subject: [PATCH] Now with userspace --- include/sys/amd64/cpu.h | 2 ++ include/sys/amd64/hw/gdt.h | 1 + sys/amd64/hw/ap_code.nasm | 2 ++ sys/amd64/hw/gdt.c | 24 ++++++++++++++++-------- sys/amd64/hw/gdt_s.S | 2 ++ sys/amd64/hw/irq0.S | 6 ++++++ sys/amd64/smp/smp.c | 2 ++ sys/amd64/sys/sched.c | 15 +++++++++------ 8 files changed, 40 insertions(+), 14 deletions(-) diff --git a/include/sys/amd64/cpu.h b/include/sys/amd64/cpu.h index 99db323..c28a2c5 100644 --- a/include/sys/amd64/cpu.h +++ b/include/sys/amd64/cpu.h @@ -1,5 +1,6 @@ #pragma once #include "sys/amd64/asm/asm_irq.h" +#include "sys/amd64/hw/gdt.h" #include "sys/types.h" #include "sys/thread.h" @@ -9,6 +10,7 @@ struct cpu { struct thread *thread; // 0x08 uint64_t ticks; // 0x10 + amd64_tss_t *tss; // 0x18 // No need to define offsets for these: ther're not accessed // from assembly diff --git a/include/sys/amd64/hw/gdt.h b/include/sys/amd64/hw/gdt.h index 57451c4..7ff6db6 100644 --- a/include/sys/amd64/hw/gdt.h +++ b/include/sys/amd64/hw/gdt.h @@ -35,5 +35,6 @@ typedef struct { } __attribute__((packed)) amd64_gdt_ptr_t; amd64_gdt_ptr_t *amd64_gdtr_get(int cpu); +amd64_tss_t *amd64_tss_get(int cpu); void amd64_gdt_init(void); diff --git a/sys/amd64/hw/ap_code.nasm b/sys/amd64/hw/ap_code.nasm index 7d3f719..9441709 100644 --- a/sys/amd64/hw/ap_code.nasm +++ b/sys/amd64/hw/ap_code.nasm @@ -76,6 +76,8 @@ ap_startup_long: add rax, rcx lgdt [rax] + mov ax, 0x28 + ltr ax mov rax, 0x10 mov ds, rax diff --git a/sys/amd64/hw/gdt.c b/sys/amd64/hw/gdt.c index 1b129aa..f122047 100644 --- a/sys/amd64/hw/gdt.c +++ b/sys/amd64/hw/gdt.c @@ -1,5 +1,5 @@ #include "sys/amd64/hw/gdt.h" -#define GDT_SIZE 3 +#define GDT_SIZE 7 extern void amd64_gdt_load(void *p); @@ -35,6 +35,10 @@ amd64_gdt_ptr_t *amd64_gdtr_get(int cpu) { return &amd64_gdtr[cpu]; } +amd64_tss_t *amd64_tss_get(int cpu) { + return &amd64_tss[cpu]; +} + void amd64_gdt_init(void) { for (size_t i = 0; i < AMD64_MAX_SMP; ++i) { amd64_gdt_set(i, 0, 0, 0, 0, 0); @@ -44,14 +48,18 @@ void amd64_gdt_init(void) { amd64_gdt_set(i, 2, 0, 0, 0, GDT_ACC_PR | GDT_ACC_S | GDT_ACC_RW); - //amd64_gdt_set(i, 3, 0, 0, - // 0, - // GDT_ACC_PR | GDT_ACC_R3 | GDT_ACC_S | GDT_ACC_RW); - //amd64_gdt_set(i, 4, 0, 0, - // GDT_FLG_LONG, - // GDT_ACC_PR | GDT_ACC_R3 | GDT_ACC_S | GDT_ACC_EX); + amd64_gdt_set(i, 3, 0, 0, + 0, + GDT_ACC_PR | GDT_ACC_R3 | GDT_ACC_S | GDT_ACC_RW); + amd64_gdt_set(i, 4, 0, 0, + GDT_FLG_LONG, + GDT_ACC_PR | GDT_ACC_R3 | GDT_ACC_S | GDT_ACC_EX); + amd64_gdt_set(i, 5, ((uintptr_t) &amd64_tss[i]) & 0xFFFFFFFF, sizeof(amd64_tss_t) - 1, + GDT_FLG_LONG, + GDT_ACC_PR | GDT_ACC_AC | GDT_ACC_EX); + *(uint64_t *) &gdt[i * GDT_SIZE + 6] = ((uintptr_t) &amd64_tss[i]) >> 32; - amd64_gdtr[i].size = sizeof(GDT_SIZE) * sizeof(amd64_gdt_entry_t) - 1; + amd64_gdtr[i].size = GDT_SIZE * sizeof(amd64_gdt_entry_t) - 1; amd64_gdtr[i].offset = (uintptr_t) &gdt[GDT_SIZE * i]; } diff --git a/sys/amd64/hw/gdt_s.S b/sys/amd64/hw/gdt_s.S index 7cec8c2..e8c030d 100644 --- a/sys/amd64/hw/gdt_s.S +++ b/sys/amd64/hw/gdt_s.S @@ -3,4 +3,6 @@ amd64_gdt_load: lgdt (%rdi) // Not sure if CS reload is needed + movw $0x28, %ax + ltr %ax retq diff --git a/sys/amd64/hw/irq0.S b/sys/amd64/hw/irq0.S index d046e82..a3ed25f 100644 --- a/sys/amd64/hw/irq0.S +++ b/sys/amd64/hw/irq0.S @@ -31,6 +31,12 @@ amd64_irq0: // rsi = thread structure pointer movq get_cpu(0x08), %rsi movq 0(%rsi), %rsp + + // Write TSS entry + movq get_cpu(0x18), %rdi + movq %rsp, %rax + addq $(25 * 8), %rax + movq %rax, 4(%rdi) 1: // Assume we're now on TASK2's stack diff --git a/sys/amd64/smp/smp.c b/sys/amd64/smp/smp.c index e10efee..37a8546 100644 --- a/sys/amd64/smp/smp.c +++ b/sys/amd64/smp/smp.c @@ -141,6 +141,7 @@ void amd64_smp_add(uint8_t apic_id) { cpus[i].self = &cpus[i]; cpus[i].apic_id = (uint64_t) apic_id; cpus[i].processor_id = i; + cpus[i].tss = amd64_tss_get(i); } static void amd64_smp_bsp_configure(void) { @@ -149,6 +150,7 @@ static void amd64_smp_bsp_configure(void) { cpus[0].self = &cpus[0]; cpus[0].processor_id = 0; cpus[0].apic_id = 0 /* TODO: apic_id may be different from 0 for BSP */; + cpus[0].tss = amd64_tss_get(0); set_cpu((uintptr_t) &cpus[0]); } diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index 04f5d39..9b26629 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -16,9 +16,12 @@ static char t_stack3[TEST_STACK * AMD64_MAX_SMP] = {0}; static struct thread t_idle[AMD64_MAX_SMP] = {0}; void idle_func(uintptr_t id) { + int v = 0; while (1) { - //kdebug("%d\n", id); - //asm volatile ("sti; hlt"); + // Cannot call kernel functions directly - they use privileged insns. + *((uint16_t *) 0xFFFFFF00000B8000 + id) = v * 0x700 | ('A' + id); + v = !v; + for (size_t i = 0; i < 100000000; ++i); } } @@ -40,8 +43,8 @@ static void make_idle_task(int cpu) { ctx->rip = (uintptr_t) idle_func; ctx->rsp = t->data.stack3_base + t->data.stack3_size; - ctx->cs = 0x08; - ctx->ss = 0x10; + ctx->cs = 0x23; + ctx->ss = 0x1B; ctx->rflags = 0x248; ctx->rax = 0; @@ -65,8 +68,8 @@ static void make_idle_task(int cpu) { ctx->r14 = 0; ctx->r15 = 0; - ctx->ds = 0x10; - ctx->es = 0x10; + ctx->ds = 0x1B; + ctx->es = 0x1B; ctx->fs = 0; ctx->__canary = AMD64_STACK_CTX_CANARY;