Commit Diff


commit - a1ebf18642867950f088fe721bdf1742f88bec39
commit + 7abd0aa7f90dfa1a7147252f69971b23d6a119c9
blob - ba37bbc9df29c2c46b0d4363a0f829bc8971717c
blob + 328bcaa3fc244f7ebb9b149b20ea0db74ae89291
--- README
+++ README
@@ -15,12 +15,59 @@ Communication among tasks is done through shared buffe
 called seats. When the kernel boots, it takes a set amount
 of seats represented by a fixed size array. These seats are
 all of PAGE_SIZE and can be either vacant or occupied. When
-a task wants to communicate wit another it takes a seat
+a task wants to communicate with another it takes a seat
 and waits before exchanging information.
 
 Fragmentation is solved by moving chunks of innactive
-threads.
+threads. The chunks are all of PAGE_SIZE.
 
+Userspace programs request memory in a different way. When
+compiling a program you specify how much fake dynamic
+memory (FDM) the program needs. The fake memory is added at
+runtime. Hence, memory allocation is based on that memory
+chunk and not a syscall to request pages from the kernel.
+This will force you to tell how much RAM your program
+really needs instead of pretending to be lightweight. Hence,
+when a program does a `malloc` it takes a seat with the
+allocation server which reads the FDM and returns either the
+part needed or and error to say that there is no memory left.
+
+The layout of the operating system image is :
+
+[ boot ] [ identifier ] [ boot 2 ] [ kernel ] [ alpha ] ...
+
+The identifier is a magic number combined with a date and
+time to identify the PCI device used by the boot drive. The
+date and time is passed to the bootloader at compile time.
+The second stage bootloader reads the driver part of it and
+loads it into memory then passes the ident to the kernel.
+The kernel then passes it to the root task which starts the
+PCI server to search for that specific device with the
+ident. Afterwards it starts the driver server and the
+filesystem server to load the remaining needed drivers. This
+makes it so only required drivers are loaded. When the OS
+is installed on a storage device, the image just changes the
+storage type byte in the ident sector.
+
+Each programs in its executable header mentions the resources
+it will use. Programs also can have communication channels
+which ask to reserve seats. Seats are all simplex. There is
+no half-duplex or duplex. Half-duplex and duplex are implemented
+at the userspace level with the reaction of the receiver from
+the sender. The kernel only job is to read seats every timer
+interrupt and wake up the receiver when data is available or
+ignore the packet if there are no receiver. Example of 2 threads
+
+       Seat A                  Seat B
+[ ThreadA => Thread B ] [ ThreadB => ThreadA ]
+
+The behaviour of simplex/duplex/half-duplex is handled by the
+thread through communication. The kernel only job is to wake
+threads. I call this the seat protocol.
+
+The Root Task (alpha) goal is to strip away the header and load
+executable in memory. Essentialy the root task is the loader.
+
 Features:
 
 - Buggy
blob - d68f908015ca22dec2be019261b6b627578b3dab
blob + ec51940dd81dada2c03e09336da14d9ff0129520
--- alpha/build.sh
+++ alpha/build.sh
@@ -4,17 +4,20 @@ set -e
 
 echo "alpha: building"
 
-INCS='-I ../common -I ../'
+INCS='-I ../common -I ../ -I ../kernel'
 
 . ../include
 
-nasm -f elf64 -o syscall.o ../syscalls/syscalls.s
+nasm -f elf64 -o io.o ../kernel/io.s
+
 cc -m64 $CFLAGS -o main.o -c main.c $INCS
+cc -m64 $CFLAGS -o pci.o -c pci.c $INCS
+cc -m64 $CFLAGS -o libc.o -c libc.c $INCS
 
 ld \
 	--defsym=entry=$ALPHA_ENTRY \
 	-T linker.ld $LFLAGS \
-	-o alpha.bin main.o syscall.o
+	-o alpha.bin main.o pci.o libc.o io.o
 
 ALPHA_SIZE=$(wc -c < alpha.bin)
 ALPHA_SECTORS=$(( (ALPHA_SIZE + SECTOR_SIZE - 1) / SECTOR_SIZE))
blob - /dev/null
blob + 3d351992d333c0c5df49bc4885d6bcd0b4f97c92 (mode 644)
--- /dev/null
+++ alpha/libc.c
@@ -0,0 +1,34 @@
+#include "types.h"
+#include "syscalls/syscalls.h"
+
+void (*sys_send)(struct sysc *call) = (void (*)(struct sysc *))SYSC_BELL;
+
+void
+output(const u8 *msg)
+{
+	struct sysc_echo echo;
+	echo.sysc.type = SYSC_ECHO;
+	echo.type = SYSC_ECHO_STRING;
+	echo.msg = msg;
+	sys_send((struct sysc *)&echo);
+}
+
+void
+outputi(u64 i)
+{
+	struct sysc_echo echo;
+	echo.sysc.type = SYSC_ECHO;
+	echo.type = SYSC_ECHO_INTEGER;
+	echo.number = i;
+	sys_send((struct sysc *)&echo);
+}
+
+void
+outputh(u64 i)
+{
+	struct sysc_echo echo;
+	echo.sysc.type = SYSC_ECHO;
+	echo.type = SYSC_ECHO_HEXADECIMAL;
+	echo.number = i;
+	sys_send((struct sysc *)&echo);
+}
blob - 0cedacc0e680a7dd1060bcee065eeaf36a744393
blob + 8c5eb444d30483b9169d4472de388a9f08637b48
--- alpha/main.c
+++ alpha/main.c
@@ -1,6 +1,8 @@
 #include "mmap.h"
 #include "types.h"
 
+#include "pci.h"
+#include "libc.h"
 #include "syscalls/syscalls.h"
 
 #define MAX_TASKS	64
@@ -21,26 +23,18 @@ static struct task* task_new(void *);
 void
 alpha_main(struct mmap *km)
 {
-	struct task *t = task_new((void *)XHCI_ENTRY);
-	u64 *ptr = (u64 *)0;
+	struct task *t;
+	pci_init();
 
+	t = task_new((void *)XHCI_ENTRY);
+
 	if (t == nil)
-		send_msg("alpha: failed to create task!\n");
+		output("alpha: failed to create task!\n");
 
-	send_msg("alpha: running\n");
+	output("alpha: running\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);
-}
-
 static struct task*
 task_new(void *entry)
 {
blob - /dev/null
blob + aa80895e24f1195b07f322154bb5f0f0912a0cb0 (mode 644)
--- /dev/null
+++ alpha/libc.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "types.h"
+
+// If you come from Unix-like this is kinda
+// like print.
+
+void output(const u8 *);
+
+void outputi(u64);
+
+void outputh(u64);
blob - /dev/null
blob + 7cab7c0456c075991d302f39dce4edb1c081dd82 (mode 644)
--- /dev/null
+++ alpha/pci.c
@@ -0,0 +1,245 @@
+#include "io.h"
+#include "libc.h"
+
+#define CONFIG_ADDR	0xCF8
+#define CONFIG_DATA 0xCFC
+
+struct imap {
+	u16 id;
+	u8 *name;
+};
+
+struct pci_device {
+	u16 vendorID;
+	u16 productID;
+	u32 bar[6];
+};
+
+static struct imap vendors[] = {
+	{ .id = 0x8086, .name="Intel" },
+	{ .id = 0x1234, .name="QEMU" },
+	{ .id = 0x1b36, .name="Red Hat" },
+	{ .id = 0x1b73, .name="Fresco Logic"},
+};
+
+static u16
+pciConfigReadWord(u8 bus, u8 slot, u8 func, u8 offset)
+{
+	u32 addr;
+	u32 lbus = (u32)bus;
+	u32 lslot = (u32)slot;
+	u32 lfunc = (u32)func;
+	u16 tmp = 0;
+
+	addr = (u32)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) |
+		   ((u32)0x80000000));
+
+	outl(CONFIG_ADDR, addr);
+	tmp = (u16)((inl(CONFIG_DATA) >> ((offset & 2) * 8)) & 0xffff);
+	return tmp;
+}
+
+static void
+pciConfigWriteWord(u8 bus, u8 slot, u8 func, u8 offset, u16 value)
+{
+	u32 curr;
+	u32 addr;
+	u32 lbus = (u32)bus;
+	u32 lslot = (u32)slot;
+	u32 lfunc = (u32)func;
+
+	addr = (u32)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) |
+		   ((u32)0x80000000));
+
+	outl(CONFIG_ADDR, addr);
+	curr  = inl(CONFIG_DATA);
+
+	if ((offset & 2)) {
+		curr = (curr & 0x0000ffff) | ((u32)value << 16);
+	} else {
+		curr = (curr & 0xffff0000) | (u32)value;
+	}
+
+	// Write
+	outl(CONFIG_ADDR, addr);
+	outl(CONFIG_DATA, curr);
+}
+
+static u16
+pciCheckVendor(u8 bus, u8 slot, u8 func)
+{
+	u16 vendor, device;
+
+	if ((vendor = pciConfigReadWord(bus, slot, func, 0)) != 0xffff) {
+		device = pciConfigReadWord(bus, slot, func, 2);
+		return vendor;
+	}
+	return vendor;
+}
+
+static void
+getVendor(u16 id)
+{
+	u64 count = sizeof(vendors) / sizeof(*vendors);
+
+	for (int i = 0; i < count; i++) {
+		if (vendors[i].id == id) {
+			output(vendors[i].name);
+			return;
+		}
+	}
+	output("undefined");
+}
+
+static void
+getClass(u8 class, u8 subclass, u8 progif)
+{
+	switch (class) {
+	case 0x0:
+		output("Unclassified");
+		break;
+	case 0x1:
+		switch (subclass) {
+		case 0x6:
+			switch (progif) {
+			case 0x1:
+				output("AHCI Controller");
+				break;
+			default:
+				output("Unsupported ATA Controller");
+				break;
+			}
+			break;
+		default:
+			output("Unssuported Mass Storage Controller");
+			break;
+		}
+		break;
+	case 0xC:
+		switch (subclass) {
+		case 0x3:
+			switch (progif) {
+			case 0x0:
+				output("UHCI Controller");
+				break;
+			case 0x10:
+				output("OHCI Controller");
+				break;
+			case 0x20:
+				output("EHCI (USB2) Controller");
+				break;
+			case 0x30:
+				output("XHCI (USB3) Controller");
+				break;
+			case 0x80:
+				output("Unspecified USB Controller");
+				break;
+			case 0xFE:
+				output("USB Device (Not a controller)");
+				break;
+			default:
+				output("Unknown USB Controller");
+				break;
+			}
+			break;
+		default:
+			output("Unssuported Serial Bus Controller");
+			break;
+		}
+		break;
+	default:
+		output("Unsupported Controller");
+	}
+}
+
+void
+pci_init()
+{
+	u8 hdr;
+	u8 class;
+	u8 progif;
+	u16 vendor;
+	u8 subclass;
+	u16 command;
+	u32 bars[6];
+	u32 dev32_addr;
+	u64 dev64_addr;
+	u8 done = 0;
+	output("Initializing PCIs\n");
+
+	for (u16 bus = 0; bus < 256; bus++) {
+		for (u16 device = 0; device < 32; device++) {
+			for (u16 func = 0; func < 8; func++) {
+				if ((vendor = pciCheckVendor((u8)bus, (u8)device, func)) != 0xffff) {
+					hdr = (pciConfigReadWord(bus, device, func, 0x0E)) & 0xFF;
+					class = (pciConfigReadWord(bus, device, func, 0x0A)) >> 8;
+					progif = (pciConfigReadWord(bus, device, func, 0x08)) >> 8;
+					subclass = (pciConfigReadWord(bus, device, func, 0x0A)) & 0xFF;
+					command = pciConfigReadWord(bus, device, func, 0x4);
+
+					// For now we skip all but type 0. Bit 7 needs to be removed
+					if ((hdr & ~(1 << 7)) != 0)
+						continue;
+
+					output("PCI: "); getVendor(vendor);
+					output(", "); getClass(class, subclass, progif); output("\n");
+
+					if (class == 0xC && subclass == 0x3 && progif == 0x30 && done == 0) {
+						// Disable I/O and Memory Space
+						command &= ~(1 << 0);
+						command &= ~(1 << 1);
+						pciConfigWriteWord(bus, device, 0, 0x04, command);
+
+						bars[0] = pciConfigReadWord(bus, device, func, 0x10) | 
+								  (pciConfigReadWord(bus, device, func, 0x12) << 16);
+
+						bars[1] = pciConfigReadWord(bus, device, func, 0x14) |
+								  (pciConfigReadWord(bus, device, func, 0x16) << 16);
+
+						bars[2] = pciConfigReadWord(bus, device, func, 0x18) |
+								  (pciConfigReadWord(bus, device, func, 0x1A) << 16);
+
+						bars[3] = pciConfigReadWord(bus, device, func, 0x1C) |
+								  (pciConfigReadWord(bus, device, func, 0x1E) << 16);
+
+						bars[4] = pciConfigReadWord(bus, device, func, 0x20) |
+								  (pciConfigReadWord(bus, device, func, 0x22) << 16);
+
+						bars[5] = pciConfigReadWord(bus, device, func, 0x24) |
+								  (pciConfigReadWord(bus, device, func, 0x26) << 16);
+
+						if ((bars[0] & (1 << 0)) == 0) {
+							u8 type = (bars[0] & (3 << 1)) >> 1;
+							if (type == 0x0) {
+								output("32-bit Memory Space Bar Layout ");
+								dev32_addr = (u32)(bars[0] & 0xfffffff0);
+								outputh(dev32_addr);
+								output("\n");
+
+							} else if (type == 0x2) {
+								output("64-bit Memory Space Bar Layout ");
+								dev64_addr = (u64)(bars[0] & 0xfffffff0) + 
+									((u64)(bars[1] & 0xffffffff) << 32);
+								outputh(dev64_addr);
+								output("\n");
+
+							} else if (type == 0x1) {
+								output("PCI 3.0 reserved\n");
+							}
+						}
+
+						command |= (1 << 0);
+						command |= (1 << 1);
+						pciConfigWriteWord(bus, device, func, 0x04, command);
+								volatile u32 *xhci_base = (volatile u32 *)dev64_addr;
+								u32 cap_reg = xhci_base[0];
+
+								u8 cap_len = cap_reg & 0xff;
+								u16 hci_version = (cap_reg >> 16) & 0xffff;
+								output("xhci version: "); outputh(hci_version); output("\n");
+					}
+				}
+			}
+		}
+	}
+}
blob - /dev/null
blob + c723553e038a68be543c67d2412ac8a9596e6e66 (mode 644)
--- /dev/null
+++ alpha/pci.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void pci_init(void);
blob - 9159beef07d7a4fcea323c46deff368abf573a71
blob + 626656de7372e28c8776f0e056d187d7fdb35b4d
--- build.sh
+++ build.sh
@@ -48,8 +48,8 @@ ld \
 	--defsym=entry=$KERNEL_ENTRY \
 	-T $KERNEL_DIR/linker.ld $LFLAGS \
 	-o kernel.bin kmain.o io.o kprint.o kmmap.o mem.o \
-	switch.o idt.o lidt.o lgdt.o kgdt.o kpic.o syscalls.o \
-	sysentry.o kthreads.o
+	switch.o idt.o lidt.o lgdt.o kgdt.o kpic.o \
+	syscalls.o sysentry.o kthreads.o
 
 KSIZE=$(wc -c < kernel.bin)
 KSECTORS=$(( (KSIZE + SECTOR_SIZE - 1) / SECTOR_SIZE + 2)) # Extra sector
blob - 6ef478526ceceee1bc89936256afdde6bce583de
blob + cee74ed4f57f2cd2531915e4dc3972c890094c26
--- c449
+++ c449
@@ -45,6 +45,35 @@ generate a compiler error when used outside of them. S
 available for directories and subdirectories within the module using
 the keyword. export means available for everyone.
 
+[ THREADING ]
+
+To solve the problem of multithreading, I thought of a syntax that
+defines a thread right away and that the root task can load in memory
+properly:
+
+thread 0;
+
+static u8 *name="First";
+
+void
+main()
+{
+	output("Thread 0\n");
+}
+
+thread 1;
+
+void
+main()
+{
+	output("Thread 1\n");
+}
+
+
+In this example thread 1 `main` is not able to read thread 0 static
+`name` variable.
+
+
 [ C PREPROCESSOR ]
 
 There are minor differences within C449. #define keyword does not
blob - 30b8a7dd5b4fe5fe44a7d27e8602741b79984258
blob + 15ee22e44c08b1d58a85ee5ed5ae33d5294522ee
--- kernel/idt.c
+++ kernel/idt.c
@@ -122,7 +122,6 @@ timer_handler_c()
 	next = thread_next();
 
 	if (next != nil) {
-		tss_switch_rsp0((u64)next->base + PAGE_SIZE * 3);
 		cthread = next;
 	}
 
blob - da3bfa2fb1c11c17a75fb44a051cf0a34cfbcfa6
blob + 23461ea8256b8e3f767113d793524c7e43e98b8c
--- kernel/io.h
+++ kernel/io.h
@@ -7,3 +7,5 @@
 
 u8 inb(u16 port);
 void outb(u16 port, u8 value);
+u32 inl(u16 port);
+void outl(u16 port, u32 value);
blob - 562c0bf8b9f7d85ce755c79e60d5af151dd67e27
blob + 21156ca8b7be4e87dbd6a812ea21b0689203e800
--- kernel/io.s
+++ kernel/io.s
@@ -4,6 +4,8 @@
 
 global inb
 global outb
+global inl
+global outl
 
 inb:
 	mov dx, di
@@ -15,3 +17,14 @@ outb:
 	mov al, sil
 	out dx, al
 	ret
+
+inl:
+	mov dx, di
+	in eax, dx
+	ret
+
+outl:
+	mov dx, di
+	mov eax, esi
+	out dx, eax
+	ret
blob - b2366e527a26372c6ecb83786edcd572fdce0e7c
blob + 63b7b85f1c653588678667cb19e57a6d98b0c33c
--- kernel/kgdt.c
+++ kernel/kgdt.c
@@ -12,24 +12,10 @@ struct gdt_desc {
 	u8 hbase;
 } __packed;
 
-struct tss_desc {
-	u16 llimit;
-	u16 lbase;
-	u8 mbase;
-	u8 access;
-	u8 flags;
-	u8 hbase;
-	u32 ubase;
-	u32 reserved;
-} __packed;
-
 struct gdt {
 	struct gdt_desc null;
 	struct gdt_desc kernel_code;
 	struct gdt_desc kernel_data;
-	struct gdt_desc user_data;
-	struct gdt_desc user_code;
-	struct tss_desc tss;
 } __packed;
 
 struct gdtr {
@@ -37,36 +23,14 @@ struct gdtr {
 	u64 base;
 } __packed;
 
-struct tss {
-	u32 reserved0;
-	u64 rsp0;
-	u64 rsp1;
-	u64 rsp2;
-	u32 reserved1;
-	u32 reserved2;
-	u64 ist1;
-	u64 ist2;
-	u64 ist3;
-	u64 ist4;
-	u64 ist5;
-	u64 ist6;
-	u64 ist7;
-	u32 reserved3;
-	u32 reserved4;
-	u16 reserved5;
-	u16 iomap;
-} __packed;
+void load_gdt(struct gdtr*);
 
-static struct tss tss;
 static struct gdt gdt;
 static struct gdtr gdtr = {
 	.limit = sizeof(gdt) - 1,
 	.base = (u64)&gdt
 };
 
-void load_gdt(struct gdtr*);
-static void setup_tss(void);
-
 s8
 kgdt_init()
 {
@@ -84,47 +48,7 @@ kgdt_init()
 	gdt.kernel_data.flags = 0xCF;
 	gdt.kernel_data.hbase = 0;
 
-	gdt.user_code.llimit = 0xffff;
-	gdt.user_code.lbase = 0;
-	gdt.user_code.mbase = 0;
-	gdt.user_code.access = 0xFA;
-	gdt.user_code.flags = 0xAF;
-	gdt.user_code.hbase = 0;
-
-	gdt.user_data.llimit = 0xffff;
-	gdt.user_data.lbase = 0;
-	gdt.user_data.mbase = 0;
-	gdt.user_data.access = 0xF2;
-	gdt.user_data.flags = 0xCF;
-	gdt.user_data.hbase = 0;
-
-	setup_tss();
 	load_gdt(&gdtr); // See lgdt.s
 
 	return 0;
 }
-
-static void
-setup_tss()
-{
-	u64 base = (u64)&tss;
-	u64 limit = sizeof(tss) - 1;
-
-	tss.rsp0 = KERNEL_STACK_TOP;
-	tss.iomap = sizeof(tss);
-
-	gdt.tss.llimit = limit & 0xffff;
-	gdt.tss.lbase = base & 0xffff;
-	gdt.tss.mbase = (base >> 16) & 0xff;
-	gdt.tss.access = 0x89;
-	gdt.tss.flags = (limit >> 16) & 0x0f;
-	gdt.tss.hbase = (base >> 24) & 0xff;
-	gdt.tss.ubase = (base >> 32) & 0xff;
-	gdt.tss.reserved = 0;
-}
-
-void
-tss_switch_rsp0(u64 rsp0)
-{
-	tss.rsp0 = rsp0;
-}
blob - cdc2d5b4dc9a349890c07f32c786f010284c9a41
blob + 80dc8b3b55590067ed94ce974b03df157bb78893
--- kernel/kmain.c
+++ kernel/kmain.c
@@ -23,14 +23,13 @@ kmain(struct kinfo *kinfo, u8 drive)
 
 	kprint("GDT configured!\n");
 
-	syscalls_init();
-
 	if (idt_init() == -1) {
 		kprint("Failed to initialize IDT\n");
 		return;
 	}
 
 	kprint("IDT configured!\n");
+	syscall_init();
 
 	ammap = kmmap_init(kinfo);
 	if (ammap == nil) {
@@ -41,7 +40,6 @@ kmain(struct kinfo *kinfo, u8 drive)
 	kpic_setup();
 
 	kprint("Page tables configured!\n");
-	kprint("Free memory U/S bit set!\n");
 	kloop(&kinfo->modules[1], ammap);
 }
 
blob - 3334258cf25f3e68aae8d615009bfc9bba95d272
blob + 62195e7b1db99e5a7a72a440fefd5dd6630afab3
--- kernel/kmmap.c
+++ kernel/kmmap.c
@@ -2,12 +2,12 @@
 
 #include "kmmap.h"
 #include "kdebug.h"
+#include "syscalls/syscalls.h"
 
 #define MAX_MEMORY (4ULL * 1024 * 1024 * 1024)
 
 #define P_PRESENT	(1ULL << 0)
 #define P_RW		(1ULL << 1)
-#define P_USER		(1ULL << 2)
 #define P_AMASK		0xfffffffffffff000
 #define P_ENTRIES	512
 
@@ -53,8 +53,6 @@ static struct mmap *mmap_config(void); // This is for 
 static struct kminfo kminfo;
 static struct vminfo vminfo;
 
-static void kmmap_usermode(void);
-
 static void
 set_bitmap(u64 addr)
 {
@@ -183,6 +181,8 @@ kmmap_init(struct kinfo *kinfo)
 			set_bitmap(j);
 	}
 
+	set_bitmap(SYSC_BELL);
+
 	PageTableCount = kminfo.frames;
 	PageDirCount = (PageTableCount + P_ENTRIES - 1) / P_ENTRIES;
 	PageDptrCount = (PageDirCount + P_ENTRIES - 1) / P_ENTRIES;
@@ -193,15 +193,14 @@ kmmap_init(struct kinfo *kinfo)
 	}
 
 	for (u64 i = 0; i < PageDirCount; i++)
-		vminfo.dirs[i] = ((u64)&vminfo.tables[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW | P_USER;
+		vminfo.dirs[i] = ((u64)&vminfo.tables[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW;
 
 	for (u64 i = 0; i < PageDptrCount; i++)
-		vminfo.dptrs[i] = ((u64)&vminfo.dirs[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW | P_USER;
+		vminfo.dptrs[i] = ((u64)&vminfo.dirs[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW;
 
 	for (u64 i = 0; i < PagePML4Count; i++)
-		vminfo.pml4s[i] = ((u64)&vminfo.dptrs[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW | P_USER;
+		vminfo.pml4s[i] = ((u64)&vminfo.dptrs[i * P_ENTRIES] & P_AMASK) | P_PRESENT | P_RW;
 
-
 	// This is technically an allocation. Due to the fact that compiling the
 	// kernel does not add the bss into the binary image. This allows us to
 	// avoid having a huge kernel to copy from low memory in BIOS boot. So
@@ -213,23 +212,11 @@ kmmap_init(struct kinfo *kinfo)
 		set_bitmap(i);
 
 	vmmap_load((u64)vminfo.pml4s);
-
 	kminfo.amap = mmap_config();
 
 	if (kminfo.amap == nil)
 		return nil;
 
-	// Changing modules to user mode
-
-	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;
 }
 
@@ -254,9 +241,6 @@ mmap_config()
 	amap->page_count = kminfo.frames;
 	amap->pages = pages;
 
-	for (u64 i = (u64 )mapbase; i < (u64 )mapbase + mapsize; i += PAGE_SIZE)
-		kmmap_addr_touser(i);
-
 	for (u64 i = 0; i < amap->page_count; i++) {
 		struct page *page = &amap->pages[i];
 		u64 addr = i * PAGE_SIZE;
@@ -265,43 +249,7 @@ mmap_config()
 			page->status = PAGE_STATUS_USED;
 		else
 			page->status = PAGE_STATUS_FREE;
-
-		if (vminfo.tables[i] & P_USER)
-			page->level = PAGE_LEVEL_USER;
-		else
-			page->level = PAGE_LEVEL_KERN;
 	}
 
 	return amap;
 }
-
-void
-kmmap_addr_touser(u64 addr)
-{
-	u64 frame = addr / PAGE_SIZE;
-	u64 pt = frame / P_ENTRIES;
-	u64 entry = frame % P_ENTRIES;
-
-	if (kminfo.amap != nil)
-		kminfo.amap->pages[frame].level = PAGE_LEVEL_USER;
-
-	vminfo.tables[pt * P_ENTRIES + entry] |= P_USER;
-	vmmap_update_entry(frame * PAGE_SIZE);
-}
-
-void
-kmmap_usermode()
-{
-	for (u64 i = 0; i < kminfo.frames; i++) {
-		if (get_bitmap(i * PAGE_SIZE) == 1)
-			continue;
-
-		u64 pt = i / P_ENTRIES;
-		u64 entry = i % P_ENTRIES;
-
-		vminfo.tables[pt * P_ENTRIES + entry] |= P_USER;
-		vmmap_update_entry(i * PAGE_SIZE);
-		
-		if (kminfo.amap != nil) kminfo.amap->pages[i].level = PAGE_LEVEL_USER;
-	}
-}
blob - 22b22d08c60f36ee2e5a4ddf1e2557d122dde1f1
blob + 9a60bed7857dc8a5730d6c49352efc797ae6b597
--- kernel/kmmap.h
+++ kernel/kmmap.h
@@ -15,8 +15,6 @@ struct kinfo {
 };
 
 struct mmap* kmmap_init(struct kinfo *);
-void kmmap_addr_touser(u64 addr);
-
 u64 *allocate_memory(u64 bytes);
 
 s8 kgdt_init(void);
blob - fe438fa7f5b494e80edf47a178b5aaf4e06d97f9
blob + 2aaa27bd3d0a50f812e72284bcf53e13aaaad651
--- kernel/kthreads.c
+++ kernel/kthreads.c
@@ -29,20 +29,20 @@ thread_create(void (*entry)(void))
 		return nil;
 	}
 
-	thread->base = allocate_memory(PAGE_SIZE * 3);
+	thread->base = allocate_memory(PAGE_SIZE * 2);
 
 	if (thread->base == nil) {
 		thread->assigned = 0;
 		return nil;
 	}
 
-	usp = (u64)thread->base + PAGE_SIZE;
-	sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 3);
+	sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 2);
+	usp = (u64)sp;
 
-	*(--sp) = 0x1B; // user SS/DS see kgdt.c
-	*(--sp) = usp; // user sp
+	*(--sp) = 0x10; // Kernel SS
+	*(--sp) = usp; // Kernel sp
 	*(--sp) = 0x202; // RFLAGS
-	*(--sp) = 0x23; // User CS
+	*(--sp) = 0x08; // Kernel CS
 	*(--sp) = (u64)entry; // RIP
 
 	*(--sp) = 0; // rbp
@@ -77,7 +77,6 @@ void
 thread_schedule(struct mmap *ammap, struct thread *th)
 {
 	cthread = th;
-	tss_switch_rsp0((u64)th->base + PAGE_SIZE * 3);
 	start_alpha(ammap, th);
 }
 
blob - b7f8f2a8b77fecb71b1d061abf2d78353eb4a77e
blob + 4eabc87c4c005efb8cc4af679eae19108c35cdd9
--- kernel/lgdt.s
+++ kernel/lgdt.s
@@ -2,7 +2,4 @@ global load_gdt
 
 load_gdt:
 	lgdt [rdi]
-
-	mov ax, 0x28 ; Offset based on gdt in kgdt.c
-	ltr ax
 	ret
blob - f575e2ff8206bacbd765276605e8d4a67a36add4
blob + 2dc35b1e0b56da7ebf126adaf33be290cd292dc7
--- kernel/lidt.s
+++ kernel/lidt.s
@@ -40,6 +40,7 @@ general_protection_handler:
 
 timer_handler:
 	cli
+
 	push rbp
 	push rbx
 	push r12
blob - 73117a1355dc2a443b0cf3445a09e380fcd3f8e8
blob + eb53bcf9b9f470e202a4ae5ef4bfa696e10b33e7
--- kernel/mem.s
+++ kernel/mem.s
@@ -1,11 +1,6 @@
 [bits 64]
 global vmmap_load
-global vmmap_update_entry
 
 vmmap_load:
 	mov cr3, rdi
 	ret
-
-vmmap_update_entry:
-	invlpg [rdi]
-	ret
blob - 616bc48d63becb64fdcaab0c1cbdb7d1689e51f1
blob + 014a9a1f363403a2edea51c96f40aa503e2abfb4
--- kernel/switch.s
+++ kernel/switch.s
@@ -5,7 +5,6 @@
 global start_alpha
 
 start_alpha:
-	cli
 	mov rsp, [rsi + RSP_OFFSET]
 	pop r15
 	pop r14
blob - 506f0acdbc5f659191e10538612fa9e4b82aa5cd
blob + ef4077ea1afc937475b103521f2bd6c238d74b47
--- kernel/syscalls.c
+++ kernel/syscalls.c
@@ -3,36 +3,49 @@
 #include "kthreads.h"
 #include "syscalls/syscalls.h"
 
-#define IA32_EFER	0xC0000080
-#define IA32_STAR	0xC0000081
-#define IA32_LSTAR	0xC0000082
-#define IA32_FMASK	0xC0000084
+#define MAX_SEATS 64
 
-u64 rdmsr(u32 msr);
-void wrmsr(u32 msr, u64 value);
-void syscall_entry(void);
+struct seatmap {
+	u64 send; // Sender Thread
+	u64 recv; // Receiver Thread
+};
 
-void
-syscalls_init()
+static struct seatmap seatmaps[MAX_SEATS];
+
+void syscall_handler(struct sysc *);
+
+// Trampoline
+void syscall_init()
 {
-	u64 efer;
-	u64 star;
+	u8 *jump = (u8 *)SYSC_BELL;
+	u64 addr = (u64)&syscall_handler;
 
-	efer = rdmsr(IA32_EFER);
-	efer |= 1ULL;
-	wrmsr(IA32_EFER, efer);
+	// movabs rax, addr
+	jump[0] = 0x48;
+	jump[1] = 0xB8;
+	*(u64 *)(jump + 2) = addr;
 
-	wrmsr(IA32_LSTAR, (u64)syscall_entry);
-
-	star = ((u64)0x10 << 48) | ((u64)0x08 << 32);
-	wrmsr(IA32_STAR, star);
-	wrmsr(IA32_FMASK, 0);
+	// jmp rax
+	jump[10] = 0xFF;
+	jump[11] = 0xE0;
 }
 
 void
 syscall_echo_h(struct sysc_echo *echo)
 {
-	kprint(echo->msg);
+	switch (echo->type) {
+	case SYSC_ECHO_STRING:
+		kprint(echo->msg);
+		break;
+	case SYSC_ECHO_INTEGER:
+		kprinti(echo->number);
+		break;
+	case SYSC_ECHO_HEXADECIMAL:
+		kprinth(echo->number);
+		break;
+	default:
+		break;
+	}
 }
 
 void
blob - 8ad13727f0ce6c2dd73228114071371bd159d087
blob + 95ffef1019aeafa48a48857106ea098ee698ec70
--- kernel/syscalls.h
+++ kernel/syscalls.h
@@ -1,3 +1,3 @@
 #pragma once
 
-void syscalls_init(void);
+void syscall_init(void);
blob - 9e460d889acdd7664a8a494521a753f1e9ed08d5
blob + 122a306e1a63ac3a5c2d5d602ce3e2e49a2e1971
--- kernel/sysentry.s
+++ kernel/sysentry.s
@@ -5,25 +5,7 @@ extern syscall_handler
 
 global rdmsr
 global wrmsr
-global syscall_entry
 
-syscall_entry:
-	mov rax, rsp
-
-	mov r10, [rel cthread]
-	mov rsp, [r10 + RSP_OFFSET]
-
-	push rax
-	push rcx
-	push r11
-
-	call syscall_handler
-
-	pop r11
-	pop rcx
-	pop rsp
-	o64 sysret ; This instead of `sysretq` because nasm complain
-
 wrmsr:
 	mov ecx, edi
 	mov eax, esi
blob - 5bf1972f01da0943e8d03902b113b420fa14167b
blob + 3f2964d17b6bd6e0c70520b7e33ed953b8735548
--- servers/include
+++ servers/include
@@ -1,3 +1,3 @@
 # Servers global include files
 
-INCS='-I ../.. -I ../../common'
+INCS='-I ../.. -I ../../common -I ../../alpha'
blob - 3cf9a7817bf1abdb4622552611080a652e465dca
blob + ba331fc0284d2cd8b1cea71b06ceca12a29ac4dd
--- servers/xhci/build.sh
+++ servers/xhci/build.sh
@@ -7,13 +7,13 @@ set -e
 
 echo "xhci: building"
 
-nasm -f elf64 -o syscall.o ../../syscalls/syscalls.s
 cc -m64 $CFLAGS -o main.o -c main.c $INCS
+cc -m64 $CFLAGS -o libc.o -c ../../alpha/libc.c $INCS
 
 ld \
 	--defsym=entry=$XHCI_ENTRY \
 	-T linker.ld $LFLAGS \
-	-o xhci.bin main.o syscall.o
+	-o xhci.bin main.o libc.o
 
 XHCI_SIZE=$(wc -c < xhci.bin)
 XHCI_SECTORS=$(( (XHCI_SIZE + SECTOR_SIZE - 1) / SECTOR_SIZE))
blob - a63060857332e965651f8484c979a5233d2346eb
blob + 9c4f59ed470664e3583932f89f1a9e98980ec009
--- servers/xhci/main.c
+++ servers/xhci/main.c
@@ -1,22 +1,13 @@
+// The xHCI driver possess a number of slots for each devices
+// it can handle. The slot maximum can be changed at compile
+// time by the end user.
+
 #include "types.h"
-#include "syscalls/syscalls.h"
+#include "libc.h"
 
-static void send_msg (const u8 *msg);
-
 void
 xhci_main()
 {
-	send_msg("xhci: driver started\n");
-
+	output("xhci: running\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 - 4ed19f7d29b986549d6fec7d04fe784cbd0226cc
blob + d1edb04a4f5cfca5a1ece76b9ed6582ada0a95eb
--- syscalls/syscalls.h
+++ syscalls/syscalls.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#define SYSC_BELL	0xE00000
+
 enum sysc_type {
 	SYSC_ECHO,
 	SYSC_NEW_THREAD,
@@ -11,9 +13,20 @@ struct sysc {
 	enum sysc_type type;
 };
 
+enum sysc_echo_type {
+	SYSC_ECHO_STRING,
+	SYSC_ECHO_INTEGER,
+	SYSC_ECHO_HEXADECIMAL,
+	SYSC_ECHO_FLOAT,
+};
+
 struct sysc_echo {
 	struct sysc sysc;
-	const char *msg;
+	enum sysc_echo_type type;
+	union {
+		const char *msg;
+		u64 number;
+	};
 };
 
 struct sysc_new_thread {
@@ -34,5 +47,4 @@ struct sysc_context_switch {
 	u64 threadid;
 };
 
-void sys_send(struct sysc *);
-void sys_recv(void);
+extern void (*sys_send)(struct sysc *call);
blob - ee332a1157cd391ca49fd5dec16b823f91d3c4dd (mode 644)
blob + /dev/null
--- syscalls/syscalls.s
+++ /dev/null
@@ -1,11 +0,0 @@
-[bits 64]
-global sys_send
-global sys_recv
-
-sys_send:
-	syscall
-	ret
-
-sys_recv:
-	syscall
-	ret