Commit Diff


commit - e5731e19a513e6a92d2b1d5dd1e57d1ef9c0a632
commit + 17683e896fc6162a038d5fb2711ca94055188dfb
blob - f1119d53a193b4a502931fdab8067c0e0c8ea8bf
blob + 89788503a89a7d78c692d45b4e8240c5b2eaa64f
--- alpha/main.c
+++ alpha/main.c
@@ -4,6 +4,7 @@
 #include "syscalls/syscalls.h"
 
 #define MAX_TASKS	64
+#define XHCI_ENTRY	0xC00000
 
 struct task {
 	u8 assigned;
@@ -15,17 +16,24 @@ struct task {
 static struct task tasks[MAX_TASKS];
 
 static void send_msg(const u8 *);
-static struct task* task_new(void);
+static struct task* task_new(void *);
 
 void
 alpha_main(struct mmap *km)
 {
-	struct task *p = task_new();
+	struct task *t = task_new((void *)XHCI_ENTRY);
+	struct sysc_context_switch scs;
 
-	if (p == nil)
-		send_msg("Alpha: failed to create task!\n");
+	if (t == nil)
+		send_msg("alpha: failed to create task!\n");
 
-	send_msg("Alpha: running\n");
+	send_msg("alpha: running\n");
+
+	scs.sysc.type = SYSC_CONTEXT_SWITCH;
+	scs.threadid = t->thread;
+
+	sys_send((struct sysc *)&scs);
+
 	for (;;);
 }
 
@@ -39,11 +47,22 @@ send_msg (const u8 *msg)
 }
 
 static struct task*
-task_new()
+task_new(void *entry)
 {
+	struct sysc_new_thread snt;
+
+	snt.sysc.type = SYSC_NEW_THREAD;
+	snt.entry = entry;
+
 	for (int i = 0; i < MAX_TASKS; i++) {
 		if (tasks[i].assigned == 0) {
+			sys_send((struct sysc *)&snt);
+
+			if (snt.retid == -1)
+				break;
+
 			tasks[i].assigned = 1;
+			tasks[i].thread = snt.retid;
 			return &tasks[i];
 		}
 	}
blob - bffe5353e7d660182869ce421266cdebae9f98f8
blob + 206e351a6d3de7a304a5f92746e4f0296d04920a
--- boot.s
+++ boot.s
@@ -8,6 +8,8 @@ start:
 	; Safety first!
 	xor ax, ax
 	mov ds, ax
+	mov es, ax
+	mov ss, ax
 	mov sp, 0x7c00 ; Stack under boot sector
 
 	; Save drive on boot and check LBA support
blob - a807dab563e01d327f6db6396f87182ce01d29fe
blob + ec4e1f9a0f50deb7371b258265b8470d750e8dec
--- boot2.s
+++ boot2.s
@@ -19,6 +19,9 @@ start:
 	mov si, alpha_dap
 	call load_dap
 
+	mov si, xhci_dap
+	call load_dap
+
 	; Loading e820 blocks and values at kernel's entry
 	;
 	; Segmentation is required due to Real Mode limited
@@ -90,6 +93,14 @@ alpha_dap:
 	dw ALPHA_LOAD_ADDR >> 4
 	dq 1 + STAGE2_SECTORS + KERNEL_SECTORS
 
+xhci_dap:
+	db 0x10
+	db 0
+	dw XHCI_SECTORS
+	dw 0
+	dw XHCI_LOAD_ADDR >> 4
+	dq 1 + STAGE2_SECTORS + KERNEL_SECTORS + ALPHA_SECTORS
+
 load_dap:
 	mov dl, [boot_drive]
 	mov ah, 0x42
@@ -208,6 +219,12 @@ protected_mode:
 	mov ecx, (ALPHA_SECTORS * 512) / 4
 	rep movsd
 
+	; Copy xhci
+	mov esi, XHCI_LOAD_ADDR
+	mov edi, XHCI_ENTRY
+	mov ecx, (XHCI_SECTORS * 512) / 4
+	rep movsd
+
 	; Update kernel module
 	mov DWORD [BINFO_KERNEL_ADDR], KERNEL_ENTRY
 	mov DWORD [BINFO_KERNEL_ADDR + 4], KERNEL_SECTORS * 512
@@ -215,6 +232,10 @@ protected_mode:
 	; Update alpha module
 	mov DWORD [BINFO_ALPHA_ADDR], ALPHA_ENTRY
 	mov DWORD [BINFO_ALPHA_ADDR + 4], ALPHA_SECTORS * 32
+
+	; Update xhci module
+	mov DWORD [BINFO_XHCI_ADDR], XHCI_ENTRY
+	mov DWORD [BINFO_XHCI_ADDR + 4], XHCI_SECTORS * 32
 	
 	; Check for longmode support
 	mov eax, 0x80000000
@@ -334,6 +355,7 @@ long_phase:
 
 	mov rsp, 0x90000
 	mov rdi, BINFO_ADDR ; Kernel info
+	movzx rsi, byte [abs boot_drive]
 
 	mov rax, KERNEL_ENTRY
 	jmp rax
@@ -343,7 +365,7 @@ align 512, db 0
 end:
 
 STAGE2_SECTORS equ (end - start) / 512
-E820_COUNT_ADDR equ BINFO_ALPHA_ADDR + 8
+E820_COUNT_ADDR equ BINFO_XHCI_ADDR + 8
 E820_PTR_ADDR equ E820_COUNT_ADDR + 8
 E820_BLOCK_ADDR equ E820_PTR_ADDR + 8
 
blob - 8a3993143a938b35c65caf3c670a52119187d2d2
blob + 56896c243a94edf9e13fba720973564503dbf7c1
--- build.sh
+++ build.sh
@@ -22,6 +22,10 @@ ALPHA_BIN=alpha/alpha.bin
 ALPHA_SIZE=$(wc -c < $ALPHA_BIN)
 ALPHA_SECTORS=$(( (ALPHA_SIZE + SECTOR_SIZE - 1) / SECTOR_SIZE))
 
+XHCI_BIN=servers/xhci/xhci.bin
+XHCI_SIZE=$(wc -c < $XHCI_BIN)
+XHCI_SECTORS=$(( (XHCI_SIZE + SECTOR_SIZE - 1) / SECTOR_SIZE))
+
 echo "$OS_NAME: building"
 
 nasm -f elf64 -o io.o $KERNEL_DIR/io.s
@@ -48,7 +52,7 @@ ld \
 	sysentry.o kthreads.o
 
 KSIZE=$(wc -c < kerneli.bin)
-KSECTORS=$(( (KSIZE + SECTOR_SIZE - 1) / SECTOR_SIZE + 1)) # Extra sector
+KSECTORS=$(( (KSIZE + SECTOR_SIZE - 1) / SECTOR_SIZE + 2)) # Extra sector
 KSIZE=$((KSECTORS * SECTOR_SIZE))
 
 cat kerneli.bin /dev/zero | dd of=kernel.bin bs=$KSIZE count=1
@@ -58,11 +62,15 @@ nasm \
 	-D ALPHA_SECTORS=$ALPHA_SECTORS \
 	-D KERNEL_ENTRY=$KERNEL_ENTRY \
 	-D ALPHA_ENTRY=$ALPHA_ENTRY \
+	-D XHCI_ENTRY=$XHCI_ENTRY \
+	-D XHCI_SECTORS=$XHCI_SECTORS \
 	-D BINFO_ADDR=$BINFO_ADDR \
 	-D KERNEL_LOAD_ADDR=$KERNEL_LOAD_ADDR \
 	-D ALPHA_LOAD_ADDR=$ALPHA_LOAD_ADDR \
+	-D XHCI_LOAD_ADDR=$XHCI_LOAD_ADDR \
 	-D BINFO_KERNEL_ADDR=$BINFO_KERNEL_ADDR \
 	-D BINFO_ALPHA_ADDR=$BINFO_ALPHA_ADDR \
+	-D BINFO_XHCI_ADDR=$BINFO_XHCI_ADDR \
 	boot2.s -o boot2.bin
 
 STAGE2_SIZE=$(wc -c < boot2.bin)
@@ -71,21 +79,12 @@ STAGE2_SIZE=$((STAGE2_SECTORS * SECTOR_SIZE))
 
 BOOT_SECTORS=$((STAGE2_SECTORS + 1)) # Boot sector is 1 sector so we add
 BOOT_SIZE=$((BOOT_SECTORS * SECTOR_SIZE))
-IMGSIZE=$(((KSECTORS * SECTOR_SIZE) + BOOT_SIZE + ALPHA_SIZE))
+IMGSIZE=$(((KSECTORS * SECTOR_SIZE) + BOOT_SIZE + ALPHA_SIZE + XHCI_SIZE))
 
-nasm \
-	-D STAGE2_SECTORS=$STAGE2_SECTORS \
-	-D KERNEL_SECTORS=$KSECTORS \
-	-D ALPHA_SECTORS=$ALPHA_SECTORS \
-	-D KERNEL_LOAD_ADDR=$KERNEL_LOAD_ADDR \
-	-D ALPHA_LOAD_ADDR=$ALPHA_LOAD_ADDR  \
-	-D BINFO_ADDR=$BINFO_ADDR \
-	-D BINFO_KERNEL_ADDR=$BINFO_KERNEL_ADDR \
-	-D BINFO_ALPHA_ADDR=$BINFO_ALPHA_ADDR \
-	boot.s -o boot.bin
+nasm -D STAGE2_SECTORS=$STAGE2_SECTORS boot.s -o boot.bin
 
 cat boot2.bin /dev/zero | dd of=boot2i.bin bs=$STAGE2_SIZE count=1
-cat boot.bin boot2i.bin kernel.bin $ALPHA_BIN /dev/zero | dd of=$OS_NAME bs=$IMGSIZE count=1
+cat boot.bin boot2i.bin kernel.bin $ALPHA_BIN $XHCI_BIN /dev/zero | dd of=$OS_NAME bs=$IMGSIZE count=1
 
 # This is so qemu doesn't bother us but really the OS is not that size
 if (( IMG_SIZE < 0x100000 )) then
blob - 954a99bc381daa4b70b5b6f0b7dd6fae9e8d1040
blob + fa5d1ad7b193b5c6d07d406a9aaaac250743e385
--- include
+++ include
@@ -23,3 +23,4 @@ XHCI_ENTRY=0xC00000
 BINFO_ADDR=0x20000
 BINFO_KERNEL_ADDR=$((BINFO_ADDR))
 BINFO_ALPHA_ADDR=$((BINFO_KERNEL_ADDR + 8))
+BINFO_XHCI_ADDR=$((BINFO_ALPHA_ADDR + 8))
blob - 6c27160322ee571ec650f882cdcdf8100e2b06d0
blob + c03eeaa10e4b75159709cacf3ae014e5987bf1f1
--- kernel/idt.c
+++ kernel/idt.c
@@ -1,6 +1,8 @@
 #include "kdebug.h"
 #include "types.h"
 
+#define APIC_EOI_REG ((volatile u32*)0xFEE000B0)
+
 struct idt_desc {
 	u16 offset_1;
 	u16 selector;
@@ -16,12 +18,13 @@ struct idt_ptr {
 	u64 base;
 } __packed;
 
-static struct idt_desc desc[32];
+static struct idt_desc desc[256];
 
 void debug_exception_handler(void);
 void page_fault_handler(void);
 void double_fault_handler(void);
 void general_protection_handler(void);
+void timer_handler(void);
 
 void load_idt(struct idt_ptr *); /* set lidt.s */
 
@@ -69,6 +72,15 @@ idt_init()
 	desc[14].offset_3 = (u32)(((u64)(page_fault_handler) >> 32));
 	desc[14].zero = 0;
 
+	// TIMER INTERRUPT (custom)
+	desc[0x20].offset_1 = (u16)((u64)(timer_handler) & 0xffff);
+	desc[0x20].selector = 0x08;
+	desc[0x20].ist = 0;
+	desc[0x20].type_attributes = 0x8E;
+	desc[0x20].offset_2 = (u16)(((u64)(timer_handler) & 0xffff0000) >> 16);
+	desc[0x20].offset_3 = (u32)(((u64)(timer_handler) >> 32));
+	desc[0x20].zero = 0;
+
 	load_idt(&ptr);
 
 	return 0;
@@ -97,3 +109,13 @@ general_protection_handler_c()
 {
 	kprint("#GP interrupt\n");
 }
+
+u64 tint = 0;
+
+void
+timer_handler_c()
+{
+	kprint("Timer interrupt: "); kprinti(tint++); kprint("\n");
+
+	*APIC_EOI_REG = 0; // Tells register interrupt was received
+}
blob - 088c815aa876b54b6d2a83a4386af126be315d9e
blob + 5ebcf6e1480e25bb0cbe91bb902bdc7fb8c72303
--- kernel/kmain.c
+++ kernel/kmain.c
@@ -11,7 +11,7 @@
 static void kloop(struct module *, struct mmap *);
 
 void
-kmain(struct kinfo *kinfo)
+kmain(struct kinfo *kinfo, u8 drive)
 {
 	struct mmap *ammap;
 	kprint("Only 10 remote holes in a heck of a long time!\n");
@@ -23,7 +23,6 @@ kmain(struct kinfo *kinfo)
 
 	kprint("GDT configured!\n");
 
-	kpic_setup();
 	syscalls_init();
 
 	if (idt_init() == -1) {
@@ -39,15 +38,13 @@ kmain(struct kinfo *kinfo)
 		return;
 	}
 
+	kpic_setup();
+
 	kprint("Page tables configured!\n");
 	kprint("Free memory U/S bit set!\n");
 	kloop(&kinfo->modules[1], ammap);
 }
 
-// Defined in switch.s
-void start_alpha(struct mmap *ammap, struct thread *thread);
-void switch_context(struct thread *old, struct thread *new);
-
 static void
 kloop(struct module *amodule, struct mmap *ammap)
 {
@@ -55,10 +52,8 @@ kloop(struct module *amodule, struct mmap *ammap)
 
 	if (athread == nil) {
 		kprint("Failed to create thread\n");
-		goto repeat;
+		repeat: goto repeat;
 	}
 
-	kprint("Jumping to alpha!\n");
-	start_alpha(ammap, athread);
-	repeat: goto repeat;
+	thread_schedule(ammap, athread);
 }
blob - 51f6b639c87130e8f972813419c6eddbccfa9829
blob + 3334258cf25f3e68aae8d615009bfc9bba95d272
--- kernel/kmmap.c
+++ kernel/kmmap.c
@@ -132,6 +132,8 @@ kmmap_init(struct kinfo *kinfo)
 
 	struct module *kmodule = &kinfo->modules[0];
 	struct module *amodule = &kinfo->modules[1];
+	struct module *xhci_module = &kinfo->modules[2];
+	u64 nmodules = sizeof(kinfo->modules) / sizeof(*kinfo->modules);
 	u64 memsize = 0;
 
 	for (u64 i = 0; i < kinfo->e820_bcount; i++) {
@@ -172,11 +174,14 @@ kmmap_init(struct kinfo *kinfo)
 	for (u64 i = 0; i < kmodule->entry + kmodule->size; i += PAGE_SIZE)
 		set_bitmap(i);
 
-	// Alpha module is occupied
+	// Occupy other modules
 
-	for (u64 i = amodule->entry; i < amodule->entry + amodule->size; i += PAGE_SIZE)
-		set_bitmap(i);
+	for (u64 i = 1; i < nmodules; i++) {
+		struct module *m = &kinfo->modules[i];
 
+		for (u64 j = m->entry; j < m->entry + m->size; j += PAGE_SIZE)
+			set_bitmap(j);
+	}
 
 	PageTableCount = kminfo.frames;
 	PageDirCount = (PageTableCount + P_ENTRIES - 1) / P_ENTRIES;
@@ -214,11 +219,15 @@ kmmap_init(struct kinfo *kinfo)
 	if (kminfo.amap == nil)
 		return nil;
 
-	// Changing amodule to user
+	// Changing modules to user mode
 
-	for (u64 i = amodule->entry; i < amodule->entry + amodule->size; i += PAGE_SIZE)
-		kmmap_addr_touser(i);
+	for (u64 i = 1; i < nmodules; i++) {
+		struct module *m = &kinfo->modules[i];
 
+		for (u64 j = m->entry; j < m->entry + m->size; j += PAGE_SIZE)
+			kmmap_addr_touser(j);
+	}
+
 	kmmap_usermode();
 
 	return kminfo.amap;
blob - 5275b82f081415d89d7f8233b0b66fc381ddc828
blob + 22b22d08c60f36ee2e5a4ddf1e2557d122dde1f1
--- kernel/kmmap.h
+++ kernel/kmmap.h
@@ -9,7 +9,7 @@ struct module {
 };
 
 struct kinfo {
-	struct module modules[2];
+	struct module modules[3];
 	u64 e820_bcount;
 	struct e820h *e820_headers;
 };
blob - 23604f521342f4d853c24fc4cbe9630ac1979487
blob + 5b711f5a26c269a6ec68fd7615236c460ef62d09
--- kernel/kpic.c
+++ kernel/kpic.c
@@ -2,14 +2,76 @@
 #include "types.h"
 #include "kdebug.h"
 
+#define APIC_TIMER_CUR 	((u32 *)0xFEE00390)
+#define APIC_TIMER_INI	((u32 *)0xFEE00380)
+#define APIC_TIMER_DIV 	((u32 *)0xFEE003E0)
+#define APIC_TIMER_LVT	((u32 *)0xFEE00320)
+
+#define APIC_LVT_PERIODIC 0x20000
+#define TIMER_VECTOR 0x20
+
+#define IA32_APIC_BASE_MSR 0x1B
+#define IA32_APIC_BASE_MSR_ENABLE 0x800
+
 #define PIC1		0x20
 #define PIC2		0xA0
 #define PIC1_DATA	(PIC1+1)
 #define PIC2_DATA	(PIC2+1)
 
-void
-kpic_setup()
+// See sysentry.s
+u64 rdmsr(u32 msr);
+void wrmsr(u32 msr, u64 value);
+
+static void apic_setup_timer(void);
+
+static void
+pic_disable()
 {
 	outb(PIC1_DATA, 0xff);
 	outb(PIC2_DATA, 0xff);
 }
+
+// Enable local APIC for a core
+
+void
+kpic_setup()
+{
+	u64 apic_base;
+	u32 *spivptr;
+	u32 spiv;
+
+	pic_disable();
+
+	// Enable local APIC
+
+	apic_base = rdmsr(IA32_APIC_BASE_MSR);
+
+	apic_base |= IA32_APIC_BASE_MSR_ENABLE;
+
+	wrmsr(IA32_APIC_BASE_MSR, apic_base);
+
+	// Start receiving interrupts
+	
+	spivptr = (u32 *)0xFEE000F0;
+	spiv = *spivptr;
+
+	spiv |= 0x100;
+	spiv |= 0xFF;
+
+	*spivptr = spiv;
+
+	apic_setup_timer();
+}
+
+static void
+apic_setup_timer()
+{
+	// Clock divider
+	*APIC_TIMER_DIV = 0x03;
+
+	// Setup register
+	*APIC_TIMER_LVT = APIC_LVT_PERIODIC | TIMER_VECTOR;
+
+	// Initial countdown
+	*APIC_TIMER_INI = 10000000;
+}
blob - ad5151966c615d05cc3610d39e1438f46e7e5c1d
blob + 2accf334df9298693dd6ee50980ab5275610c0a0
--- kernel/kthreads.c
+++ kernel/kthreads.c
@@ -6,6 +6,7 @@
 #define MAX_USER_THREADS	64
 
 static struct thread uthreads[MAX_USER_THREADS];
+static struct thread *cthread;
 
 struct thread*
 thread_create(void (*entry)(void))
@@ -27,7 +28,6 @@ thread_create(void (*entry)(void))
 		return nil;
 	}
 
-	kprint("Creating thread\n");
 	thread->base = allocate_memory(PAGE_SIZE);
 
 	if (thread->base == nil) {
@@ -53,3 +53,51 @@ thread_create(void (*entry)(void))
 
 	return thread;
 }
+
+s64 
+thread_getuid(struct thread *th)
+{
+	for (int i = 0; i < MAX_USER_THREADS; i++) {
+		if (&uthreads[i] == th)
+			return i;
+	}
+
+	return -1;
+}
+
+// This is defined in switch.s
+
+void start_alpha(struct mmap *ammap, struct thread *thread);
+void switch_context(struct thread *old, struct thread *new);
+
+void
+thread_schedule(struct mmap *ammap, struct thread *th)
+{
+	cthread = th;
+	start_alpha(ammap, th);
+
+	repeat: goto repeat;
+}
+
+void
+thread_switch(struct thread *th)
+{
+	struct thread *othread;
+
+	if (th == cthread) {
+		kprint("Huh?\n");
+		return;
+	}
+
+	othread = cthread;
+	cthread = th;
+	switch_context(othread, cthread);
+}
+
+struct thread*
+thread_get_uthread(u64 id)
+{
+	if (id < MAX_USER_THREADS && uthreads[id].assigned == 1)
+		return &uthreads[id];
+	return nil;
+}
blob - 911e2269adde81f02054325a01a8d4f4c36b56a3
blob + b962ab43fc5883d0f878a41c640fde2977e15761
--- kernel/kthreads.h
+++ kernel/kthreads.h
@@ -1,10 +1,23 @@
 #pragma once
 
+#include "kmmap.h"
+
+enum thread_state {
+	THREAD_READY,
+	THREAD_RUNNING,
+};
+
 struct thread {
 	u64 *base;
 	u64 *top;
 	u64 rsp;
+
 	u8 assigned;
+	enum thread_state sate;
 };
 
 struct thread *thread_create(void (*entry)(void));
+s64 thread_getuid(struct thread *th);
+void thread_schedule(struct mmap *, struct thread *);
+void thread_switch(struct thread *);
+struct thread *thread_get_uthread(u64 id);
blob - 956758d0e646b87b571b9d62ab69efe230287cfb
blob + 086afdfc65590671baca91ac1a342feeec475041
--- kernel/lidt.s
+++ kernel/lidt.s
@@ -14,6 +14,9 @@ extern double_fault_handler_c
 global general_protection_handler
 extern general_protection_handler_c
 
+global timer_handler
+extern timer_handler_c
+
 load_idt:
 	lidt [rdi]
 	ret
@@ -33,3 +36,7 @@ double_fault_handler:
 general_protection_handler:
 	call general_protection_handler_c
 	hlt
+
+timer_handler:
+	call timer_handler_c
+	iretq
blob - 96cdf2ec8e0f43812f162b177f0270aa9aa8fb4a
blob + 97983d5a50a7c11a00eb9b8167610e5a3babe57c
--- kernel/syscalls.c
+++ kernel/syscalls.c
@@ -1,5 +1,6 @@
 #include "types.h"
 #include "kdebug.h"
+#include "kthreads.h"
 #include "syscalls/syscalls.h"
 
 #define IA32_EFER	0xC0000080
@@ -35,12 +36,46 @@ syscall_echo_h(struct sysc_echo *echo)
 }
 
 void
+syscall_new_thread_h(struct sysc_new_thread *nthread)
+{
+	struct thread *th = thread_create(nthread->entry);
+	s64 threadid;
+
+	if (th == nil)
+		kprint("failed to create thread from syscall!\n");
+
+	threadid = thread_getuid(th);
+	nthread->retid = threadid;
+
+	kprint("Thread (id="); kprinti(threadid); kprint(") created!\n");
+}
+
+void
+syscall_context_switch_h(struct sysc_context_switch *scs)
+{
+	struct thread *cthread = thread_get_uthread(scs->threadid);
+
+	if (cthread == nil) {
+		kprint("No current thread :/\n");
+		return;
+	}
+
+	thread_switch(cthread);
+}
+
+void
 syscall_handler(struct sysc *call)
 {
 	switch (call->type) {
 	case SYSC_ECHO:
 		syscall_echo_h((struct sysc_echo *)call);
 		break;
+	case SYSC_NEW_THREAD:
+		syscall_new_thread_h((struct sysc_new_thread *)call);
+		break;
+	case SYSC_CONTEXT_SWITCH:
+		syscall_context_switch_h((struct sysc_context_switch *)call);
+		break;
 	default:
 		break;
 	}
blob - 3d5477f9fc4ebb1e5081b30b5d0558fc90973efc
blob + a63060857332e965651f8484c979a5233d2346eb
--- servers/xhci/main.c
+++ servers/xhci/main.c
@@ -1,8 +1,22 @@
 #include "types.h"
 #include "syscalls/syscalls.h"
 
+static void send_msg (const u8 *msg);
+
 void
 xhci_main()
 {
+	send_msg("xhci: driver started\n");
+
 	for (;;);
 }
+
+static void
+send_msg (const u8 *msg)
+{
+	struct sysc_echo echo;
+	echo.sysc.type = SYSC_ECHO;
+	echo.msg = msg;
+	sys_send((struct sysc *)&echo);
+}
+
blob - f4d21d3b8483f50020a2d4112286b187c1cd34d5
blob + 4ed19f7d29b986549d6fec7d04fe784cbd0226cc
--- syscalls/syscalls.h
+++ syscalls/syscalls.h
@@ -2,6 +2,9 @@
 
 enum sysc_type {
 	SYSC_ECHO,
+	SYSC_NEW_THREAD,
+	SYSC_FREE_THREAD,
+	SYSC_CONTEXT_SWITCH, // This shouldn't be a thing its for testing before APIC and thread states
 };
 
 struct sysc {
@@ -13,5 +16,23 @@ struct sysc_echo {
 	const char *msg;
 };
 
+struct sysc_new_thread {
+	struct sysc sysc;
+	void *entry;
+	u64 size; // Unused for now
+
+	s64 retid; // The threadId returned
+};
+
+struct sysc_free_thread {
+	struct sysc sysc;
+	u64 id;
+};
+
+struct sysc_context_switch {
+	struct sysc sysc;
+	u64 threadid;
+};
+
 void sys_send(struct sysc *);
 void sys_recv(void);