aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2021-12-19 17:10:36 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2021-12-19 17:10:36 +0200
commit9966b49db468de0168c7a455dfb5b4c66c413c4d (patch)
treedf31febe5e1ae52bae68ebe1df8b4469b97e0546
parent8bb1e280280c2f30740defca68ea643c56a3d880 (diff)
downloadkmi-9966b49db468de0168c7a455dfb5b4c66c413c4d.tar.gz
kmi-9966b49db468de0168c7a455dfb5b4c66c413c4d.zip
Massive changes to jump to userspace
-rw-r--r--Makefile24
-rw-r--r--TODO.txt26
-rw-r--r--arch/riscv/common/vmem.c104
-rw-r--r--arch/riscv/conf/apos.its2
-rw-r--r--arch/riscv/conf/init-link.S31
-rw-r--r--arch/riscv/conf/kernel-link.S4
-rw-r--r--arch/riscv/include/csr.h36
-rw-r--r--arch/riscv/include/vmem.h8
-rw-r--r--arch/riscv/init/head.S7
-rw-r--r--arch/riscv/init/init.c337
-rw-r--r--arch/riscv/kernel/irq.c4
-rw-r--r--arch/riscv/kernel/main.c314
-rw-r--r--arch/riscv/kernel/proc.c15
-rw-r--r--arch/riscv/kernel/vmem.c52
-rw-r--r--arch/riscv/proc.txt3
-rw-r--r--arch/riscv/source.mk5
-rw-r--r--common/elf.c9
-rw-r--r--common/initrd.c (renamed from kernel/temp.c)0
-rw-r--r--common/mem_nodes.c2
-rw-r--r--common/tcb.c55
-rw-r--r--common/vmem.c112
-rw-r--r--include/apos/elf.h33
-rw-r--r--include/apos/init.h31
-rw-r--r--include/apos/initrd.h9
-rw-r--r--include/apos/pmem.h6
-rw-r--r--include/apos/proc.h7
-rw-r--r--include/apos/tcb.h34
-rw-r--r--include/apos/vmem.h18
-rwxr-xr-xscripts/gen-deps30
29 files changed, 649 insertions, 669 deletions
diff --git a/Makefile b/Makefile
index 2a388e8..e0a2ec6 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ DEBUGFLAGS != [ $(RELEASE) ] && echo "-flto -O2" || echo "-O0 -ggdb3 -DDEBUG"
CFLAGS = -fno-pie -ffreestanding -nostdlib -std=c17 -Wall -Wextra
DEPFLAGS = -MT $@ -MMD -MP -MF $@.d
-all: apos.bin
+all: kernel.bin
# default values, overwrite if/when needed
ARCH ?= riscv
@@ -20,10 +20,8 @@ OBJCOPY ?= objcopy
# This makes sure .bss is loaded into the binary
OBJCOPY_FLAGS ?= -Obinary --set-section-flags .bss=alloc,load,contents
-COMMON_SOURCES != echo common/*.c lib/fdt*.c
-KERNEL_SOURCES != echo kernel/*.c $(COMMON_SOURCES)
-INIT_SOURCES := $(COMMON_SOURCES)
-CLEANUP := build deps.mk kernel.* init.* apos.bin
+KERNEL_SOURCES != echo common/*.c lib/*.c
+CLEANUP := build deps.mk kernel.* apos.bin
CLEANUP_CMD :=
include arch/$(ARCH)/source.mk
@@ -43,32 +41,20 @@ KERN_SIZE = wc -c kernel.bin | cut -d ' ' -f 1
KERN_INFO = sed "s/<KERNEL_SIZE>/$$($(KERN_SIZE))/"
KERNEL_LINK := arch/$(ARCH)/conf/kernel-link
-INIT_LINK := arch/$(ARCH)/conf/init-link
-KERNEL_OBJECTS != ./scripts/gen-deps --kern "$(KERNEL_SOURCES)"
-INIT_OBJECTS != ./scripts/gen-deps --init "$(INIT_SOURCES)"
-KERNEL_LD != ./scripts/gen-deps --kern-link "$(KERNEL_LINK).S"
-INIT_LD != ./scripts/gen-deps --init-link "$(INIT_LINK).S"
+KERNEL_OBJECTS != ./scripts/gen-deps --compile "$(KERNEL_SOURCES)"
+KERNEL_LD != ./scripts/gen-deps --link "$(KERNEL_LINK).S"
include deps.mk
-apos.bin: kernel.bin init.bin
- cat init.bin kernel.bin > $@
-
kernel.elf: $(KERNEL_OBJECTS) $(KERNEL_LD)
$(GENELF) -T $(KERNEL_LD) $(KERNEL_OBJECTS) -o $@
$(INIT_LD): kernel.bin
-init.elf: $(INIT_OBJECTS) $(INIT_LD)
- $(GENELF) -T $(INIT_LD) $(INIT_OBJECTS) -o $@
-
kernel.bin: kernel.elf
$(CROSS_COMPILE)$(OBJCOPY) $(OBJCOPY_FLAGS) $< $@
-init.bin: init.elf
- $(CROSS_COMPILE)$(OBJCOPY) $(OBJCOPY_FLAGS) $< $@
-
clean:
$(RM) -r $(CLEANUP)
diff --git a/TODO.txt b/TODO.txt
index 3691a68..149fcfc 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,22 +1,6 @@
-+ Add in sensible defines (uint64_t etc.) x
-+ Improve build process (Kbuild? nah, regular config.h files)
-+ Automate booting and starting qemu etc. (make run) (sort of)
-+ Add in pmem/vmem routines (both .init and .text!)
-
-+ Test string.c
-+ Write the kernel lol
-+ Test libfdt and see if it can be used to read memory geometry etc.
-
-+ Jump to vmem x
-+ Mark fdt, reserved mem, kernel, init and initrd in vmem. Remember to remove
-init from vmem when jumping to vmem
-+ Figure out best way to tell the init how large out kernel is x~
-+ Make code more robust, error checking etc
-+ Make all physical memory addresses use the same typedef x
-
-+ should I consider passing more pointers around rather than return structures?
-+ should probably come up with some kind of general error handling scheme?
-
-+ Fix unmap/map_vmem when called from virtual memory
-
+ Investigate GCC/Clang builtin atomic operations?
+
++ Add in mapping the same memory to two different processes
++ Create sensible thread handling
++ Add in init process loading
++ Make sure vmap is in 4K increments or whatever
diff --git a/arch/riscv/common/vmem.c b/arch/riscv/common/vmem.c
deleted file mode 100644
index 6b022e1..0000000
--- a/arch/riscv/common/vmem.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include <apos/string.h>
-#include <apos/pmem.h>
-#include <apos/vmem.h>
-#include <apos/mem.h>
-#include <apos/debug.h>
-#include <pages.h>
-
-#define pte_ppn(pte) (((pm_t)(pte)) >> 10)
-#define pte_flags(pte) (((pm_t)(pte)) & 0xff)
-#define to_pte(p, f) ((pm_to_pnum(p) << 10) + (f))
-#define pte_addr(pte) (pnum_to_paddr(pte_ppn(pte)))
-#define vm_to_index(a, o) (pm_to_index(a, o))
-
-#if defined(KERNEL)
-
-static vm_t *tmp_pte = 0;
-void arch_init_vmem(struct vm_branch_t *branch, vm_t pte)
-{
- (void)branch;
- tmp_pte = (vm_t *)pte;
-}
-
-/* this seems like an awful idea, should probably try to come up with a smarter
- * approach? flushing the cache every time is probably pretty slow and also
- * this code doesn't take into account the cpu ASID, although that's probably
- * not relevant here */
-
-/* what I probably should do is something like Linux, where the kernel has a
- * direct (or linear, I suppose?) so that all direct memory accesses are also
- * accessible from virtual memory. Not entirely sure how I should do that,
- * wouldn't there be situations where the RAM is larger than the allocated
- * memory region?
- *
- * Or maybe some kind of walker, where I maintain a virtual page table that
- * mirrors the physical page table? Not sure yet, but this seems to work for
- * _now_.
- */
-#define QUOTE2(x) #x
-#define QUOTE(x) QUOTE2(x)
-static void *set_vptr(uint8_t flags, pm_t a)
-{
- *tmp_pte = to_pte(a, flags);
- __asm__ ("sfence.vma %0, %1"
- :: "rk" (0), "rK" (TMP_PTE)
- : "memory");
-
- return (void *)TMP_PTE;
-}
-
-#else
-struct vm_branch_t *arch_get_tmp_pte(struct vm_branch_t *branch)
-{
- enum mm_order_t top = __mm_max_order;
- while(top){
- size_t idx = vm_to_index(TMP_PTE, top);
- branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]);
- top--;
- }
-
- return branch;
-}
-
-#define set_vptr(flags, a) (a)
-#endif
-
-void map_vmem(struct vm_branch_t *branch,
- pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order_t order)
-{
- enum mm_order_t top = __mm_max_order;
- while (top != order) {
- size_t idx = vm_to_index(vaddr, top);
-
- if (!branch->leaf[idx]) {
- pm_t new_leaf = alloc_page(MM_KPAGE, 0);
- branch->leaf[idx] =
- (struct vm_branch_t *)to_pte(new_leaf, VM_V);
-
- void *leaf_ptr = (void *)set_vptr(VM_R | VM_W | VM_V, new_leaf);
- memset(leaf_ptr, 0, sizeof(struct vm_branch_t));
- }
-
- pm_t pte = (pm_t)branch->leaf[idx];
- pm_t branch_pptr = (pm_t)pte_addr(pte);
- branch = (struct vm_branch_t *)set_vptr(VM_R | VM_W | VM_V, branch_pptr);
- top--;
- }
-
- size_t idx = vm_to_index(vaddr, top);
- branch->leaf[idx] = (struct vm_branch_t *)to_pte(paddr, flags);
-}
-
-void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr, enum mm_order_t order)
-{
- while (order) {
- size_t idx = pm_to_index(vaddr, order);
- branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]);
- }
-
- size_t idx = pm_to_index(vaddr, order);
- if (branch->leaf[idx])
- free_page(order, pte_addr(branch->leaf[idx]));
-
- branch->leaf[idx] = 0;
-}
diff --git a/arch/riscv/conf/apos.its b/arch/riscv/conf/apos.its
index 7c05044..1581025 100644
--- a/arch/riscv/conf/apos.its
+++ b/arch/riscv/conf/apos.its
@@ -7,7 +7,7 @@
images {
kernel {
description = "Garbaggio";
- data = /incbin/("../../../apos.bin");
+ data = /incbin/("../../../kernel.bin");
type = "kernel";
arch = "riscv";
os = "apos";
diff --git a/arch/riscv/conf/init-link.S b/arch/riscv/conf/init-link.S
deleted file mode 100644
index c9a6da2..0000000
--- a/arch/riscv/conf/init-link.S
+++ /dev/null
@@ -1,31 +0,0 @@
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-
-SECTIONS {
- . = ABSOLUTE(PM_KERN);
- __init_start = .;
-
- /* objcopy only copies these three sections (as far as I'm aware) into the
- produces binary, so __init_end should point to the correct location in the
- final binary
- */
- .text ALIGN(4K) : AT(0) {
- *(.init.start)
- *(.text*);
- }
-
- .rodata : {
- *(.rodata*)
- }
-
- .data : {
- *(.data*)
- }
-
- .bss : {
- *(.bss*) *(COMMON)
- }
-
- __kernel_size = <KERNEL_SIZE>;
- __init_end = . ;
-}
diff --git a/arch/riscv/conf/kernel-link.S b/arch/riscv/conf/kernel-link.S
index d3b1223..bf0ad28 100644
--- a/arch/riscv/conf/kernel-link.S
+++ b/arch/riscv/conf/kernel-link.S
@@ -2,10 +2,10 @@ OUTPUT_ARCH(riscv)
ENTRY(main)
SECTIONS {
- . = ABSOLUTE(VM_KERN);
+ . = ABSOLUTE(PM_KERN);
__kernel_start = .;
- .text ALIGN(4K) : AT(0) {
+ .text : AT(0) {
*(.kernel.start);
*(.text*);
}
diff --git a/arch/riscv/include/csr.h b/arch/riscv/include/csr.h
index ab25bdd..70e60bb 100644
--- a/arch/riscv/include/csr.h
+++ b/arch/riscv/include/csr.h
@@ -3,11 +3,39 @@
#include <apos/utils.h>
-#define SATP_MODE_Sv32 0x80000000
-#define SATP_MODE_Sv39 0x8000000000000000
-#define SATP_MODE_Sv48 0x9000000000000000
+#define SATP_MODE_Sv32 0x80000000
+#define SATP_MODE_Sv39 0x8000000000000000
+#define SATP_MODE_Sv48 0x9000000000000000
-#define CSR_SATP 0x180
+
+/* supervisor CSR registers */
+#define CSR_SSTATUS 0x100
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SCOUNTEREN 0x106
+
+#define CSR_SENVCFG 0x10A
+
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_STVAL 0x143
+#define CSR_SIP 0x144
+
+#define CSR_SATP 0x180
+
+#define CSR_SCONTEXT 0x5A8
+
+/* Exception causes */
+#define EXC_INST_MISALIGNED 0
+#define EXC_INST_ACCESS 1
+#define EXC_BREAKPOINT 3
+#define EXC_LOAD_ACCESS 5
+#define EXC_STORE_ACCESS 7
+#define EXC_SYSCALL 8
+#define EXC_INST_PAGE_FAULT 12
+#define EXC_LOAD_PAGE_FAULT 13
+#define EXC_STORE_PAGE_FAULT 15
/* directly lifted from Linux:/arch/riscv/include/asm/asm.h:9-13 */
#ifdef __ASSEMBLY__
diff --git a/arch/riscv/include/vmem.h b/arch/riscv/include/vmem.h
index d17aaf1..2cd3ac7 100644
--- a/arch/riscv/include/vmem.h
+++ b/arch/riscv/include/vmem.h
@@ -3,6 +3,7 @@
#include <apos/types.h>
#include <apos/attrs.h>
+#include <apos/pmem.h>
#define VM_V (1 << 0)
#define VM_R (1 << 1)
@@ -24,4 +25,11 @@ struct __packed vm_branch_t {
struct vm_branch_t *leaf[512];
};
+
+void map_vmem(struct vm_branch_t *b,
+ pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order_t order);
+
+void unmap_vmem(struct vm_branch_t *b,
+ vm_t vaddr, enum mm_order_t order);
+
#endif /* APOS_RISCV_VMAP_H */
diff --git a/arch/riscv/init/head.S b/arch/riscv/init/head.S
deleted file mode 100644
index 3589ead..0000000
--- a/arch/riscv/init/head.S
+++ /dev/null
@@ -1,7 +0,0 @@
-.section .init.start
-.global _start
-.type _start, @function
-_start:
- li sp, PM_STACK_TOP
- /* go to proper init */
- j init
diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c
deleted file mode 100644
index 721712c..0000000
--- a/arch/riscv/init/init.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/* TODO: cleanup :P */
-
-#include <apos/init.h>
-#include <apos/sizes.h>
-#include <apos/types.h>
-#include <apos/string.h>
-#include <apos/debug.h>
-#include <apos/pmem.h>
-#include <apos/vmem.h>
-#include <apos/utils.h>
-#include <libfdt.h>
-#include <pages.h>
-#include <csr.h>
-
-struct pm_layout_t {
- pm_t base;
- pm_t top;
-};
-
-struct pm_orders_t {
- size_t max_order;
- size_t bits[10];
- size_t page_shift;
-};
-
-static struct pm_layout_t get_memlayout(void *fdt)
-{
- struct cell_info_t ci = get_reginfo(fdt, "/memory");
- int mem_offset = fdt_path_offset(fdt, "/memory");
- uint8_t *mem_reg =
- (uint8_t *) fdt_getprop(fdt, mem_offset, "reg", NULL);
-
- /* if riscv128 comes around we will probably see addr_cells == 4, but
- * I'm not too concerned about it at the moment */
- pm_t base = (pm_t)fdt_load_int_ptr(ci.addr_cells, mem_reg);
-
- if(ci.addr_cells == 2)
- mem_reg += sizeof(fdt64_t);
- else
- mem_reg += sizeof(fdt32_t);
-
- /* -1 because base is a legitimate memory address */
- pm_t top = (pm_t)fdt_load_int_ptr(ci.size_cells, mem_reg) + base - 1;
- return (struct pm_layout_t){base, top};
-}
-
-#ifdef DEBUG
-
-static void init_debug(void *fdt)
-{
- struct dbg_info_t dbg = dbg_from_fdt(fdt);
- dbg_init(dbg.dbg_ptr, dbg.dev);
-}
-
-#else
-#define init_debug(...)
-#endif
-
-static pm_t get_kerneltop()
-{
- /* interesting, for some reason if I define these to be just char
- * pointers I get some wacky values. Not sure why that would be, but
- * this works. */
- extern char __init_end, __kernel_size;
- return (pm_t)&__init_end + (pm_t)&__kernel_size;
-}
-
-static pm_t get_initrdtop(void *fdt)
-{
- int chosen_offset = fdt_path_offset(fdt, "/chosen");
- struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
-
- void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset,
- "linux,initrd-end", NULL);
-
- return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_end_ptr);
-}
-
-static pm_t get_initrdbase(void *fdt)
-{
- int chosen_offset = fdt_path_offset(fdt, "/chosen");
- struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
-
- void *initrd_base_ptr = (void *)fdt_getprop(fdt, chosen_offset,
- "linux,initrd-start", NULL);
-
- return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_base_ptr);
-}
-
-static pm_t get_fdttop(void *fdt)
-{
- const char *b = (const char *)fdt;
- return (pm_t)(b + fdt_totalsize(fdt));
-}
-
-static pm_t get_fdtbase(void *fdt)
-{
- /* lol */
- return (pm_t)fdt;
-}
-
-static void mark_area_used(pm_t base, pm_t top)
-{
- size_t area_left = top - base;
- /* TODO: add in a method to make sure that we use as large mappings as
- * possible. */
- while(area_left >= MM_KPAGE_SIZE){
- mark_used(base, MM_KPAGE);
- area_left -= MM_KPAGE_SIZE;
- base += MM_KPAGE_SIZE;
- }
-
- if(area_left != 0)
- mark_used(base, MM_KPAGE_SIZE);
-}
-
-static void mark_reserved_mem(void *fdt)
-{
- int rmem_offset = fdt_path_offset(fdt, "/reserved-memory/mmode_resv0");
- struct cell_info_t ci = get_reginfo(fdt, "/reserved-memory/mmode_resv0");
- uint8_t *rmem_reg = (uint8_t *)fdt_getprop(fdt, rmem_offset, "reg", NULL);
-
- pm_t base = (pm_t)fdt_load_int_ptr(ci.addr_cells, rmem_reg);
-
- if(ci.addr_cells == 2)
- rmem_reg += sizeof(fdt64_t);
- else
- rmem_reg += sizeof(fdt32_t);
-
- pm_t top = (pm_t)fdt_load_int_ptr(ci.size_cells, rmem_reg) + base - 1;
- mark_area_used(base, top);
-}
-
-static struct pm_orders_t init_pmem(void *fdt)
-{
- enum mm_mode_t mmode = get_mmode(fdt);
-
- size_t max_order = 0;
- size_t order_bits = 9;
- switch(mmode){
- case Sv32:
- max_order = 1;
- order_bits = 10;
- break;
-
- case Sv39:
- max_order = 2;
- break;
-
- case Sv48:
- max_order = 3;
- break;
- };
-
- size_t bits[10] = {0};
- for(size_t i = 0; i <= max_order; ++i)
- bits[i] = order_bits;
-
- init_mem(max_order, bits, 12);
-
- struct pm_orders_t ret = {max_order, {0}, 12};
- for(size_t i = 0; i <= __mm_max_order; ++i)
- ret.bits[i] = bits[i];
-
- return ret;
-}
-
-static struct pm_layout_t setup_pmem(void *fdt)
-{
- struct pm_layout_t pmem = get_memlayout(fdt);
-
- pm_t initrd_top = get_initrdtop(fdt);
- pm_t kernel_top = get_kerneltop();
- pm_t fdt_top = get_fdttop(fdt);
-
- pm_t top = MAX3(kernel_top, initrd_top, fdt_top);
- dbg("initrd_top:\t%#lx\n", initrd_top);
- dbg("kernel_top:\t%#lx\n", kernel_top);
- dbg("fdt_top:\t%#lx\n", fdt_top);
-
- /* TODO: check that pmap placement doesn't overwrite anything, such as
- * stack or go over top address of memory */
- size_t probe_size = probe_pmap(pmem.base, pmem.top - pmem.base);
- /* riscv handles two byte boundaries better than one byte, so align
- * upwards */
- pm_t pmap_base = align_up(top + 1, 2);
- size_t actual_size = populate_pmap(pmem.base, pmem.top - pmem.base,
- pmap_base);
-
- /* TODO: not entirely sure what to do about this, probably give up trying to
- * boot? */
- if(probe_size != actual_size){
- dbg("BUG! probe_size (%#lx) != actual_size (%#lx)\n",
- probe_size, actual_size);
- }
-
- /* mark init stack, at the moment always mapped to 2M */
- mark_used(PM_STACK_BASE, MM_MPAGE);
-
- /* mark kernel, at the moment it is always mapped to a 2M partition */
- mark_used(PM_KERN, MM_MPAGE);
-
- /* mark fdt and initrd */
- mark_area_used(get_initrdbase(fdt), initrd_top);
- mark_area_used(get_fdtbase(fdt), fdt_top);
-
- /* mark pmap */
- mark_area_used(pmap_base, pmap_base + actual_size);
-
- /* mark reserved mem */
- mark_reserved_mem(fdt);
-
- return (struct pm_layout_t){.base = pmap_base, .top = actual_size + pmap_base};
-}
-
-pm_t move_kernel()
-{
- extern char __init_end, __kernel_size;
- pm_t dst = alloc_page(MM_MPAGE, 0);
- memmove((void *)dst, &__init_end, (size_t)&__kernel_size);
-
- return dst;
-}
-
-struct vm_branch_t *prepare_vmem()
-{
- pm_t kernel_dst = move_kernel();
-
- /* TODO: check if this actually works */
- struct vm_branch_t *branch = (struct vm_branch_t *)alloc_page(MM_KPAGE, 0);
- memset(branch, 0, sizeof(struct vm_branch_t));
-
- /* TODO: check mapping flags, also iron out possible bugs etc in
- * map_vmem */
- /* map kernel */
- map_vmem(branch, kernel_dst, VM_KERN, VM_R | VM_W | VM_G | VM_X | VM_V, MM_MPAGE);
-
- /* map init */
- map_vmem(branch, PM_KERN, PM_KERN, VM_R | VM_W | VM_X | VM_V, MM_MPAGE);
-
- /* map stack */
- map_vmem(branch, PM_STACK_BASE, PM_STACK_BASE, VM_R | VM_W | VM_V, MM_MPAGE);
-
- /* map root pte */
- map_vmem(branch, (pm_t)branch, ROOT_PTE, VM_R | VM_W | VM_V, MM_KPAGE);
-
- /* TODO: map more stuff? */
- return branch;
-}
-
-static vm_t prepare_tmp_pte(struct vm_branch_t *branch)
-{
- /* make sure the TMP_PTE is mapped to *something* */
- map_vmem(branch, 0, TMP_PTE, VM_R | VM_W | VM_V, MM_KPAGE);
-
- struct vm_branch_t *tmp_pte = arch_get_tmp_pte(branch);
-
- vm_t addr = TMP_PTE + MM_KPAGE_SIZE;
- map_vmem(branch, (vm_t)tmp_pte, addr, VM_R | VM_W | VM_V, MM_KPAGE);
- return addr;
-}
-
-void start_vmem(void *fdt, struct vm_branch_t *branch)
-{
- /* TODO: get ASID from CPU id */
-
- /* TODO: probably unnecessary optimisations but this could be cached? */
- enum mm_mode_t m = get_mmode(fdt);
-
- if(m == Sv32)
- csr_write(CSR_SATP, SATP_MODE_Sv32 | pm_to_pnum((pm_t)(branch)));
- else if (m == Sv39)
- csr_write(CSR_SATP, SATP_MODE_Sv39 | pm_to_pnum((pm_t)(branch)));
- else
- csr_write(CSR_SATP, SATP_MODE_Sv48 | pm_to_pnum((pm_t)(branch)));
-
- __asm__ ("sfence.vma" : : : "memory");
- /* Sv57 && Sv64 in the future? */
-}
-
-struct init_data_t populate_initdata(void *fdt, struct pm_orders_t o,
- struct pm_layout_t p,
- struct vm_branch_t *b,
- vm_t v)
-{
- extern char __init_start, __init_end;
-
- struct init_data_t d = {0};
- d.init_base = (pm_t)&__init_start;
- d.init_top = (pm_t)&__init_end;
-
- d.initrd_base = get_initrdbase(fdt);
- d.initrd_top = get_initrdtop(fdt);
-
- d.pmap_base = p.base;
- d.pmap_top = p.top;
-
- d.fdt_base = get_fdtbase(fdt);
- d.fdt_top = get_fdttop(fdt);
-
- d.stack_base = PM_STACK_BASE;
- d.stack_top = PM_STACK_TOP;
-
- d.kernel_vm_base = b;
- d.tmp_pte = v;
-
- d.max_order = o.max_order;
- for(size_t i = 0; i <= __mm_max_order; ++i)
- d.bits[i] = o.bits[i];
- d.page_shift = o.page_shift;
-
- /* initialize pmap in vmem */
- pm_t addr = p.base;
- while(addr < p.top){
- map_vmem(b, addr, addr, VM_R | VM_W | VM_V, MM_MPAGE);
- addr += MM_MPAGE_SIZE;
- }
-
- return d;
-}
-
-void init(void *fdt)
-{
- init_debug(fdt);
- dbg_fdt(fdt);
-
- struct pm_orders_t o = init_pmem(fdt);
- struct pm_layout_t p = setup_pmem(fdt);
- struct vm_branch_t *b = prepare_vmem();
- vm_t v = prepare_tmp_pte(b);
- struct init_data_t d = populate_initdata(fdt, o, p, b, v);
- start_vmem(fdt, b);
-
- /* update_pmap(TODO: figure out where to place pmap in vmem); */
- void (*main)(struct init_data_t) = (void (*)(struct init_data_t))VM_KERN;
- main(d);
-}
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
new file mode 100644
index 0000000..f015411
--- /dev/null
+++ b/arch/riscv/kernel/irq.c
@@ -0,0 +1,4 @@
+void irq_handler()
+{
+
+}
diff --git a/arch/riscv/kernel/main.c b/arch/riscv/kernel/main.c
index 3f524bc..c7a1290 100644
--- a/arch/riscv/kernel/main.c
+++ b/arch/riscv/kernel/main.c
@@ -1,51 +1,305 @@
#include <apos/debug.h>
-#include <apos/init.h>
#include <apos/vmem.h>
+#include <apos/pmem.h>
+#include <apos/types.h>
#include <apos/mem.h>
#include <apos/lock.h>
+#include <apos/tcb.h>
+#include <apos/string.h>
+#include <apos/proc.h>
+#include <apos/mem_nodes.h>
+#include <apos/elf.h>
+#include <apos/initrd.h>
+#include <libfdt.h>
+#include <csr.h>
+
+struct pm_layout_t {
+ pm_t base;
+ pm_t top;
+};
+
+struct pm_orders_t {
+ size_t max_order;
+ size_t bits[10];
+ size_t page_shift;
+};
#ifdef DEBUG
-static void kernel_dbg(void *fdt)
+static void init_dbg(void *fdt)
{
struct dbg_info_t dbg = dbg_from_fdt(fdt);
- map_vmem(ROOT_PTE, (pm_t)dbg.dbg_ptr, (vm_t)dbg.dbg_ptr,
- VM_R | VM_W | VM_V, MM_KPAGE);
dbg_init(dbg.dbg_ptr, dbg.dev);
}
#else
-#define kernel_dbg(...)
+#define init_dbg(...)
#endif
-static void map_fdt(struct vm_branch_t *branch, vm_t fdt_base, vm_t fdt_top)
+static struct pm_layout_t get_memlayout(void *fdt)
+{
+ struct cell_info_t ci = get_reginfo(fdt, "/memory");
+ int mem_offset = fdt_path_offset(fdt, "/memory");
+ uint8_t *mem_reg =
+ (uint8_t *) fdt_getprop(fdt, mem_offset, "reg", NULL);
+
+ /* if riscv128 comes around we will probably see addr_cells == 4, but
+ * I'm not too concerned about it at the moment */
+ pm_t base = (pm_t)fdt_load_int_ptr(ci.addr_cells, mem_reg);
+
+ if(ci.addr_cells == 2)
+ mem_reg += sizeof(fdt64_t);
+ else
+ mem_reg += sizeof(fdt32_t);
+
+ /* -1 because base is a legitimate memory address */
+ pm_t top = (pm_t)fdt_load_int_ptr(ci.size_cells, mem_reg) + base - 1;
+ return (struct pm_layout_t){base, top};
+}
+
+static pm_t get_kerneltop()
+{
+ /* interesting, for some reason if I define these to be just char
+ * pointers I get some wacky values. Not sure why that would be, but
+ * this works. */
+ extern char __kernel_end;
+ return (pm_t)&__kernel_end;
+}
+
+static pm_t get_initrdtop(void *fdt)
+{
+ int chosen_offset = fdt_path_offset(fdt, "/chosen");
+ struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
+
+ void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset,
+ "linux,initrd-end", NULL);
+
+ return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_end_ptr);
+}
+
+static pm_t get_initrdbase(void *fdt)
+{
+ int chosen_offset = fdt_path_offset(fdt, "/chosen");
+ struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
+
+ void *initrd_base_ptr = (void *)fdt_getprop(fdt, chosen_offset,
+ "linux,initrd-start", NULL);
+
+ return (pm_t)fdt_load_int_ptr(ci.addr_cells, initrd_base_ptr);
+}
+
+static pm_t get_fdttop(void *fdt)
+{
+ const char *b = (const char *)fdt;
+ return (pm_t)(b + fdt_totalsize(fdt));
+}
+
+static pm_t get_fdtbase(void *fdt)
+{
+ /* lol */
+ return (pm_t)fdt;
+}
+
+
+static void mark_area_used(pm_t base, pm_t top)
+{
+ size_t area_left = top - base;
+ /* TODO: add in a method to make sure that we use as large mappings as
+ * possible. */
+ while(area_left >= MM_KPAGE_SIZE){
+ mark_used(base, MM_KPAGE);
+ area_left -= MM_KPAGE_SIZE;
+ base += MM_KPAGE_SIZE;
+ }
+
+ if(area_left != 0)
+ mark_used(base, MM_KPAGE_SIZE);
+}
+
+static void mark_reserved_mem(void *fdt)
+{
+ int rmem_offset = fdt_path_offset(fdt, "/reserved-memory/mmode_resv0");
+ struct cell_info_t ci = get_reginfo(fdt, "/reserved-memory/mmode_resv0");
+ uint8_t *rmem_reg = (uint8_t *)fdt_getprop(fdt, rmem_offset, "reg", NULL);
+
+ pm_t base = (pm_t)fdt_load_int_ptr(ci.addr_cells, rmem_reg);
+
+ if(ci.addr_cells == 2)
+ rmem_reg += sizeof(fdt64_t);
+ else
+ rmem_reg += sizeof(fdt32_t);
+
+ pm_t top = (pm_t)fdt_load_int_ptr(ci.size_cells, rmem_reg) + base - 1;
+ mark_area_used(base, top);
+}
+
+static struct pm_layout_t setup_pmem(void *fdt)
+{
+ struct pm_layout_t pmem = get_memlayout(fdt);
+
+ pm_t initrd_top = get_initrdtop(fdt);
+ pm_t kernel_top = get_kerneltop();
+ pm_t fdt_top = get_fdttop(fdt);
+
+ pm_t top = MAX3(kernel_top, initrd_top, fdt_top);
+ dbg("initrd_top:\t%#lx\n", initrd_top);
+ dbg("kernel_top:\t%#lx\n", kernel_top);
+ dbg("fdt_top:\t%#lx\n", fdt_top);
+
+ /* TODO: check that pmap placement doesn't overwrite anything, such as
+ * stack or go over top address of memory */
+ size_t probe_size = probe_pmap(pmem.base, pmem.top - pmem.base);
+ /* riscv handles two byte boundaries better than one byte, so align
+ * upwards */
+ pm_t pmap_base = align_up(top + 1, 2);
+ size_t actual_size = populate_pmap(pmem.base, pmem.top - pmem.base,
+ pmap_base);
+
+ /* TODO: not entirely sure what to do about this, probably give up trying to
+ * boot? */
+ if(probe_size != actual_size){
+ dbg("BUG! probe_size (%#lx) != actual_size (%#lx)\n",
+ probe_size, actual_size);
+ }
+
+ /* mark init stack, at the moment always mapped to 2M */
+ mark_used(PM_STACK_BASE, MM_MPAGE);
+
+ /* mark kernel, at the moment it is always mapped to a 2M partition */
+ mark_used(PM_KERN, MM_MPAGE);
+
+ /* mark fdt and initrd */
+ mark_area_used(get_initrdbase(fdt), initrd_top);
+ mark_area_used(get_fdtbase(fdt), fdt_top);
+
+ /* mark pmap */
+ mark_area_used(pmap_base, pmap_base + actual_size);
+
+ /* mark reserved mem */
+ mark_reserved_mem(fdt);
+
+ return (struct pm_layout_t){.base = pmap_base, .top = actual_size + pmap_base};
+}
+
+static struct pm_orders_t init_pmem(void *fdt)
{
- /* TODO: fix this shit */
- map_vregion(branch, fdt_base, fdt_base, fdt_top - fdt_base, VM_R | VM_W |VM_V);
+ enum mm_mode_t mmode = get_mmode(fdt);
+
+ size_t max_order = 0;
+ size_t order_bits = 9;
+ switch(mmode){
+ case Sv32:
+ max_order = 1;
+ order_bits = 10;
+ break;
+
+ case Sv39:
+ max_order = 2;
+ break;
+
+ case Sv48:
+ max_order = 3;
+ break;
+ };
+
+ size_t bits[10] = {0};
+ for(size_t i = 0; i <= max_order; ++i)
+ bits[i] = order_bits;
+
+ init_mem(max_order, bits, 12);
+
+ struct pm_orders_t ret = {max_order, {0}, 12};
+ for(size_t i = 0; i <= __mm_max_order; ++i)
+ ret.bits[i] = bits[i];
+
+ return ret;
+}
+
+static void populate_root_branch(struct vm_branch_t *b, size_t mul)
+{
+ for(size_t i = 0; i <= (MM_KPAGE_SIZE / sizeof(size_t))/2; ++i)
+ b->leaf[i] = (struct vm_branch_t *)(mul * i | VM_V | VM_R | VM_W | VM_X | VM_G);
+}
+
+static void start_vmem(struct vm_branch_t *branch, enum mm_mode_t m)
+{
+ /* TODO: get ASID from CPU id */
+
+ if(m == Sv32)
+ csr_write(CSR_SATP, SATP_MODE_Sv32 | pm_to_pnum((pm_t)(branch)));
+ else if (m == Sv39)
+ csr_write(CSR_SATP, SATP_MODE_Sv39 | pm_to_pnum((pm_t)(branch)));
+ else
+ csr_write(CSR_SATP, SATP_MODE_Sv48 | pm_to_pnum((pm_t)(branch)));
+
+ __asm__ ("sfence.vma" : : : "memory");
+ /* Sv57 && Sv64 in the future? */
+}
+
+static struct vm_branch_t *init_vmem(void *fdt)
+{
+ struct pm_orders_t o = init_pmem(fdt);
+ setup_pmem(fdt);
+
+ struct vm_branch_t *b = (struct vm_branch_t *)alloc_page(MM_KPAGE, 0);
+ memset(b, 0, sizeof(struct vm_branch_t));
+
+ enum mm_mode_t mm = Sv48;
+ size_t mul = 0;
+ switch(o.max_order){
+ case 3: /* Sv48 */
+ mm = Sv48;
+ mul = 1UL << 37;
+ break;
+
+ case 2: /* Sv39 */
+ mm = Sv39;
+ mul = 1UL << 28;
+ break;
+
+ case 1: /* Sv32 */
+ mm = Sv32;
+ mul = 1UL << 20;
+ break;
+ }
+
+ set_uvmem_size(mul);
+ populate_root_branch(b, uvmem_size());
+ /* jump to vmem */
+ start_vmem(b, mm);
+ return b;
+}
+
+static void init_irq(void *fdt)
+{
+}
+
+static void init_proc(void *fdt, struct vm_branch_t *b)
+{
+ struct tcb *t = (struct tcb *)alloc_page(MM_KPAGE, 0);
+ t->b_r = b;
+ t->pid = 0;
+ t->tid = 0;
+ threads_insert(t);
+ sp_mem_init(&t->sp_r, uvmem_size());
+
+ /* binary itself */
+ size_t sz = align_up(get_init_size(fdt), BASE_PAGE_SIZE);
+ t->bin = alloc_uvmem(t, sz, VM_V | VM_X);
+ /* stack */
+ t->stack = alloc_uvmem(t, SZ_2M, VM_V | VM_R | VM_W);
+ /* if it needs heap, it'll ask for it */
+
+ move_init(fdt, (void *)t->bin, sz);
+ jump_to_userspace(t, 0, 0);
}
-void __main main(struct init_data_t d)
+void __main main(void *fdt)
{
- init_pmap((void *)d.pmap_base);
- init_mem(d.max_order, d.bits, d.page_shift);
- init_vmem(ROOT_PTE, d.tmp_pte);
- /* TODO: move pmap into vmem somewhere */
- /* TODO: mark kernel area as used */
- map_fdt(ROOT_PTE, d.fdt_base, d.fdt_top);
- kernel_dbg((void *)d.fdt_base);
- dbg("test\n");
- /* TODO: approximate order of business:
- * setup debugging in vmem (requires mapping fdt)
- * free unnecessary init
- * setup interrupts (should this be done in init?)
- * load init from initrd
- * setup init environment (thread control blocks etc.)
- * jumpstart init (free stack init setup)
- */
+ init_dbg(fdt);
+ struct vm_branch_t *b = init_vmem(fdt);
- /* functionality that should be implemented:
- * figure out best continuous run of memory (pmap etc)
- * arbitrary user and kernel mapping (memory)
- * vm to pm
- */
+ init_mem_blocks();
+ init_irq(fdt);
+ init_proc(fdt, b);
}
diff --git a/arch/riscv/kernel/proc.c b/arch/riscv/kernel/proc.c
new file mode 100644
index 0000000..3a39dd3
--- /dev/null
+++ b/arch/riscv/kernel/proc.c
@@ -0,0 +1,15 @@
+#include <apos/tcb.h>
+#include <apos/elf.h>
+#include <csr.h>
+
+void jump_to_userspace(struct tcb *t, char **argv, int argc)
+{
+ csr_write(CSR_SEPC, bin_entry(t->bin));
+ __asm__("mv sp, %0\n" : "=r" (t->stack) :: "memory");
+ __asm__("sret\n" ::: "memory");
+}
+
+void return_to_userspace(struct tcb *t)
+{
+ /* lol */
+}
diff --git a/arch/riscv/kernel/vmem.c b/arch/riscv/kernel/vmem.c
new file mode 100644
index 0000000..ffe8731
--- /dev/null
+++ b/arch/riscv/kernel/vmem.c
@@ -0,0 +1,52 @@
+#include <apos/string.h>
+#include <apos/pmem.h>
+#include <apos/vmem.h>
+#include <apos/mem.h>
+#include <apos/debug.h>
+#include <pages.h>
+
+#define pte_ppn(pte) (((pm_t)(pte)) >> 10)
+#define pte_flags(pte) (((pm_t)(pte)) & 0xff)
+#define to_pte(p, f) ((pm_to_pnum(p) << 10) + (f))
+#define pte_addr(pte) (pnum_to_paddr(pte_ppn(pte)))
+#define vm_to_index(a, o) (pm_to_index(a, o))
+
+void map_vmem(struct vm_branch_t *branch,
+ pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order_t order)
+{
+ enum mm_order_t top = __mm_max_order;
+ while (top != order) {
+ size_t idx = vm_to_index(vaddr, top);
+
+ if (!branch->leaf[idx]) {
+ pm_t new_leaf = alloc_page(MM_KPAGE, 0);
+ branch->leaf[idx] =
+ (struct vm_branch_t *)to_pte(new_leaf, VM_V);
+
+ void *leaf_ptr = (void *)new_leaf;
+ memset(leaf_ptr, 0, sizeof(struct vm_branch_t));
+ }
+
+ pm_t pte = (pm_t)branch->leaf[idx];
+ pm_t branch_pptr = (pm_t)pte_addr(pte);
+ branch = (struct vm_branch_t *)branch_pptr;
+ top--;
+ }
+
+ size_t idx = vm_to_index(vaddr, top);
+ branch->leaf[idx] = (struct vm_branch_t *)to_pte(paddr, flags);
+}
+
+void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr, enum mm_order_t order)
+{
+ while (order) {
+ size_t idx = pm_to_index(vaddr, order);
+ branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]);
+ }
+
+ size_t idx = pm_to_index(vaddr, order);
+ if (branch->leaf[idx])
+ free_page(order, pte_addr(branch->leaf[idx]));
+
+ branch->leaf[idx] = 0;
+}
diff --git a/arch/riscv/proc.txt b/arch/riscv/proc.txt
new file mode 100644
index 0000000..29b2e92
--- /dev/null
+++ b/arch/riscv/proc.txt
@@ -0,0 +1,3 @@
+Each thread should obviously have a thread control block (tcb) which lives in
+kernelspace and has pointers to virtual memory allocations, along with PID and
+other required data. That's about what I can come up with at the moment.
diff --git a/arch/riscv/source.mk b/arch/riscv/source.mk
index b1dd361..ecc22bd 100644
--- a/arch/riscv/source.mk
+++ b/arch/riscv/source.mk
@@ -1,9 +1,6 @@
-KERNEL_LOCAL != echo arch/riscv/kernel/*.[cS] arch/riscv/common/*.[cS]
+KERNEL_LOCAL != echo arch/riscv/kernel/*.[cS]
KERNEL_SOURCES += $(KERNEL_LOCAL)
-INIT_LOCAL != echo arch/riscv/init/*.[cS] arch/riscv/common/*.[cS]
-INIT_SOURCES += $(INIT_LOCAL)
-
CLEANUP_CMD := ./arch/riscv/conf/rmimage.sh
ARCH_FLAGS := -mcmodel=medany
diff --git a/common/elf.c b/common/elf.c
new file mode 100644
index 0000000..7531bd1
--- /dev/null
+++ b/common/elf.c
@@ -0,0 +1,9 @@
+#include <apos/elf.h>
+#include <apos/vmem.h>
+
+vm_t bin_entry(vm_t bin)
+{
+ struct elf_header *e = (struct elf_header *)bin;
+ /* TODO: check that address points to a valid ELF executable */
+ return (vm_t)e->e_entry;
+}
diff --git a/kernel/temp.c b/common/initrd.c
index e69de29..e69de29 100644
--- a/kernel/temp.c
+++ b/common/initrd.c
diff --git a/common/mem_nodes.c b/common/mem_nodes.c
index 1779276..dba714f 100644
--- a/common/mem_nodes.c
+++ b/common/mem_nodes.c
@@ -138,7 +138,7 @@ struct sp_mem *get_mem_node()
return __find_free_block(r);
}
- n = n->left;
+ n = sp_left(n);
}
/* we need to allocate a new region */
diff --git a/common/tcb.c b/common/tcb.c
new file mode 100644
index 0000000..5b00524
--- /dev/null
+++ b/common/tcb.c
@@ -0,0 +1,55 @@
+#include <apos/tcb.h>
+#include <apos/utils.h>
+#include <apos/sp_tree.h>
+
+static struct sp_root t_root = (struct sp_root){0};
+
+#define tcb_container(x) \
+ container_of(x, struct tcb, sp_n)
+
+void threads_insert(struct tcb *t)
+{
+ if(!sp_root(t_root)){
+ sp_root(t_root) = &t->sp_n;
+ return;
+ }
+
+ struct sp_node *n = sp_root(t_root), *p = NULL;
+ enum sp_dir d = LEFT;
+
+ while(n){
+ struct tcb *tc = tcb_container(n);
+ p = n;
+
+ if(t->tid < tc->tid){
+ n = sp_left(n);
+ d = LEFT;
+ }
+
+ else {
+ n = sp_right(n);
+ d = RIGHT;
+ }
+ }
+
+ sp_insert(&sp_root(t_root), p, &t->sp_n, d);
+}
+
+struct tcb *threads_find(id_t tid)
+{
+ struct sp_node *n = sp_root(t_root);
+
+ while(n){
+ struct tcb *t = tcb_container(n);
+
+ if(t->tid == tid)
+ return t;
+
+ if(t->tid < tid)
+ n = sp_left(n);
+ else
+ n = sp_right(n);
+ }
+
+ return 0;
+}
diff --git a/common/vmem.c b/common/vmem.c
index 267fbb7..25a8617 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -1,3 +1,4 @@
+#include <vmem.h>
#include <apos/vmem.h>
#include <apos/mem_nodes.h>
@@ -5,8 +6,7 @@
#define mark_region_unused(r) ((r) = 0)
#define is_region_used(r) (r)
-static struct sp_root free_regions = (struct sp_root){0};
-static struct sp_root used_regions = (struct sp_root){0};
+static size_t __uvmem_size = 0;
/* pretty major slowdown when we get to some really massive numbers, not
* entirely sure why. Will need to check up on this at some point, have I
@@ -24,9 +24,9 @@ static struct sp_root used_regions = (struct sp_root){0};
* maybe not even anything with sp_trees but more a weakness of binary trees in
* general?
*/
-static struct sp_mem *sp_free_insert_region(struct sp_mem *m)
+static struct sp_mem *sp_free_insert_region(struct sp_reg_root *r, struct sp_mem *m)
{
- struct sp_node *n = sp_root(free_regions), *p = NULL;
+ struct sp_node *n = sp_root(r->free_regions), *p = NULL;
size_t start = m->start;
size_t size = m->end - m->start;
enum sp_dir d = LEFT;
@@ -59,17 +59,17 @@ static struct sp_mem *sp_free_insert_region(struct sp_mem *m)
}
}
- if(sp_root(free_regions))
- sp_insert(&sp_root(free_regions), p, &m->sp_n, d);
+ if(sp_root(r->free_regions))
+ sp_insert(&sp_root(r->free_regions), p, &m->sp_n, d);
else
- sp_root(free_regions) = &m->sp_n;
+ sp_root(r->free_regions) = &m->sp_n;
return m;
}
-static struct sp_mem *sp_used_insert_region(struct sp_mem *m)
+static struct sp_mem *sp_used_insert_region(struct sp_reg_root *r, struct sp_mem *m)
{
- struct sp_node *n = sp_root(used_regions), *p = NULL;
+ struct sp_node *n = sp_root(r->used_regions), *p = NULL;
vm_t start = m->start;
enum sp_dir d = LEFT;
@@ -93,19 +93,19 @@ static struct sp_mem *sp_used_insert_region(struct sp_mem *m)
}
}
- if(sp_root(used_regions))
- sp_insert(&sp_root(used_regions), p, &m->sp_n, d);
+ if(sp_root(r->used_regions))
+ sp_insert(&sp_root(r->used_regions), p, &m->sp_n, d);
else
- sp_root(used_regions) = &m->sp_n;
+ sp_root(r->used_regions) = &m->sp_n;
return m;
}
-int sp_mem_init(size_t arena_size)
+int sp_mem_init(struct sp_reg_root *r, size_t arena_size)
{
struct sp_mem *m = get_mem_node();
m->end = arena_size;
- sp_free_insert_region(m);
+ sp_free_insert_region(r, m);
return 0;
}
@@ -122,10 +122,10 @@ static void __sp_mem_destroy(struct sp_node *n)
free_mem_node(m);
}
-void sp_mem_destroy()
+void sp_mem_destroy(struct sp_reg_root *r)
{
- __sp_mem_destroy(sp_root(free_regions));
- __sp_mem_destroy(sp_root(used_regions));
+ __sp_mem_destroy(sp_root(r->free_regions));
+ __sp_mem_destroy(sp_root(r->used_regions));
}
/* interestingly this is now the main bottleneck :D
@@ -133,9 +133,9 @@ void sp_mem_destroy()
* eh, it's not a massive thing I guess, maybe the code could be a bit quicker
* but I mean 10 000 000 memory allocations in 20 s is good enough for now
* */
-static struct sp_mem *sp_used_find(vm_t start)
+static struct sp_mem *sp_used_find(struct sp_reg_root *r, vm_t start)
{
- struct sp_node *n = sp_root(used_regions);
+ struct sp_node *n = sp_root(r->used_regions);
while(n){
struct sp_mem *t = mem_container(n);
if(start == t->start)
@@ -161,9 +161,9 @@ static struct sp_mem *sp_mem_create_region(vm_t start, vm_t end,
return m;
}
-static struct sp_mem *sp_free_find_first(size_t size, size_t alignment)
+static struct sp_mem *sp_free_find_first(struct sp_reg_root *r, size_t size, size_t alignment)
{
- struct sp_node *n = sp_root(free_regions);
+ struct sp_node *n = sp_root(r->free_regions);
while(n){
struct sp_mem *t = mem_container(n);
size_t nsize = t->end - align_up(t->start, alignment);
@@ -181,13 +181,13 @@ static struct sp_mem *sp_free_find_first(size_t size, size_t alignment)
* just ignore them for now. Note that alloc_region should only be used when
* mmap is called with MAP_ANON, all other situations should be handled in some
* fs server */
-vm_t alloc_region(size_t size, size_t alignment)
+vm_t alloc_region(struct sp_reg_root *r, size_t size, size_t alignment)
{
- struct sp_mem *m = sp_free_find_first(size, alignment);
+ struct sp_mem *m = sp_free_find_first(r, size, alignment);
if(!m)
return 0;
- sp_remove(&sp_root(free_regions), &m->sp_n);
+ sp_remove(&sp_root(r->free_regions), &m->sp_n);
vm_t aligned_start = align_up(m->start, alignment);
@@ -206,7 +206,7 @@ vm_t alloc_region(size_t size, size_t alignment)
if(n->prev)
n->prev->next = n;
- sp_free_insert_region(n);
+ sp_free_insert_region(r, n);
}
if(post_start != post_end){
@@ -215,17 +215,17 @@ vm_t alloc_region(size_t size, size_t alignment)
if(n->next)
n->next->prev = n;
- sp_free_insert_region(n);
+ sp_free_insert_region(r, n);
}
m->end = end;
m->start = start;
mark_region_used(m->flags);
- sp_used_insert_region(m);
+ sp_used_insert_region(r, m);
return start;
}
-static void __sp_try_coalesce_prev(struct sp_mem *m)
+static void __sp_try_coalesce_prev(struct sp_reg_root *r, struct sp_mem *m)
{
while(m){
if(!m || is_region_used(m->flags))
@@ -241,14 +241,14 @@ static void __sp_try_coalesce_prev(struct sp_mem *m)
if(m->prev)
m->prev->next = m;
- sp_remove(&sp_root(free_regions), &p->sp_n);
+ sp_remove(&sp_root(r->free_regions), &p->sp_n);
free_mem_node(p);
m = m->prev;
}
}
-static void __sp_try_coalesce_next(struct sp_mem *m)
+static void __sp_try_coalesce_next(struct sp_reg_root *r, struct sp_mem *m)
{
while(m){
if(!m || is_region_used(m->flags))
@@ -264,28 +264,62 @@ static void __sp_try_coalesce_next(struct sp_mem *m)
if(m->next)
m->next->prev = m;
- sp_remove(&sp_root(free_regions), &n->sp_n);
+ sp_remove(&sp_root(r->free_regions), &n->sp_n);
free_mem_node(n);
m = m->next;
}
}
-static void sp_mem_try_coalesce(struct sp_mem *m)
+static void sp_mem_try_coalesce(struct sp_reg_root *r, struct sp_mem *m)
{
- __sp_try_coalesce_prev(m);
- __sp_try_coalesce_next(m);
+ __sp_try_coalesce_prev(r, m);
+ __sp_try_coalesce_next(r, m);
}
-void free_region(vm_t start)
+void free_region(struct sp_reg_root *r, vm_t start)
{
- struct sp_mem *m = sp_used_find(start);
+ struct sp_mem *m = sp_used_find(r, start);
if(!m)
return;
- sp_remove(&sp_root(used_regions), &m->sp_n);
+ sp_remove(&sp_root(r->used_regions), &m->sp_n);
mark_region_unused(m->flags);
- sp_mem_try_coalesce(m);
- sp_free_insert_region(m);
+ sp_mem_try_coalesce(r, m);
+ sp_free_insert_region(r, m);
+}
+
+void set_uvmem_size(size_t s)
+{
+ __uvmem_size = s;
+}
+
+size_t uvmem_size()
+{
+ return __uvmem_size;
+}
+
+vm_t map_fill_region(struct vm_branch_t *b, vm_t start, size_t bytes, uint8_t flags)
+{
+ size_t pages = bytes / BASE_PAGE_SIZE;
+ pm_t offset = 0;
+ for(size_t i = 0; i < pages; ++i){
+ offset = alloc_page(BASE_PAGE, offset);
+ map_vmem(b, offset, start + i * BASE_PAGE_SIZE, flags, BASE_PAGE);
+ }
+
+ return start;
+}
+
+vm_t alloc_uvmem(struct tcb *t, size_t s, uint8_t flags)
+{
+ size_t sa = align_up(s, BASE_PAGE_SIZE);
+ vm_t v = alloc_region(&t->sp_r, sa, 0);
+ return map_fill_region(t->b_r, v, sa, flags);
+}
+
+void free_uvmem(struct tcb *t, vm_t a)
+{
+ free_region(&t->sp_r, a);
}
diff --git a/include/apos/elf.h b/include/apos/elf.h
new file mode 100644
index 0000000..492c414
--- /dev/null
+++ b/include/apos/elf.h
@@ -0,0 +1,33 @@
+#ifndef APOS_ELF_H
+#define APOS_ELF_H
+
+#include <apos/attrs.h>
+#include <apos/types.h>
+#include <apos/vmem.h>
+
+__packed struct elf_header {
+ uint64_t ei_magic;
+ uint8_t ei_class;
+ uint8_t ei_data;
+ uint8_t ei_version;
+ uint8_t ei_osabi;
+ uint8_t ei_abiversion;
+ uint8_t e_pad;
+ uint16_t e_type;
+ uint16_t e_machine;
+ uint32_t e_version;
+ void *e_entry;
+ void *e_phoff;
+ void *e_shoff;
+ uint32_t e_flags;
+ uint16_t e_ehsize;
+ uint16_t e_phentsize;
+ uint16_t e_phnum;
+ uint16_t e_shentsize;
+ uint16_t e_shnum;
+ uint16_t e_shstrndx;
+};
+
+vm_t bin_entry(vm_t bin);
+
+#endif /* APOS_ELF_H */
diff --git a/include/apos/init.h b/include/apos/init.h
deleted file mode 100644
index 2dd8a27..0000000
--- a/include/apos/init.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef APOS_INIT_H
-#define APOS_INIT_H
-
-#include <apos/pmem.h>
-#include <apos/vmem.h>
-
-struct init_data_t {
- pm_t init_base;
- pm_t init_top;
-
- pm_t initrd_base;
- pm_t initrd_top;
-
- pm_t pmap_base;
- pm_t pmap_top;
-
- pm_t fdt_base;
- pm_t fdt_top;
-
- pm_t stack_base;
- pm_t stack_top;
-
- struct vm_branch_t *kernel_vm_base;
- vm_t tmp_pte;
-
- size_t max_order;
- size_t bits[10];
- size_t page_shift;
-};
-
-#endif /* APOS_INIT_H */
diff --git a/include/apos/initrd.h b/include/apos/initrd.h
new file mode 100644
index 0000000..942875f
--- /dev/null
+++ b/include/apos/initrd.h
@@ -0,0 +1,9 @@
+#ifndef APOS_INITRD_H
+#define APOS_INITRD_H
+
+#include <apos/types.h>
+
+size_t get_init_size(void *fdt);
+void move_init(void *fdt, void *target, size_t sz);
+
+#endif /* APOS_INITRD_H */
diff --git a/include/apos/pmem.h b/include/apos/pmem.h
index 38dd670..01d89ce 100644
--- a/include/apos/pmem.h
+++ b/include/apos/pmem.h
@@ -25,13 +25,7 @@ void free_page(enum mm_order_t order, pm_t paddr);
void mark_used(enum mm_order_t order, pm_t paddr);
pm_t alloc_page(enum mm_order_t order, pm_t offset);
-#if defined(INIT)
pm_t populate_pmap(pm_t ram_base, size_t ram_size, pm_t cont);
pm_t probe_pmap(pm_t ram_base, size_t ram_size);
-#endif
-
-#if defined(KERNEL)
-void init_pmap(void *p);
-#endif
#endif /* APOS_PMEM_H */
diff --git a/include/apos/proc.h b/include/apos/proc.h
new file mode 100644
index 0000000..7506b10
--- /dev/null
+++ b/include/apos/proc.h
@@ -0,0 +1,7 @@
+#ifndef APOS_PROC_H
+#define APOS_PROC_H
+
+#include <apos/tcb.h>
+void jump_to_userspace(struct tcb *t, char **argv, int argc);
+
+#endif /* APOS_PROC_H */
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
new file mode 100644
index 0000000..9cef386
--- /dev/null
+++ b/include/apos/tcb.h
@@ -0,0 +1,34 @@
+#ifndef APOS_TCB_H
+#define APOS_TCB_H
+
+struct tcb;
+struct sp_reg_root;
+
+#include <vmem.h>
+#include <apos/vmem.h>
+#include <apos/types.h>
+#include <apos/sp_tree.h>
+
+typedef size_t id_t;
+
+struct sp_reg_root {
+ struct sp_root free_regions;
+ struct sp_root used_regions;
+};
+
+struct tcb {
+ struct sp_node sp_n;
+
+ id_t pid;
+ id_t tid;
+
+ vm_t stack;
+ vm_t bin;
+
+ struct vm_branch_t *b_r;
+ struct sp_reg_root sp_r;
+};
+
+void threads_insert(struct tcb *t);
+
+#endif /* APOS_TCB_H */
diff --git a/include/apos/vmem.h b/include/apos/vmem.h
index eb7ad17..fe2a76f 100644
--- a/include/apos/vmem.h
+++ b/include/apos/vmem.h
@@ -1,11 +1,14 @@
#ifndef APOS_VMEM_H
#define APOS_VMEM_H
+struct sp_mem;
+
/* arch-specific data */
#include <vmem.h>
/* common */
#include <apos/pmem.h>
+#include <apos/tcb.h>
#include <apos/sp_tree.h>
struct sp_mem {
@@ -24,6 +27,7 @@ struct sp_mem {
container_of(ptr, struct sp_mem, sp_n)
+
/* general overview of the different functions:
* (un)map_vmem: map one known page of physical memory to one known page of
* virtual memory
@@ -35,16 +39,14 @@ struct sp_mem {
*/
/* defined by arch */
-void map_vmem(struct vm_branch_t *branch,
- pm_t paddr, vm_t vaddr,
- uint8_t flags, enum mm_order_t order);
+int sp_mem_init(struct sp_reg_root *r, size_t nums);
-void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr, enum mm_order_t order);
+vm_t alloc_uvmem(struct tcb *r, size_t s, uint8_t flags);
+void free_uvmem(struct tcb *r, vm_t a);
+vm_t map_fill_region(struct vm_branch_t *b, vm_t start, size_t bytes, uint8_t flags);
-vm_t map_vregion(struct vm_branch_t *branch, pm_t base, vm_t start, size_t size,
- uint8_t flags);
-void unmap_vregion(struct vm_branch_t *branch, vm_t start);
+size_t uvmem_size();
+void set_uvmem_size(size_t s);
-void init_vmem(struct vm_branch_t *branch, vm_t tmp_pte);
#endif /* APOS_VMEM_H */
diff --git a/scripts/gen-deps b/scripts/gen-deps
index 7a468d3..ee64022 100755
--- a/scripts/gen-deps
+++ b/scripts/gen-deps
@@ -11,43 +11,25 @@ gencommon () {
echo "${obj}: ${s}" >> deps.mk
}
+
genlink () {
gencommon ".ld"
- if [ "${init}" = "0" ] ; then
- echo " \$(GENLINK) $< | \$(STRIPLINK) > \$@"\
- >> deps.mk;
- else
- echo " \$(GENLINK) $< | \$(STRIPLINK) | \$(KERN_INFO) > \$@"\
+ echo " \$(GENLINK) $< | \$(STRIPLINK) | \$(KERN_INFO) > \$@"\
>> deps.mk;
- fi
-
}
genrule () {
gencommon "${1}"
- echo " \$(COMPILE) ${defs} -c \$< -o \$@" >> deps.mk
+ echo " \$(COMPILE) -c \$< -o \$@" >> deps.mk
}
case "${1}" in
- --kern)
- suffix=.k.o
- defs=-DKERNEL
- func=genrule
- ;;
- --init)
- suffix=.i.o
- defs=-DINIT
+ --compile)
+ suffix=.o
func=genrule
;;
- --init-link)
- suffix=.ld
- init=1
- func=genlink
- ;;
-
- --kern-link)
+ --link)
suffix=.ld
- init=0
func=genlink
esac