summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mos/sys/arch/x86_64/cpu/idt.c38
-rw-r--r--mos/sys/arch/x86_64/cpu/locore.S3
-rw-r--r--mos/sys/arch/x86_64/cpu/trap.c16
-rw-r--r--mos/sys/arch/x86_64/cpu/vector.S214
-rw-r--r--mos/sys/inc/arch/x86_64/frame.h40
-rw-r--r--mos/sys/inc/arch/x86_64/idt.h69
-rw-r--r--mos/sys/inc/arch/x86_64/kfence.h31
-rw-r--r--mos/sys/inc/kern/panic.h18
-rw-r--r--mos/sys/kern/kern_panic.c29
-rw-r--r--usr/sdk/inc/sdk/defs.h1
10 files changed, 459 insertions, 0 deletions
diff --git a/mos/sys/arch/x86_64/cpu/idt.c b/mos/sys/arch/x86_64/cpu/idt.c
new file mode 100644
index 0000000..569fe71
--- /dev/null
+++ b/mos/sys/arch/x86_64/cpu/idt.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#include <sdk/defs.h>
+#include <md/idt.h>
+#include <md/gdt.h>
+
+ALIGN(8) static IDT_GATE idt[256];
+static IDT_DESCRIPTOR idtr = {
+ .limit = sizeof(idt) - 1,
+ .offset = (UPTR)&idt[0]
+};
+
+void
+md_idt_set_entry(UBYTE vector, UPTR isr, UBYTE type, UBYTE ist)
+{
+ IDT_GATE *gate = &idt[vector];
+
+ gate->offset_low = isr & 0xFFFF;
+ gate->offset_mid = (isr >> 16) & 0xFFFF;
+ gate->offset_high = (isr >> 32) & 0xFFFFFFFF;
+ gate->p = 1;
+ gate->dpl = (type == IDT_USER_GATE) ? 3 : 0;
+ gate->zero = 0;
+ gate->zero1 = 0;
+ gate->reserved = 0;
+ gate->ist = ist;
+ gate->target_cs = GDT_KCODE;
+ gate->type = type;
+}
+
+void
+md_idt_load(void)
+{
+ ASM("lidt %0" :: "m" (idtr) : "memory");
+}
diff --git a/mos/sys/arch/x86_64/cpu/locore.S b/mos/sys/arch/x86_64/cpu/locore.S
index 5fdd741..b0eb068 100644
--- a/mos/sys/arch/x86_64/cpu/locore.S
+++ b/mos/sys/arch/x86_64/cpu/locore.S
@@ -15,6 +15,9 @@ _start:
lea g_GDTR(%rip), %rdi /* BSP GDTR base */
call md_gdt_load /* Load it */
+ call md_set_vectors /* Set interrupt vectors */
+ call md_idt_load /* Load the IDT */
+
xor %rbp, %rbp /* Terminate callstack */
call kern_main /* Call kernel main */
diff --git a/mos/sys/arch/x86_64/cpu/trap.c b/mos/sys/arch/x86_64/cpu/trap.c
new file mode 100644
index 0000000..bacf9c2
--- /dev/null
+++ b/mos/sys/arch/x86_64/cpu/trap.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#include <kern/panic.h>
+#include <md/frame.h>
+
+/* Forward declaration */
+void trap_dispatch(TRAPFRAME *tf);
+
+void
+trap_dispatch(TRAPFRAME *tf)
+{
+ panic("fatal vector %x\n", tf->vector);
+}
diff --git a/mos/sys/arch/x86_64/cpu/vector.S b/mos/sys/arch/x86_64/cpu/vector.S
new file mode 100644
index 0000000..6d29afb
--- /dev/null
+++ b/mos/sys/arch/x86_64/cpu/vector.S
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#include <md/idt.h>
+#include <md/kfence.h>
+
+ .macro set_trap vector, isr, ist
+ mov $\vector, %rdi
+ lea \isr(%rip), %rsi
+ mov $IDT_TRAP_GATE, %rdx
+ mov $\ist, %rcx
+ call md_idt_set_entry
+ .endm
+
+ .macro push_trapframe vector
+ .if \vector == 10 || \vector == 11 || \vector == 12 || \vector == 13 \
+ || \vector == 14
+ subq $8, %rsp
+ .endif
+
+ push %rax
+ push %rbx
+ push %rcx
+ push %rdx
+ push %rsi
+ push %rdi
+ push %rbp
+ push %r8
+ push %r9
+ push %r10
+ push %r11
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ push $\vector
+ .endm
+
+ .text
+ .globl md_set_vectors
+md_set_vectors:
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+ push %rbx
+ push %rbp
+
+ set_trap 0x00, diverr, 0
+ set_trap 0x01, debug_except, 0
+ set_trap 0x02, nmi, 0
+ set_trap 0x03, breakpoint, 0
+ set_trap 0x04, overflow, 0
+ set_trap 0x05, bound_range, 0
+ set_trap 0x06, invalid_tss, 0
+ set_trap 0x07, no_coproc, 0
+ set_trap 0x08, double_fault, 0
+ set_trap 0x0A, invalid_tss, 0
+ set_trap 0x0B, seg_np, 0
+ set_trap 0x0C, ss_fault, 0
+ set_trap 0x0D, gpf, 0
+ set_trap 0x0E, page_fault, 0
+
+ pop %rbp
+ pop %rbx
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ retq
+
+ .align 8
+diverr:
+ KFENCE
+ push_trapframe 0x00
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+debug_except:
+ KFENCE
+ push_trapframe 0x1
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+nmi:
+ KFENCE
+ push_trapframe 0x2
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+breakpoint:
+ KFENCE
+ push_trapframe 0x3
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+overflow:
+ KFENCE
+ push_trapframe 0x4
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+bound_range:
+ KFENCE
+ push_trapframe 0x5
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+invl_opc:
+ KFENCE
+ push_trapframe 0x6
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+no_coproc:
+ KFENCE
+ push_trapframe 0x7
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE
+1: cli
+ hlt
+ jmp 1b
+
+double_fault:
+ KFENCE_EC
+ push_trapframe 0x8
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+
+invalid_tss:
+ KFENCE_EC
+ push_trapframe 0xA
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+
+seg_np:
+ KFENCE_EC
+ push_trapframe 0xB
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+
+ss_fault:
+ KFENCE_EC
+ push_trapframe 0xC
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+
+gpf:
+ KFENCE_EC
+ push_trapframe 0xD
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+
+page_fault:
+ KFENCE_EC
+ push_trapframe 0xE
+ mov %rsp, %rdi
+ call trap_dispatch
+ KFENCE_EC
+1: cli
+ hlt
+ jmp 1b
+ hlt
diff --git a/mos/sys/inc/arch/x86_64/frame.h b/mos/sys/inc/arch/x86_64/frame.h
new file mode 100644
index 0000000..5908d93
--- /dev/null
+++ b/mos/sys/inc/arch/x86_64/frame.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#ifndef _MACHINE_FRAME_H_
+#define _MACHINE_FRAME_H_ 1
+
+#include <sdk/types.h>
+#include <sdk/defs.h>
+
+/*
+ * Processor state
+ */
+typedef struct {
+ UQUAD vector;
+ UQUAD r15;
+ UQUAD r14;
+ UQUAD r13;
+ UQUAD r12;
+ UQUAD r11;
+ UQUAD r10;
+ UQUAD r9;
+ UQUAD r8;
+ UQUAD rbp;
+ UQUAD rdi;
+ UQUAD rsi;
+ UQUAD rbx;
+ UQUAD rdx;
+ UQUAD rcx;
+ UQUAD rax;
+ UQUAD error_code;
+ UQUAD rip;
+ UQUAD cs;
+ UQUAD rflags;
+ UQUAD rsp;
+ UQUAD ss;
+} PACKED TRAPFRAME;
+
+#endif /* !_MACHINE_FRAME_H_ */
diff --git a/mos/sys/inc/arch/x86_64/idt.h b/mos/sys/inc/arch/x86_64/idt.h
new file mode 100644
index 0000000..aa03925
--- /dev/null
+++ b/mos/sys/inc/arch/x86_64/idt.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#ifndef _MACHINE_IDT_H_
+#define _MACHINE_IDT_H_ 1
+
+#ifndef __ASSEMBLER__
+#include <sdk/types.h>
+#include <sdk/defs.h>
+#endif /* !__ASSEMBLER__ */
+
+#define IDT_INT_GATE 0x8E
+#define IDT_TRAP_GATE 0x8F
+#define IDT_USER_GATE 0xEE
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Represents a 64-bit interrupt gate descriptor
+ * for the x86_64 architecture. See section 6.14.1
+ * for more information.
+ */
+typedef struct {
+ USHORT offset_low;
+ USHORT target_cs;
+ UBYTE ist : 3;
+ UBYTE zero : 5;
+ UBYTE type : 4;
+ UBYTE zero1 : 1;
+ UBYTE dpl : 2;
+ UBYTE p : 1;
+ USHORT offset_mid;
+ ULONG offset_high;
+ ULONG reserved;
+} IDT_GATE;
+
+/*
+ * This descriptor is loaded into the processor core
+ * for when it needs to reference a gate descriptor.
+ *
+ * @limit: IDT limit
+ * @offset: Base address of IDT
+ */
+typedef struct {
+ USHORT limit;
+ UPTR offset;
+} PACKED IDT_DESCRIPTOR;
+
+/*
+ * Set an interrupt gate descriptor within the
+ * interrupt descriptor table.
+ *
+ * @vector: Interrupt vector to set
+ * @isr: Interrupt service routine
+ * @type: Gate descriptor type
+ * @ist: Interrupt stack table index to use
+ */
+void md_idt_set_entry(UBYTE vector, UPTR isr, UBYTE type, UBYTE ist);
+
+/*
+ * Load the interrupt descriptor table into the current
+ * processor core.
+ */
+void md_idt_load(void);
+
+#endif /* !__ASSEMBLER__ */
+#endif /* !_MACHINE_IDT_H_ */
diff --git a/mos/sys/inc/arch/x86_64/kfence.h b/mos/sys/inc/arch/x86_64/kfence.h
new file mode 100644
index 0000000..f44336c
--- /dev/null
+++ b/mos/sys/inc/arch/x86_64/kfence.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#ifndef _MACHINE_KFENCE_H_
+#define _MACHINE_KFENCE_H_ 1
+
+/*
+ * Kernel fence for interrupt entries that do
+ * not have an error code
+ */
+#define KFENCE \
+ testq $0x3, 8(%rsp) ; \
+ jz 1f ; \
+ lfence ; \
+ swapgs ; \
+1: nop
+
+/*
+ * Kernel fence for interrupt entries that
+ * have an error code
+ */
+#define KFENCE_EC \
+ testq $0x3, 16(%rsp) ; \
+ jz 1f ; \
+ lfence ; \
+ swapgs ; \
+1: nop
+
+#endif /* !_MACHINE_KFENCE_H_ */
diff --git a/mos/sys/inc/kern/panic.h b/mos/sys/inc/kern/panic.h
new file mode 100644
index 0000000..a7aac0e
--- /dev/null
+++ b/mos/sys/inc/kern/panic.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#ifndef _KERN_PANIC_H_
+#define _KERN_PANIC_H_ 1
+
+#include <sdk/types.h>
+#include <sdk/stdarg.h>
+
+/*
+ * Signal to the operator that a severe error has
+ * occurred and the system has been halted.
+ */
+void panic(const char *fmt, ...);
+
+#endif /* !_KERN_PANIC_H_ */
diff --git a/mos/sys/kern/kern_panic.c b/mos/sys/kern/kern_panic.c
new file mode 100644
index 0000000..8f03e6a
--- /dev/null
+++ b/mos/sys/kern/kern_panic.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2025, Ian Moffett.
+ * Provided under the BSD-3 clause.
+ */
+
+#include <sdk/string.h>
+#include <kern/panic.h>
+#include <kern/spinlock.h>
+#include <kern/trace.h>
+#include <mu/cpu.h>
+
+static SPINLOCK panic_sync;
+static char panic_buf[256];
+static va_list ap;
+
+void
+panic(const char *fmt, ...)
+{
+ spinlock_acquire(&panic_sync, SPINLOCK_IRQMUT);
+ va_start(ap, fmt);
+
+ vsnprintf(panic_buf, sizeof(panic_buf), fmt, ap);
+ trace("panic: ");
+ trace(panic_buf);
+
+ for (;;) {
+ mu_cpu_halt();
+ }
+}
diff --git a/usr/sdk/inc/sdk/defs.h b/usr/sdk/inc/sdk/defs.h
index 3d4ccfc..1b7cd23 100644
--- a/usr/sdk/inc/sdk/defs.h
+++ b/usr/sdk/inc/sdk/defs.h
@@ -11,5 +11,6 @@
#define ALIGN(n) ATTR(aligned((n)))
#define NO_RETURN ATTR(no_return)
#define ALWAYS_INLINE ATTR(always_inline)
+#define PACKED ATTR(packed)
#endif /* !_SDK_DEFS_H_ */