commit - a1ebf18642867950f088fe721bdf1742f88bec39
commit + 7abd0aa7f90dfa1a7147252f69971b23d6a119c9
blob - ba37bbc9df29c2c46b0d4363a0f829bc8971717c
blob + 328bcaa3fc244f7ebb9b149b20ea0db74ae89291
--- README
+++ README
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
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
+#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
#include "mmap.h"
#include "types.h"
+#include "pci.h"
+#include "libc.h"
#include "syscalls/syscalls.h"
#define MAX_TASKS 64
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
+#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
+#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
+#pragma once
+
+void pci_init(void);
blob - 9159beef07d7a4fcea323c46deff368abf573a71
blob + 626656de7372e28c8776f0e056d187d7fdb35b4d
--- build.sh
+++ build.sh
--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
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
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
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
global inb
global outb
+global inl
+global outl
inb:
mov dx, di
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
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 {
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()
{
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
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) {
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
#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
static struct kminfo kminfo;
static struct vminfo vminfo;
-static void kmmap_usermode(void);
-
static void
set_bitmap(u64 addr)
{
set_bitmap(j);
}
+ set_bitmap(SYSC_BELL);
+
PageTableCount = kminfo.frames;
PageDirCount = (PageTableCount + P_ENTRIES - 1) / P_ENTRIES;
PageDptrCount = (PageDirCount + P_ENTRIES - 1) / P_ENTRIES;
}
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
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;
}
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;
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
};
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
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
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
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
timer_handler:
cli
+
push rbp
push rbx
push r12
blob - 73117a1355dc2a443b0cf3445a09e380fcd3f8e8
blob + eb53bcf9b9f470e202a4ae5ef4bfa696e10b33e7
--- kernel/mem.s
+++ kernel/mem.s
[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
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
#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
#pragma once
-void syscalls_init(void);
+void syscall_init(void);
blob - 9e460d889acdd7664a8a494521a753f1e9ed08d5
blob + 122a306e1a63ac3a5c2d5d602ce3e2e49a2e1971
--- kernel/sysentry.s
+++ kernel/sysentry.s
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
# 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
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
+// 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
#pragma once
+#define SYSC_BELL 0xE00000
+
enum sysc_type {
SYSC_ECHO,
SYSC_NEW_THREAD,
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 {
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
-[bits 64]
-global sys_send
-global sys_recv
-
-sys_send:
- syscall
- ret
-
-sys_recv:
- syscall
- ret