commit 7abd0aa7f90dfa1a7147252f69971b23d6a119c9 from: Onana Onana Xavier Manuel date: Tue Sep 15 02:53:02 2026 UTC Changed OS to run at Ring0 only. Started adding blueprint for PCI checks. Updated my notes for clearer definition of my vision. Removed syscalls, User DS, User CS and TSS. 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