summaryrefslogtreecommitdiff
path: root/kernel/cpu
diff options
context:
space:
mode:
authorGalen Sagarin <gps5307@rit.edu>2025-04-29 14:18:40 -0400
committerGalen Sagarin <gps5307@rit.edu>2025-04-29 14:18:40 -0400
commitae2cdd83ba4a0cae161db0b29031d5591005fa34 (patch)
tree82fbdfcbb1fe4e3b5e232db195c8c331d69489fd /kernel/cpu
parentStarted writing fat.c (diff)
parentfs header changes (diff)
downloadcomus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.tar.gz
comus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.tar.bz2
comus-ae2cdd83ba4a0cae161db0b29031d5591005fa34.zip
Merge branch 'main' of https://github.com/kenshineto/kern into fat32
Merging main into here
Diffstat (limited to 'kernel/cpu')
-rw-r--r--kernel/cpu/cpu.c61
-rw-r--r--kernel/cpu/idt.S121
-rw-r--r--kernel/cpu/idt.c44
-rw-r--r--kernel/cpu/tss.S6
-rw-r--r--kernel/cpu/tss.c82
-rw-r--r--kernel/cpu/tss.h31
6 files changed, 283 insertions, 62 deletions
diff --git a/kernel/cpu/cpu.c b/kernel/cpu/cpu.c
index 136a1d8..f607b36 100644
--- a/kernel/cpu/cpu.c
+++ b/kernel/cpu/cpu.c
@@ -1,8 +1,10 @@
#include <lib.h>
#include <comus/cpu.h>
+#include <comus/asm.h>
#include "pic.h"
#include "idt.h"
+#include "tss.h"
static inline void fpu_init(void)
{
@@ -60,8 +62,10 @@ void cpu_init(void)
struct cpu_feat feats;
cpu_feats(&feats);
- pic_remap();
+ cli();
idt_init();
+ tss_init();
+ pic_remap();
if (feats.fpu)
fpu_init();
if (feats.sse) {
@@ -178,25 +182,26 @@ void cpu_feats(struct cpu_feat *feats)
void cpu_print_regs(struct cpu_regs *regs)
{
- kprintf("rax: %#016lx (%lu)\n", regs->rax, regs->rax);
- kprintf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx);
- kprintf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx);
- kprintf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx);
- kprintf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi);
- kprintf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi);
- kprintf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp);
- kprintf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp);
- kprintf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8);
- kprintf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9);
- kprintf("r10: %#016lx (%lu)\n", regs->r10, regs->r10);
- kprintf("r11: %#016lx (%lu)\n", regs->r11, regs->r11);
- kprintf("r12: %#016lx (%lu)\n", regs->r12, regs->r12);
- kprintf("r13: %#016lx (%lu)\n", regs->r13, regs->r13);
- kprintf("r14: %#016lx (%lu)\n", regs->r14, regs->r14);
- kprintf("r15: %#016lx (%lu)\n", regs->r15, regs->r15);
- kprintf("rip: %#016lx (%lu)\n", regs->rip, regs->rip);
- kprintf("rflags: %#016lx (%lu)\n", regs->rflags, regs->rflags);
- kputs("rflags: ");
+ kprintf("rax:\t%#016lx (%lu)\n", regs->rax, regs->rax);
+ kprintf("rbx:\t%#016lx (%lu)\n", regs->rbx, regs->rbx);
+ kprintf("rcx:\t%#016lx (%lu)\n", regs->rcx, regs->rcx);
+ kprintf("rdx:\t%#016lx (%lu)\n", regs->rdx, regs->rdx);
+ kprintf("rsi:\t%#016lx (%lu)\n", regs->rsi, regs->rsi);
+ kprintf("rdi:\t%#016lx (%lu)\n", regs->rdi, regs->rdi);
+ kprintf("rsp:\t%#016lx (%lu)\n", regs->rsp, regs->rsp);
+ kprintf("rbp:\t%#016lx (%lu)\n", regs->rbp, regs->rbp);
+ kprintf("r8:\t%#016lx (%lu)\n", regs->r8, regs->r8);
+ kprintf("r9:\t%#016lx (%lu)\n", regs->r9, regs->r9);
+ kprintf("r10:\t%#016lx (%lu)\n", regs->r10, regs->r10);
+ kprintf("r11:\t%#016lx (%lu)\n", regs->r11, regs->r11);
+ kprintf("r12:\t%#016lx (%lu)\n", regs->r12, regs->r12);
+ kprintf("r13:\t%#016lx (%lu)\n", regs->r13, regs->r13);
+ kprintf("r14:\t%#016lx (%lu)\n", regs->r14, regs->r14);
+ kprintf("r15:\t%#016lx (%lu)\n", regs->r15, regs->r15);
+ kprintf("rip:\t%#016lx (%lu)\n", regs->rip, regs->rip);
+ kprintf("rflags: %#016lx (%lu) [ ", regs->rflags, regs->rflags);
+ if (regs->rflags & (3 << 12))
+ kprintf("IOPL=%lu ", (regs->rflags >> 12) & 0x3);
if (regs->rflags & (1 << 0))
kputs("CF ");
if (regs->rflags & (1 << 2))
@@ -215,8 +220,6 @@ void cpu_print_regs(struct cpu_regs *regs)
kputs("DF ");
if (regs->rflags & (1 << 11))
kputs("OF ");
- if (regs->rflags & (3 << 12))
- kputs("IOPL ");
if (regs->rflags & (1 << 14))
kputs("NT ");
if (regs->rflags & (1 << 15))
@@ -233,5 +236,19 @@ void cpu_print_regs(struct cpu_regs *regs)
kputs("VIP ");
if (regs->rflags & (1 << 21))
kputs("ID ");
+ kputs("]\n");
+ kprintf("cs:\t%#04lx (%lu) [ DPL=%lu ]\n", regs->cs, regs->cs,
+ regs->cs & 0x3);
+ kprintf("ss:\t%#04lx (%lu) [ DPL=%lu ]\n", regs->ss, regs->ss,
+ regs->ss & 0x3);
+ kprintf("ds:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->ds, regs->ds,
+ regs->ds & 0x3);
+ kprintf("es:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->es, regs->es,
+ regs->es & 0x3);
+ kprintf("fs:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->fs, regs->fs,
+ regs->fs & 0x3);
+ kprintf("gs:\t%#04hx (%hu) [ DPL=%hu ]\n", regs->gs, regs->gs,
+ regs->gs & 0x3);
+ kprintf("cr3:\t%#016lx (%lu)\n", regs->cr3, regs->cr3);
kputs("\n");
}
diff --git a/kernel/cpu/idt.S b/kernel/cpu/idt.S
index 0ba35f8..b3a8454 100644
--- a/kernel/cpu/idt.S
+++ b/kernel/cpu/idt.S
@@ -1,12 +1,17 @@
.global isr_stub_table
+ .global syscall_return
.extern idt_exception_handler
.extern idt_pic_timer
.extern idt_pic_keyboard
.extern idt_pic_mouse
.extern idt_pic_eoi
+ .extern syscall_handler
+ .extern current_pcb
+ .extern isr_save
.macro PUSHALL
+ # regs
pushq %rax
pushq %rbx
pushq %rcx
@@ -22,9 +27,38 @@
pushq %r13
pushq %r14
pushq %r15
+
+ # segments
+ movw %ds, %ax
+ pushw %ax
+ movw %es, %ax
+ pushw %ax
+ movw %fs, %ax
+ pushw %ax
+ movw %gs, %ax
+ pushw %ax
+
+ # pgdir
+ movq %cr3, %rax
+ pushq %rax
.endm
.macro POPALL
+ # pgdir
+ popq %rax
+ movq %rax, %cr3
+
+ # segments
+ popw %ax
+ movw %ax, %gs
+ popw %ax
+ movw %ax, %fs
+ popw %ax
+ movw %ax, %es
+ popw %ax
+ movw %ax, %ds
+
+ # regs
popq %r15
popq %r14
popq %r13
@@ -42,19 +76,29 @@
popq %rax
.endm
+.macro ISRSave
+ PUSHALL
+ cld
+
+ movq %rsp, %rdi
+ callq isr_save
+.endm
+
+.macro ISRRestore
+ POPALL
+ iretq
+.endm
+
# call the exception handler with the interrupt number
# args: interrupt number
.macro ISRException num
.align 8
isr_stub_\num:
- PUSHALL
- cld
- movq $\num, %rdi # exception number
+ ISRSave
+ movq $\num, %rdi # exception number
movq $0, %rsi # placeholder error code
- movq %rsp, %rdx # top of stack
callq idt_exception_handler
- POPALL
- iretq
+ ISRRestore
.endm
# call the exception handler with the interrupt number
@@ -64,65 +108,64 @@ isr_stub_\num:
.align 8
isr_stub_\num:
# retrieve the error code without corrupting registers
- mov %eax, isr_tmp
+ movq %rax, isr_tmp
popq %rax
- mov %eax, isr_err_code
+ movq %rax, isr_err_code
movq isr_tmp, %rax
- PUSHALL
- cld
+ ISRSave
movq $\num, %rdi # exception number
movq isr_err_code, %rsi # error code
- movq %rsp, %rdx # top of stack
callq idt_exception_handler
- POPALL
- iretq
+ ISRRestore
+.endm
+
+.macro SYSCALL num
+ .align 8
+isr_stub_\num:
+ ISRSave
+ callq syscall_handler
+ jmp syscall_return
.endm
.macro PICGeneric num
.align 8
isr_stub_\num:
- PUSHALL
- cld
+ ISRSave
movq $\num, %rdi
callq idt_pic_eoi
- POPALL
- iretq
+ ISRRestore
.endm
+# we have to send eoi first since
+# idt_pic_timer may not return
.macro PICTimer num
.align 8
isr_stub_\num:
- PUSHALL
- cld
- callq idt_pic_timer
- movq $\num, %rdi
+ ISRSave
callq idt_pic_eoi
- POPALL
- iretq
+ movq $\num, %rdi
+ callq idt_pic_timer
+ ISRRestore
.endm
.macro PICKeyboard num
.align 8
isr_stub_\num:
- PUSHALL
- cld
+ ISRSave
callq idt_pic_keyboard
movq $\num, %rdi
callq idt_pic_eoi
- POPALL
- iretq
+ ISRRestore
.endm
.macro PICMouse num
.align 8
isr_stub_\num:
- PUSHALL
- cld
+ ISRSave
callq idt_pic_mouse
movq $\num, %rdi
callq idt_pic_eoi
- POPALL
- iretq
+ ISRRestore
.endm
# do nothing
@@ -402,10 +445,22 @@ isr_stub_table:
.quad isr_stub_254
.quad isr_stub_255
-# isr stubs
.section .text
.code64
+# isr restore
+syscall_return:
+ // get current pcb address
+ movq current_pcb, %rbx
+
+ // load user stack
+ leaq 8(%rbx), %rsp
+
+ // return
+ POPALL
+ iretq
+
+# isr stubs
ISRException 0
ISRException 1
ISRException 2
@@ -536,7 +591,7 @@ ISRIgnore 124
ISRIgnore 125
ISRIgnore 126
ISRIgnore 127
-ISRIgnore 128
+SYSCALL 128
ISRIgnore 129
ISRIgnore 130
ISRIgnore 131
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index bf4b499..2eab7ec 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -2,7 +2,10 @@
#include <comus/memory.h>
#include <comus/asm.h>
#include <comus/cpu.h>
+#include <comus/drivers/ps2.h>
#include <comus/drivers/pit.h>
+#include <comus/procs.h>
+#include <comus/memory.h>
#include "idt.h"
#include "pic.h"
@@ -41,8 +44,12 @@ struct idtr {
__attribute__((aligned(0x10))) static struct idt_entry idt[256];
static struct idtr idtr;
-// from idt.S
extern void *isr_stub_table[];
+extern char kern_stack_start[];
+extern char kern_stack_end[];
+
+// current register state on interrupt
+static struct cpu_regs *state;
// initialize and load the IDT
void idt_init(void)
@@ -57,15 +64,17 @@ void idt_init(void)
uint64_t isr = (uint64_t)isr_stub_table[vector];
// interrupts before 0x20 are for cpu exceptions
- uint8_t gate_type = (vector < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT;
entry->kernel_cs = 0x08; // offset of 1 into GDT
entry->ist = 0;
- entry->flags = PRESENT | RING0 | gate_type;
+ entry->flags = PRESENT | RING0 | GATE_64BIT_INT;
entry->isr_low = isr & 0xffff;
entry->isr_mid = (isr >> 16) & 0xffff;
entry->isr_high = (isr >> 32) & 0xffffffff;
entry->reserved = 0;
+
+ if (vector == 0x80)
+ entry->flags |= RING3;
}
__asm__ volatile("lidt %0" : : "m"(idtr));
@@ -111,8 +120,8 @@ char *EXCEPTIONS[] = {
"Reserved",
};
-void idt_exception_handler(uint64_t exception, uint64_t code,
- struct cpu_regs *state)
+__attribute__((noreturn)) void idt_exception_handler(uint64_t exception,
+ uint64_t code)
{
uint64_t cr2;
@@ -144,22 +153,43 @@ void idt_exception_handler(uint64_t exception, uint64_t code,
}
}
+void isr_save(struct cpu_regs *regs)
+{
+ // make sure were in the kernel memory context
+ mem_ctx_switch(kernel_mem_ctx);
+
+ // save pointer to registers
+ state = regs;
+
+ // if we have a kernel stack pointer
+ // we should return to not save kernel context
+ // data to userspace
+ if (regs->rsp >= (size_t)kern_stack_start &&
+ regs->rsp <= (size_t)kern_stack_end)
+ return;
+
+ // save registers in current_pcb
+ if (current_pcb != NULL)
+ current_pcb->regs = *regs;
+}
+
void idt_pic_eoi(uint8_t exception)
{
pic_eoi(exception - PIC_REMAP_OFFSET);
}
-int counter = 0;
-
void idt_pic_timer(void)
{
ticks++;
+ pcb_on_tick();
}
void idt_pic_keyboard(void)
{
+ ps2kb_recv();
}
void idt_pic_mouse(void)
{
+ ps2mouse_recv();
}
diff --git a/kernel/cpu/tss.S b/kernel/cpu/tss.S
new file mode 100644
index 0000000..27f2955
--- /dev/null
+++ b/kernel/cpu/tss.S
@@ -0,0 +1,6 @@
+ .globl tss_flush
+
+tss_flush:
+ movw $0x28, %ax
+ ltr %ax
+ ret
diff --git a/kernel/cpu/tss.c b/kernel/cpu/tss.c
new file mode 100644
index 0000000..bca979d
--- /dev/null
+++ b/kernel/cpu/tss.c
@@ -0,0 +1,82 @@
+#include <comus/memory.h>
+#include <lib.h>
+
+#include "tss.h"
+
+struct sys_seg_descriptor {
+ uint64_t limit0_15 : 16;
+ uint64_t base0_15 : 16;
+ uint64_t base16_23 : 8;
+ uint64_t type : 4;
+ uint64_t : 1;
+ uint64_t DPL : 2;
+ uint64_t present : 1;
+ uint64_t limit16_19 : 4;
+ uint64_t available : 1;
+ uint64_t : 1;
+ uint64_t : 1;
+ uint64_t gran : 1;
+ uint64_t base24_31 : 8;
+ uint64_t base32_63 : 32;
+ uint64_t : 32;
+} __attribute__((packed));
+
+struct tss {
+ uint64_t : 32;
+ uint64_t rsp0 : 64;
+ uint64_t rsp1 : 64;
+ uint64_t rsp2 : 64;
+ uint64_t : 64;
+ uint64_t ist1 : 64;
+ uint64_t ist2 : 64;
+ uint64_t ist3 : 64;
+ uint64_t ist4 : 64;
+ uint64_t ist5 : 64;
+ uint64_t ist6 : 64;
+ uint64_t ist7 : 64;
+ uint64_t : 64;
+ uint64_t : 16;
+ uint64_t iopb : 16;
+} __attribute__((packed));
+
+// tss entry
+static volatile struct tss tss;
+
+// gdt entries
+extern volatile uint8_t GDT[];
+static volatile struct sys_seg_descriptor *GDT_TSS;
+
+// kernel stack pointer
+static char interrupt_stack[PAGE_SIZE * 2];
+
+void tss_init(void)
+{
+ uint64_t base = (uint64_t)&tss;
+ uint64_t limit = sizeof tss - 1;
+
+ // setup tss entry
+ memsetv(&tss, 0, sizeof(struct tss));
+ tss.rsp0 = (uint64_t)interrupt_stack + sizeof(interrupt_stack);
+
+ // map tss into gdt
+ GDT_TSS = (volatile struct sys_seg_descriptor *)(GDT + 0x28);
+ memsetv(GDT_TSS, 0, sizeof(struct sys_seg_descriptor));
+ GDT_TSS->limit0_15 = limit & 0xFFFF;
+ GDT_TSS->base0_15 = base & 0xFFFF;
+ GDT_TSS->base16_23 = (base >> 16) & 0xFF;
+ GDT_TSS->type = 0x9;
+ GDT_TSS->DPL = 0;
+ GDT_TSS->present = 1;
+ GDT_TSS->limit16_19 = (limit >> 16) & 0xF;
+ GDT_TSS->available = 0;
+ GDT_TSS->gran = 0;
+ GDT_TSS->base24_31 = (base >> 24) & 0xFF;
+ GDT_TSS->base32_63 = (base >> 32) & 0xFFFFFFFF;
+
+ tss_flush();
+}
+
+void tss_set_stack(uint64_t stack)
+{
+ tss.rsp0 = stack;
+}
diff --git a/kernel/cpu/tss.h b/kernel/cpu/tss.h
new file mode 100644
index 0000000..f17b619
--- /dev/null
+++ b/kernel/cpu/tss.h
@@ -0,0 +1,31 @@
+/**
+ * @file tss.h
+ *
+ * @author Freya Murphy <freya@freyacat.org>
+ *
+ * TSS functions
+ */
+
+#ifndef TSS_H_
+#define TSS_H_
+
+#define TSS_REMAP_OFFSET 0x20
+
+#include <stdint.h>
+
+/**
+ * Load the TSS selector
+ */
+void tss_init(void);
+
+/**
+ * Flush the tss
+ */
+void tss_flush(void);
+
+/**
+ * Set the kernel stack pointer in the tss
+ */
+void tss_set_stack(uint64_t stack);
+
+#endif /* tss.h */