aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/conf/init-link.S4
-rw-r--r--arch/riscv/config.h23
-rw-r--r--arch/riscv/include/vmem.h6
-rw-r--r--arch/riscv/init/init.c33
-rw-r--r--arch/riscv/init/start.S5
-rw-r--r--arch/riscv/kernel/irq.c6
-rw-r--r--arch/riscv/kernel/main.c295
-rw-r--r--arch/riscv/kernel/pmem.c15
-rw-r--r--arch/riscv/kernel/proc.c4
-rw-r--r--arch/riscv/kernel/vmem.c92
-rw-r--r--arch/riscv/source.mk2
-rw-r--r--common/debug.c16
-rw-r--r--common/elf.c6
-rw-r--r--common/fdt.c8
-rw-r--r--common/initrd.c4
-rw-r--r--common/main.c52
-rw-r--r--common/mem.c22
-rw-r--r--common/pmem.c179
-rw-r--r--common/proc.c42
-rw-r--r--common/tcb.c5
-rw-r--r--common/uapi/conf.c4
-rw-r--r--common/vmem.c7
-rw-r--r--include/apos/arch.h6
-rw-r--r--include/apos/conf.h9
-rw-r--r--include/apos/debug.h14
-rw-r--r--include/apos/elf.h2
-rw-r--r--include/apos/irq.h2
-rw-r--r--include/apos/mem.h2
-rw-r--r--include/apos/pmem.h15
-rw-r--r--include/apos/proc.h4
-rw-r--r--include/apos/tcb.h2
-rw-r--r--include/apos/vmem.h23
-rw-r--r--include/libfdt.h7
33 files changed, 445 insertions, 471 deletions
diff --git a/arch/riscv/conf/init-link.S b/arch/riscv/conf/init-link.S
index 53d24ab..ce53e5e 100644
--- a/arch/riscv/conf/init-link.S
+++ b/arch/riscv/conf/init-link.S
@@ -1,8 +1,8 @@
OUTPUT_ARCH(riscv)
-ENTRY(init)
+ENTRY(_start)
SECTIONS {
- . = ABSOLUTE(PM_KERN);
+ . = ABSOLUTE(PM_KERN_BASE);
__init_start = .;
/* objcopy only copies these three sections (as far as I'm aware) into the
diff --git a/arch/riscv/config.h b/arch/riscv/config.h
index fa6785e..0ef22fa 100644
--- a/arch/riscv/config.h
+++ b/arch/riscv/config.h
@@ -3,15 +3,32 @@
/* --- START ARCH USER CONFIG VALUES --- */
/* physical address to which the kernel will be loaded */
#define RAM_BASE 0x80000000
-#define PM_KERN (RAM_BASE + SZ_512K)
+#define PM_KERN_BASE (RAM_BASE + SZ_512K)
+#define PM_KERN_SIZE (SZ_256K)
+#define PM_KERN_TOP (PM_KERN_BASE + PM_KERN_SIZE)
/* --- END ARCH USER CONFIG VALUES --- */
/* don't touch >:( */
-#define PM_STACK_BASE (PM_KERN)
-#define PM_STACK_TOP (RAM_BASE + SZ_1M)
+#define PM_STACK_BASE (PM_KERN_BASE + SZ_256K)
+#define PM_STACK_SIZE (SZ_256K)
+#define PM_STACK_TOP (PM_STACK_BASE + PM_STACK_SIZE)
+
#define VM_DMAP (0xffffffc000000000) /* testing for now */
#define VM_KERN (VM_DMAP + SZ_256K)
#define TMP_PTE (-SZ_2G)
#define ROOT_PTE (0)
#define ROOT_REGION (SZ_4K)
+
+#define IO_PAGE 511
+#define KSTART_PAGE 256
+#define CSTACK_PAGE 255
+
+/* assume Sv39, probably wouldn't be too difficult to use runtime parameters
+ * instead. First 4K is reserved for NULL, but I suppose it could be mapped
+ * later if *absolutely* necessary. */
+#define UVMEM_START (SZ_4K)
+#define UVMEM_END (SZ_256G - SZ_1G)
+
+#define PROC_STACK_TOP (SZ_256G)
+#define PROC_STACK_BASE (SZ_256G - SZ_1G)
diff --git a/arch/riscv/include/vmem.h b/arch/riscv/include/vmem.h
index d17aaf1..228b24b 100644
--- a/arch/riscv/include/vmem.h
+++ b/arch/riscv/include/vmem.h
@@ -13,15 +13,15 @@
#define VM_A (1 << 6)
#define VM_D (1 << 7)
-enum mm_mode_t {
+enum mm_mode {
Sv48,
Sv39,
Sv32,
};
typedef size_t vm_t;
-struct __packed vm_branch_t {
- struct vm_branch_t *leaf[512];
+struct __packed vm_branch {
+ struct vm_branch *leaf[512];
};
#endif /* APOS_RISCV_VMAP_H */
diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c
index dc9d7e9..23dcadd 100644
--- a/arch/riscv/init/init.c
+++ b/arch/riscv/init/init.c
@@ -1,6 +1,7 @@
#include <apos/types.h>
#include <apos/attrs.h>
#include <apos/utils.h>
+#include <apos/vmem.h>
#include <vmem.h>
#include <csr.h>
@@ -14,29 +15,24 @@ struct init_vmem *root_branch;
#define to_pte(a, f) (((a) >> 12) << 10 | (f))
/* assume Sv39 for now */
-void init_vmem()
+void init_bootmem()
{
size_t flags = VM_V | VM_X | VM_R | VM_W;
extern char *__init_start;
root_branch = (struct init_vmem *)align_down((size_t)&__init_start - SZ_4K, SZ_4K);
- for(size_t i = 0; i < 512; ++i)
- root_branch->leaf[i] = 0;
/* direct mapping (temp) */
- for(size_t i = 0; i < 256; ++i)
+ for(size_t i = 0; i < CSTACK_PAGE; ++i)
root_branch->leaf[i] = (int*)to_pte(SZ_1G * i, flags);
/* kernel (also sort of direct mapping) */
- /* FIXME set up actually correct addressing retard */
flags |= VM_G;
- for(size_t i = 256; i < 511; ++i)
+ for(size_t i = KSTART_PAGE; i < IO_PAGE; ++i)
root_branch->leaf[i] = (int *)to_pte(RAM_BASE + SZ_1G * (i - 256), flags);
- /* kernel IO, map to 0 for now, should be made more robust in the future */
- /* same goes for the equivalent piece of code over in kernel/main.c,
- * which btw should really get refactored, it's a mess */
- root_branch->leaf[511] = (int *)to_pte(0, flags);
+ /* kernel IO, map to 0 for now, will be updated in the future */
+ root_branch->leaf[IO_PAGE] = (int *)to_pte(0, flags);
csr_write(CSR_SATP, SATP_MODE_Sv39 | ((size_t)root_branch >> 12));
}
@@ -53,11 +49,22 @@ void move_kernel()
dst[i] = src[i];
}
-void __init init(void *fdt)
+#define __va_reg(reg)\
+{\
+ vm_t reg = 0;\
+ __asm__("mv %0, " QUOTE(reg) : "=r" (reg) :: );\
+ reg = (vm_t)__va(reg);\
+ __asm__("mv " QUOTE(reg) ", %0" :: "rK" (reg) : );\
+}
+
+void init(void *fdt)
{
extern char *__init_end;
void (*kernel_main)(void *fdt) = (void (*)(void *))(VM_KERN);
- init_vmem();
+ init_bootmem();
move_kernel();
- kernel_main(fdt);
+ __va_reg(sp);
+ __va_reg(fp);
+ __va_reg(gp);
+ kernel_main(__va(fdt));
}
diff --git a/arch/riscv/init/start.S b/arch/riscv/init/start.S
new file mode 100644
index 0000000..f9bfb92
--- /dev/null
+++ b/arch/riscv/init/start.S
@@ -0,0 +1,5 @@
+.section .init.start
+.global _start
+_start:
+li sp, PM_STACK_TOP
+jal init
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index 113773a..ed97c00 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -1,9 +1,13 @@
#include <apos/irq.h>
#include <csr.h>
-void irq_handler()
+void init_irq(void *fdt)
{
+ UNUSED(fdt);
+}
+void handle_irq()
+{
}
/* very simple for now */
diff --git a/arch/riscv/kernel/main.c b/arch/riscv/kernel/main.c
index 83270eb..9ce256e 100644
--- a/arch/riscv/kernel/main.c
+++ b/arch/riscv/kernel/main.c
@@ -1,298 +1,11 @@
-#include <apos/debug.h>
-#include <apos/vmem.h>
-#include <apos/pmem.h>
#include <apos/utils.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 init_dbg(void *fdt)
-{
- struct dbg_info_t dbg = dbg_from_fdt(fdt);
- dbg_init(dbg.dbg_ptr + (-SZ_1G), dbg.dev);
-}
-
-#else
-#define init_dbg(...)
-#endif
-
-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){(size_t)__va(base), (size_t)__va(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_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 with 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)
-{
- /* bad idea for now */
- /* enum mm_mode_t mmode = get_mmode(fdt); */
-
- size_t max_order = 0;
- size_t order_bits = 9;
- enum mm_mode_t mmode = Sv39;
- 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;
-}
-
-/* assume Sv39 for now */
-#define to_pte(a, f) (((a) >> 12) << 10 | (f))
-static void populate_root_branch(struct vm_branch_t *b)
-{
- size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G;
- for(size_t i = 256; i < 511; ++i)
- b->leaf[i] = (struct vm_branch_t *)to_pte(RAM_BASE + SZ_1G * (i - 256), flags);
-
- /* very lazy, should be ashamed, yes */
- b->leaf[511] = (struct vm_branch_t *)to_pte(0, flags);
-}
-
-static void start_vmem(struct vm_branch_t *branch, enum mm_mode_t m)
-{
- /* TODO: get ASID from CPU id */
-
- branch = (struct vm_branch_t *)__pa(branch);
-
- 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)
-{
- 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));
-
- populate_root_branch(b);
- /* update which memory branch to use */
- start_vmem(b, Sv39);
- return b;
-}
-
-static void init_irq(void *fdt)
-{
-}
-
-static void init_proc(void *fdt, struct vm_branch_t *b)
+void arch_setup(void *fdt)
{
- struct tcb *t = (struct tcb *)alloc_page(MM_KPAGE, 0);
- t->b_r = b;
- t->pid = 0;
- t->tid = 0;
- threads_insert(t);
- /* first page reserved to avoid issues with null pointers being legal */
- /* last gig page (assuming Sv39) reserved for call stack */
- sp_mem_init(&t->sp_r, SZ_4K, SZ_256G - SZ_1G);
-
- /* stack (should probably be set up to allow for configuration
- * parameters to be passed) */
- t->proc_stack = alloc_uvmem(t, SZ_2M, VM_V | VM_R | VM_W | VM_U);
- /* if need be, the call stack can later be expanded, but this init
- * program uses it like this. */
- t->call_stack = setup_call_stack(t, SZ_256G - SZ_1G + SZ_2M, SZ_2M);
-
- /* should probably wrap this in like tlb_flush_all() or something */
- __asm__ ("sfence.vma" : : : "memory");
-
- jump_to_userspace(t, get_init_base(fdt), 0, 0);
-}
-
-#define __va_reg(reg)\
-{\
- vm_t reg = 0;\
- __asm__("mv %0, " QUOTE(reg) : "=r" (reg) :: );\
- reg = (vm_t)__va(reg);\
- __asm__("mv " QUOTE(reg) ", %0" :: "rK" (reg) : );\
-}
-
-void __main arch_main(void *fdt)
-{
- __va_reg(sp);
- __va_reg(fp);
- __va_reg(gp);
-
- /* correct fdt pointer */
- fdt = (void *)__va(fdt);
- init_dbg(fdt);
- dbg_fdt(fdt);
-
- /* allow supervisor code to touch user data */
+ UNUSED(fdt);
+ /* allow supervisor code to touch user pages */
csr_set(CSR_SSTATUS, SSTATUS_SUM);
- /* maybe this is too early but mark that we want to jump to user mode
- * eventually*/
+ /* mark that we want to eventually jump to userspace */
csr_clear(CSR_SSTATUS, SSTATUS_SPP);
- struct vm_branch_t *b = init_vmem(fdt);
- init_mem_blocks();
- init_irq(fdt);
- init_proc(fdt, b);
}
diff --git a/arch/riscv/kernel/pmem.c b/arch/riscv/kernel/pmem.c
new file mode 100644
index 0000000..45b8eeb
--- /dev/null
+++ b/arch/riscv/kernel/pmem.c
@@ -0,0 +1,15 @@
+#include <apos/pmem.h>
+
+int arch_pmem_conf(void *fdt, size_t *max_order, size_t *base_bits, size_t bits[ORDERS_NUM])
+{
+ UNUSED(fdt);
+
+ /* Sv39 for now */
+ *max_order = 2;
+ *base_bits = 12;
+ /* we can assume bits[] is zeroed out beforehand */
+ for(size_t i = 0; i <= *max_order; ++i)
+ bits[i] = 9;
+
+ return 0;
+}
diff --git a/arch/riscv/kernel/proc.c b/arch/riscv/kernel/proc.c
index 57ddc5b..6120c2d 100644
--- a/arch/riscv/kernel/proc.c
+++ b/arch/riscv/kernel/proc.c
@@ -2,9 +2,9 @@
#include <apos/elf.h>
#include <csr.h>
-void jump_to_userspace(struct tcb *t, vm_t bin, int argc, char **argv)
+void jump_to_userspace(struct tcb *t, int argc, char **argv)
{
- csr_write(CSR_SEPC, prepare_proc(t, bin));
+ csr_write(CSR_SEPC, t->entry);
__asm__("mv sp, %0\n" : "=r" (t->proc_stack) :: "memory");
__asm__("sret\n" ::: "memory");
}
diff --git a/arch/riscv/kernel/vmem.c b/arch/riscv/kernel/vmem.c
index 45f6336..c862cea 100644
--- a/arch/riscv/kernel/vmem.c
+++ b/arch/riscv/kernel/vmem.c
@@ -3,12 +3,14 @@
#include <apos/vmem.h>
#include <apos/mem.h>
#include <apos/debug.h>
+#include <apos/cpu.h>
#include <pages.h>
#include <vmem.h>
+#include <csr.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((pm_t)__pa(p)) << 10) | (f))
+#define to_pte(p, f) ((pm_to_pnum(p) << 10) | (f))
#define pte_addr(pte) __va(pnum_to_paddr(pte_ppn(pte)))
#define pte_paddr(pte) (pnum_to_paddr(pte_ppn(pte)))
#define vm_to_index(a, o) (pm_to_index(a, o))
@@ -16,9 +18,9 @@
#define is_leaf(pte) (is_active(pte) && (pte_flags(pte) & ~VM_V))
#define is_branch(pte) (is_active(pte) && !(pte_flags(pte) & ~VM_V))
-static pm_t *__find_vmem(struct vm_branch_t *b, vm_t v, enum mm_order_t *o)
+static pm_t *__find_vmem(struct vm_branch *b, vm_t v, enum mm_order *o)
{
- enum mm_order_t top = __mm_max_order;
+ enum mm_order top = __mm_max_order;
if(o)
*o = MM_O0;
do {
@@ -35,17 +37,17 @@ static pm_t *__find_vmem(struct vm_branch_t *b, vm_t v, enum mm_order_t *o)
return (pm_t *)&b->leaf[idx];
}
- b = (struct vm_branch_t *)pte_addr(pte);
+ b = (struct vm_branch *)pte_addr(pte);
} while (top--);
return 0;
}
-int mod_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t paddr, uint8_t flags)
+int mod_vmem(struct vm_branch *branch, vm_t vaddr, pm_t paddr, uint8_t flags)
{
pm_t *pte = __find_vmem(branch, vaddr, 0);
if(pte){
- *pte = to_pte(paddr, flags);
+ *pte = to_pte((pm_t)__pa(paddr), flags);
return 0;
}
@@ -54,8 +56,8 @@ int mod_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t paddr, uint8_t flags)
/* huh, should probably add status flags etc. to all my API functions. Damn, I'm
* lazy. */
-int stat_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t *paddr,
- enum mm_order_t *order, uint8_t *flags)
+int stat_vmem(struct vm_branch *branch, vm_t vaddr, pm_t *paddr,
+ enum mm_order *order, uint8_t *flags)
{
pm_t *pte = __find_vmem(branch, vaddr, order);
if(pte){
@@ -71,30 +73,30 @@ int stat_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t *paddr,
return -1;
}
-static struct vm_branch_t *__create_leaf()
+static struct vm_branch *__create_leaf()
{
pm_t new_leaf = alloc_page(MM_KPAGE, 0);
- memset((void *)new_leaf, 0, sizeof(struct vm_branch_t));
- return (struct vm_branch_t *)to_pte(new_leaf, VM_V);
+ memset((void *)new_leaf, 0, sizeof(struct vm_branch));
+ return (struct vm_branch *)to_pte((pm_t)__pa(new_leaf), VM_V);
}
-static void __destroy_branch(struct vm_branch_t *b)
+static void __destroy_branch(struct vm_branch *b)
{
if(!b)
return;
for(size_t i = 0; i < BASE_PAGE_SIZE / sizeof(pm_t); ++i){
if(is_branch(b->leaf[i]))
- __destroy_branch((struct vm_branch_t *)pte_addr(b->leaf[i]));
+ __destroy_branch((struct vm_branch *)pte_addr(b->leaf[i]));
free_page(MM_KPAGE, (pm_t)pte_addr(b->leaf[i]));
}
}
-void map_vmem(struct vm_branch_t *branch,
- pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order_t order)
+void map_vmem(struct vm_branch *branch,
+ pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order order)
{
- enum mm_order_t top = __mm_max_order;
+ enum mm_order top = __mm_max_order;
while (top != order) {
size_t idx = vm_to_index(vaddr, top);
@@ -102,7 +104,7 @@ void map_vmem(struct vm_branch_t *branch,
branch->leaf[idx] = __create_leaf();
- branch = (struct vm_branch_t *)pte_addr(branch->leaf[idx]);
+ branch = (struct vm_branch *)pte_addr(branch->leaf[idx]);
top--;
}
@@ -110,10 +112,10 @@ void map_vmem(struct vm_branch_t *branch,
if (is_branch(branch->leaf[idx])) /* something has gone terribly wrong */
__destroy_branch(branch->leaf[idx]);
- branch->leaf[idx] = (struct vm_branch_t *)to_pte(paddr, flags);
+ branch->leaf[idx] = (struct vm_branch *)to_pte((pm_t)__pa(paddr), flags);
}
-void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr)
+void unmap_vmem(struct vm_branch *branch, vm_t vaddr)
{
pm_t *pte = __find_vmem(branch, vaddr, 0);
@@ -121,12 +123,60 @@ void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr)
*pte = 0;
}
-void flush_tlb(id_t cpu_id)
+void flush_tlb()
{
- __asm__("sfence.vma %0\n" :: "rk" (cpu_id) : "memory");
+ __asm__("sfence.vma %0\n" :: "rk" (cpu_id()) : "memory");
}
void flush_tlb_all()
{
__asm__("sfence.vma\n" ::: "memory");
}
+
+static void start_vmem(struct vm_branch *branch, enum mm_mode m)
+{
+ branch = (struct vm_branch *)__pa(branch);
+
+ 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)));
+
+ flush_tlb_all();
+ /* Sv57 && Sv64 in the future? */
+}
+
+struct vm_branch *init_vmem(void *fdt)
+{
+ UNUSED(fdt);
+ struct vm_branch *b = (struct vm_branch *)alloc_page(MM_KPAGE, 0);
+ memset(b, 0, MM_KPAGE_SIZE);
+
+ populate_root_branch(b);
+ /* update which memory branch to use */
+ start_vmem(b, Sv39);
+ return b;
+}
+
+void populate_root_branch(struct vm_branch *b)
+{
+ size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G;
+ for(size_t i = KSTART_PAGE; i < IO_PAGE; ++i)
+ b->leaf[i] = (struct vm_branch *)to_pte(RAM_BASE + SZ_1G * (i - KSTART_PAGE), flags);
+
+ /* map kernel IO to zero for now, this will be overridden later
+ * (if at all) */
+ b->leaf[IO_PAGE] = (struct vm_branch *)to_pte(0, flags);
+}
+
+#ifdef DEBUG
+int setup_kernel_io(struct vm_branch *b, vm_t paddr)
+{
+ /* assume Sv39 for now */
+ pm_t gigapage = paddr / MM_GPAGE_SIZE;
+ b->leaf[IO_PAGE] = (struct vm_branch *)to_pte(gigapage, VM_V | VM_R | VM_W);
+ return 0;
+}
+#endif
diff --git a/arch/riscv/source.mk b/arch/riscv/source.mk
index 0e9a5c3..e50880c 100644
--- a/arch/riscv/source.mk
+++ b/arch/riscv/source.mk
@@ -1,6 +1,6 @@
KERNEL_LOCAL != echo arch/riscv/kernel/*.[cS]
KERNEL_SOURCES += $(KERNEL_LOCAL)
-INIT_SOURCES += arch/riscv/init/init.c
+INIT_SOURCES += arch/riscv/init/*.[cS]
CLEANUP_CMD := ./arch/riscv/conf/rmimage.sh
diff --git a/common/debug.c b/common/debug.c
index 1800b1c..d34823a 100644
--- a/common/debug.c
+++ b/common/debug.c
@@ -59,7 +59,7 @@ static void __putchar(char c)
port->data = c;
}
-static enum serial_dev_t serial_dev_enum(const char *dev_name)
+static enum serial_dev serial_dev_enum(const char *dev_name)
{
if (strncmp("ns16550", dev_name, 7) == 0)
return NS16550A;
@@ -67,7 +67,7 @@ static enum serial_dev_t serial_dev_enum(const char *dev_name)
return -1;
}
-struct dbg_info_t dbg_from_fdt(void *fdt)
+struct dbg_info dbg_from_fdt(void *fdt)
{
int chosen_offset = fdt_path_offset(fdt, "/chosen");
const char *stdout = fdt_getprop(fdt, chosen_offset, "stdout-path", NULL);
@@ -78,22 +78,22 @@ struct dbg_info_t dbg_from_fdt(void *fdt)
const char *dev_name = (const char *)fdt_getprop(fdt, stdout_offset,
"compatible", NULL);
- enum serial_dev_t dev = serial_dev_enum(dev_name);
+ enum serial_dev dev = serial_dev_enum(dev_name);
/* get serial device address */
- struct cell_info_t ci = get_reginfo(fdt, stdout);
+ struct cell_info ci = get_reginfo(fdt, stdout);
void *reg_ptr = (void *)fdt_getprop(fdt, stdout_offset, "reg", NULL);
- void *dbg_ptr = (void *)(pm_t)fdt_load_int_ptr(ci.addr_cells, reg_ptr);
+ pm_t dbg_ptr = (pm_t)fdt_load_int_ptr(ci.addr_cells, reg_ptr);
- return (struct dbg_info_t){dbg_ptr, dev};
+ return (struct dbg_info){dbg_ptr, dev};
}
-void dbg_init(void *pt, enum serial_dev_t dev)
+void setup_dbg(vm_t pt, enum serial_dev dev)
{
switch (dev) {
case NS16550A:
- port = pt;
+ port = (struct ns16550a *)pt;
break;
}
diff --git a/common/elf.c b/common/elf.c
index fafef00..aab00d1 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -72,9 +72,9 @@ static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf)
}
/* sets up all memory regions etc, returns the entry address */
-vm_t prepare_proc(struct tcb *t, vm_t p)
+vm_t load_elf(struct tcb *t, vm_t b)
{
- struct elf_ident *i = (struct elf_ident *)p;
+ struct elf_ident *i = (struct elf_ident *)b;
if(i->ei_magic != cpu_to_be32(EI_MAGIC))
return 0;
@@ -82,5 +82,5 @@ vm_t prepare_proc(struct tcb *t, vm_t p)
return 0;
/* more sanity checks? */
- return __prepare_proc(t, i->ei_class, p);
+ return __prepare_proc(t, i->ei_class, b);
}
diff --git a/common/fdt.c b/common/fdt.c
index c554b25..f76ad64 100644
--- a/common/fdt.c
+++ b/common/fdt.c
@@ -1,19 +1,19 @@
#include <libfdt.h>
-struct cell_info_t get_cellinfo(void *fdt, int offset)
+struct cell_info get_cellinfo(void *fdt, int offset)
{
- return (struct cell_info_t){
+ return (struct cell_info){
fdt_size_cells(fdt, offset),
fdt_address_cells(fdt, offset)
};
}
/* how "reg" is interpreted depends on the parent node */
-struct cell_info_t get_reginfo(void *fdt, const char *path)
+struct cell_info get_reginfo(void *fdt, const char *path)
{
const char *i = strrchr(path, '/');
if(!i)
- return (struct cell_info_t){0, 0};
+ return (struct cell_info){0, 0};
size_t baselen = i - path;
if(i == 0)
diff --git a/common/initrd.c b/common/initrd.c
index 18db836..afce2ec 100644
--- a/common/initrd.c
+++ b/common/initrd.c
@@ -56,7 +56,7 @@ static struct cpio_header *find_file(char *c, char* fname, size_t fname_len)
pm_t get_initrdtop(void *fdt)
{
int chosen_offset = fdt_path_offset(fdt, "/chosen");
- struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
+ struct cell_info ci = get_cellinfo(fdt, chosen_offset);
void *initrd_end_ptr = (void *)fdt_getprop(fdt, chosen_offset,
"linux,initrd-end", NULL);
@@ -68,7 +68,7 @@ pm_t get_initrdtop(void *fdt)
pm_t get_initrdbase(void *fdt)
{
int chosen_offset = fdt_path_offset(fdt, "/chosen");
- struct cell_info_t ci = get_cellinfo(fdt, chosen_offset);
+ struct cell_info ci = get_cellinfo(fdt, chosen_offset);
void *initrd_base_ptr = (void *)fdt_getprop(fdt, chosen_offset,
"linux,initrd-start", NULL);
diff --git a/common/main.c b/common/main.c
new file mode 100644
index 0000000..f91fc22
--- /dev/null
+++ b/common/main.c
@@ -0,0 +1,52 @@
+#include <apos/mem_nodes.h>
+#include <apos/attrs.h>
+#include <apos/proc.h>
+#include <apos/debug.h>
+#include <apos/vmem.h>
+#include <apos/arch.h>
+#include <apos/irq.h>
+#include <libfdt.h>
+
+#ifdef DEBUG
+static struct dbg_info dbg_info = (struct dbg_info){0};
+
+static void init_dbg(void *fdt)
+{
+ dbg_info = dbg_from_fdt(fdt);
+}
+
+static void setup_dmap_dbg()
+{
+ setup_dbg(dbg_info.dbg_ptr, dbg_info.dev);
+}
+
+static void setup_io_dbg(struct vm_branch *b)
+{
+ vm_t io_ptr = setup_kernel_io(b, dbg_info.dbg_ptr);
+ setup_dbg(io_ptr, dbg_info.dev);
+}
+#else
+#define init_dbg(...)
+#define setup_dmap_dbg(...)
+#define setup_io_dbg(...)
+#endif
+
+void __main main(void *fdt)
+{
+ /* dbg uses direct mapping at this point */
+ init_dbg(fdt);
+ setup_dmap_dbg();
+ dbg_fdt(fdt);
+
+ arch_setup(fdt);
+
+ init_pmem(fdt);
+ init_mem_blocks();
+ struct vm_branch *b = init_vmem(fdt);
+
+ /* start up debugging in kernel IO */
+ setup_io_dbg(b);
+
+ init_irq(fdt);
+ init_proc(fdt, b);
+}
diff --git a/common/mem.c b/common/mem.c
index cff11b7..7a7eff6 100644
--- a/common/mem.c
+++ b/common/mem.c
@@ -24,25 +24,3 @@ void init_mem(size_t max_order, size_t bits[10], size_t page_shift)
__mm_sizes[i] = 1UL << __mm_shifts[i] << __mm_page_shift;
}
}
-
-enum mm_mode_t get_mmode(void *fdt)
-{
- int mmu_offset = fdt_path_offset(fdt, "/cpus/cpu");
- const char *mmu = fdt_getprop(fdt, mmu_offset, "mmu-type", NULL);
-
- if(strncmp("riscv,sv48", mmu, 10) == 0)
- return Sv48;
-
- if(strncmp("riscv,sv39", mmu, 10) == 0)
- return Sv39;
-
- if(strncmp("riscv,sv32", mmu, 10) == 0)
- return Sv32;
-
- /* fdt is missing mmu-type for some reason, but we can probably use
- * these values as fallback */
- if(__riscv_xlen == 32)
- return Sv32;
- else
- return Sv39;
-}
diff --git a/common/pmem.c b/common/pmem.c
index e40d160..d9cdd50 100644
--- a/common/pmem.c
+++ b/common/pmem.c
@@ -1,6 +1,9 @@
#include <apos/pmem.h>
+#include <apos/debug.h>
+#include <apos/initrd.h>
#include <apos/string.h> /* memset */
#include <apos/bits.h> /* __is_nset etc */
+#include <libfdt.h>
/* NOTE: these are all for pnum_t, i.e. O0_SHIFT is from 0 */
#define __foreach_page(var, start, end, attr, neg)\
@@ -41,7 +44,7 @@ struct mm_branch_t {
struct mm_omap_t {
pm_t base;
mm_node_t **orders;
- enum mm_order_t order;
+ enum mm_order order;
};
struct mm_pmap_t {
@@ -50,8 +53,8 @@ struct mm_pmap_t {
static struct mm_pmap_t *pmap = 0;
-static void __mark_free(mm_node_t * op, pnum_t pnum, enum mm_order_t tgt,
- enum mm_order_t src, enum mm_order_t dst)
+static void __mark_free(mm_node_t * op, pnum_t pnum, enum mm_order tgt,
+ enum mm_order src, enum mm_order dst)
{
size_t idx = pnum_to_index(pnum, src);
@@ -69,7 +72,7 @@ static void __mark_free(mm_node_t * op, pnum_t pnum, enum mm_order_t tgt,
__clear_nbit(o->full[__o_container(idx)], __o_bit(idx));
}
-void free_page(enum mm_order_t order, pm_t paddr)
+void free_page(enum mm_order order, pm_t paddr)
{
for (size_t i = MM_O0; i <= __mm_max_order; ++i) {
if (!pmap->omap[i])
@@ -88,8 +91,8 @@ void free_page(enum mm_order_t order, pm_t paddr)
}
}
-static bool __mark_used(mm_node_t * op, pnum_t pnum, enum mm_order_t tgt,
- enum mm_order_t src, enum mm_order_t dst)
+static bool __mark_used(mm_node_t * op, pnum_t pnum, enum mm_order tgt,
+ enum mm_order src, enum mm_order dst)
{
size_t idx = pnum_to_index(pnum, src);
@@ -123,7 +126,7 @@ static bool __mark_used(mm_node_t * op, pnum_t pnum, enum mm_order_t tgt,
return false;
}
-void mark_used(enum mm_order_t order, pm_t paddr)
+void mark_used(enum mm_order order, pm_t paddr)
{
for (size_t i = MM_O0; i <= __mm_max_order; ++i) {
if (!pmap->omap[i])
@@ -143,7 +146,7 @@ void mark_used(enum mm_order_t order, pm_t paddr)
}
static pnum_t __enum_order(mm_node_t * op, pnum_t offset,
- enum mm_order_t src, enum mm_order_t dst)
+ enum mm_order src, enum mm_order dst)
{
size_t idx = pnum_to_index(offset, src);
@@ -173,7 +176,7 @@ static pnum_t __enum_order(mm_node_t * op, pnum_t offset,
return -1;
}
-pm_t alloc_page(enum mm_order_t order, pm_t offset)
+pm_t alloc_page(enum mm_order order, pm_t offset)
{
if (order > __mm_max_order)
return 0;
@@ -204,57 +207,9 @@ pm_t alloc_page(enum mm_order_t order, pm_t offset)
return paddr;
}
-
-
-static void __update_order(mm_node_t * op, pm_t base, pm_t offset,
- enum mm_order_t src, enum mm_order_t dst)
-{
- if (src == dst) {
- struct mm_leaf_t *o = (struct mm_leaf_t *)op;
- o->used = (mm_info_t *) move_paddr(o->used, base, offset);
- return;
- }
-
- struct mm_branch_t *o = (struct mm_branch_t *)op;
- o->full = (mm_info_t *) move_paddr(o->full, base, offset);
- for (size_t i = 0; i < o->entries; ++i) {
- __update_order(o->next[i], base, offset, src - 1, dst);
- o->next[i] =
- (mm_node_t **) move_paddr(o->next[i], base, offset);
- }
-
- o->next = (mm_node_t **) move_paddr(o->next, base, offset);
-}
-
-static void __update_omap(struct mm_omap_t *omap, pm_t base, pm_t offset)
-{
- for (size_t i = MM_O0; i <= omap->order; ++i) {
- __update_order(omap->orders[i], base, offset, omap->order, i);
- omap->orders[i] =
- (mm_node_t *) move_paddr(omap->orders[i], base, offset);
- }
-
- omap->orders = (mm_node_t **) move_paddr(omap->orders, base, offset);
-}
-
-void update_pmap(pm_t offset)
-{
- pm_t base = (pm_t) pmap;
- for (size_t i = 0; i <= __mm_max_order; ++i) {
- if (!pmap->omap[i])
- continue;
-
- __update_omap(pmap->omap[i], base, offset);
- pmap->omap[i] = (struct mm_omap_t *)move_paddr(pmap->omap[i],
- base, offset);
- }
-
- pmap = (struct mm_pmap_t *)move_paddr(pmap, base, offset);
-}
-
/* unfortunate that populating the mm info is so complicated */
static pm_t __populate_order(mm_node_t ** op, pm_t cont,
- enum mm_order_t src, enum mm_order_t dst, size_t num)
+ enum mm_order src, enum mm_order dst, size_t num)
{
if (src == dst) {
struct mm_leaf_t *o = (struct mm_leaf_t *)
@@ -286,7 +241,7 @@ static pm_t __populate_order(mm_node_t ** op, pm_t cont,
return cont;
}
-static pm_t __probe_order(pm_t cont, enum mm_order_t src, enum mm_order_t dst,
+static pm_t __probe_order(pm_t cont, enum mm_order src, enum mm_order dst,
size_t num)
{
if(src == dst){
@@ -306,7 +261,7 @@ static pm_t __probe_order(pm_t cont, enum mm_order_t src, enum mm_order_t dst,
}
static pm_t __populate_omap(struct mm_omap_t **omap, pm_t cont,
- pm_t base, size_t entries, enum mm_order_t order)
+ pm_t base, size_t entries, enum mm_order order)
{
struct mm_omap_t *lomap = (struct mm_omap_t *)
move_forward(cont, sizeof(struct mm_omap_t));
@@ -327,7 +282,7 @@ static pm_t __populate_omap(struct mm_omap_t **omap, pm_t cont,
return cont;
}
-static pm_t __probe_omap(pm_t cont, size_t entries, enum mm_order_t order)
+static pm_t __probe_omap(pm_t cont, size_t entries, enum mm_order order)
{
cont += sizeof(struct mm_omap_t);
cont += (order + 1) * sizeof(mm_node_t **);
@@ -388,8 +343,104 @@ pm_t probe_pmap(pm_t ram_base, size_t ram_size)
return cont;
}
-/* only call from kernel */
-void init_pmap(void *p)
+static void mark_area_used(pm_t base, pm_t top)
{
- pmap = (struct mm_pmap_t *)p;
+ size_t area_left = top - base;
+ pm_t runner = base;
+ while(area_left >= BASE_PAGE_SIZE){
+ mark_used(BASE_PAGE, runner);
+ runner += BASE_PAGE_SIZE;
+ area_left -= BASE_PAGE_SIZE;
+ }
+
+ if(area_left != 0)
+ mark_used(BASE_PAGE, runner);
+}
+
+static void mark_reserved_mem(void *fdt)
+{
+ int rmem_offset = fdt_path_offset(fdt, "/reserved-memory/mmode_resv0");
+ struct cell_info 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;
+ mark_area_used((pm_t)__va(base), (pm_t)__va(top));
+}
+
+static pm_t get_ramtop(void *fdt)
+{
+ struct cell_info 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);
+
+ 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);
+
+ return (pm_t)fdt_load_int_ptr(ci.size_cells, mem_reg) + base;
+}
+
+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;
+}
+
+void init_pmem(void *fdt)
+{
+ size_t max_order = 0;
+ size_t base_bits = 0;
+ size_t bits[ORDERS_NUM] = {0};
+ arch_pmem_conf(fdt, &max_order, &base_bits, bits);
+ init_mem(max_order, bits, base_bits);
+
+ pm_t ram_size = get_ramtop(fdt) - RAM_BASE;
+ pm_t ram_base = (pm_t)__va(RAM_BASE);
+
+ pm_t initrd_top = get_initrdtop(fdt);
+ pm_t fdt_top = get_fdttop(fdt);
+
+ /* find probably most suitable contiguous region of ram for our physical
+ * ram map */
+ pm_t pmap_base = align_up(MAX(initrd_top, fdt_top), sizeof(int));
+
+ size_t probe_size = probe_pmap(ram_base, ram_size);
+ size_t actual_size = populate_pmap(ram_base, ram_size, pmap_base);
+
+ if(probe_size != actual_size)
+ dbg("BUG! probe_size (%#lx) != actual_size (%#lx)\n",
+ probe_size, actual_size);
+
+ /* mark init stack, this should be unmapped once we get to executing
+ * processes */
+ mark_area_used((pm_t)__va(PM_STACK_BASE), (pm_t)__va(PM_STACK_TOP));
+
+ /* mark kernel */
+ mark_area_used((pm_t)__va(PM_KERN_BASE), (pm_t)__va(PM_KERN_TOP));
+
+ /* 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);
}
diff --git a/common/proc.c b/common/proc.c
index 5fdf413..ccd60bd 100644
--- a/common/proc.c
+++ b/common/proc.c
@@ -1,16 +1,50 @@
+#include <apos/conf.h>
+#include <apos/elf.h>
+#include <apos/string.h>
+#include <apos/initrd.h>
#include <apos/proc.h>
/* TODO: add error checking */
-vm_t setup_call_stack(struct tcb *t, vm_t start, size_t bytes)
+static vm_t setup_call_stack(struct tcb *t, size_t bytes)
{
pm_t offset = 0;
size_t pages = __pages(bytes);
uint8_t flags = VM_V | VM_R | VM_W | VM_U;
- for(size_t i = 0; i < pages; ++i)
+ for(size_t i = 1; i <= pages; ++i)
{
offset = alloc_page(BASE_PAGE, offset);
- map_vmem(t->b_r, offset, start + BASE_PAGE_SIZE * i, flags, BASE_PAGE);
+ map_vmem(t->b_r, offset, PROC_STACK_TOP - BASE_PAGE_SIZE * i, flags, BASE_PAGE);
}
- return start;
+ return PROC_STACK_TOP - BASE_PAGE_SIZE * pages;
+}
+
+static vm_t setup_proc_stack(struct tcb *t, size_t bytes)
+{
+ return alloc_uvmem(t, bytes, VM_V | VM_R | VM_W | VM_U);
+}
+
+void init_proc(void *fdt, struct vm_branch *b)
+{
+ struct tcb *t = (struct tcb *)alloc_page(BASE_PAGE, 0);
+ memset(t, 0, sizeof(struct tcb));
+ t->b_r = b;
+ t->pid = 0;
+ t->tid = 0;
+
+ threads_insert(t);
+
+ sp_mem_init(&t->sp_r, UVMEM_START, UVMEM_END);
+
+ /* the binary gets to choose first what memory regions it requires */
+ t->entry = load_elf(t, get_init_base(fdt));
+
+ t->proc_stack = setup_proc_stack(t, __proc_stack_size);
+ t->call_stack = setup_call_stack(t, __call_stack_size);
+
+
+ flush_tlb();
+
+ /* TODO: move fdt into process space */
+ jump_to_userspace(t, 1, 0);
}
diff --git a/common/tcb.c b/common/tcb.c
index 1547d49..cbbfa47 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -67,3 +67,8 @@ struct tcb *cur_tcb()
{
return __tcb_cache[cpu_id()];
}
+
+void set_tcb(struct tcb *t)
+{
+ __tcb_cache[cpu_id()] = t;
+}
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index 01c4ada..6f4faff 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -1,5 +1,9 @@
+#include <apos/sizes.h>
#include <apos/uapi.h>
+size_t __proc_stack_size = SZ_2M;
+size_t __call_stack_size = SZ_2M;
+
vm_t sys_conf(vm_t param, vm_t val, vm_t u0, vm_t u1)
{
UNUSED(u0); UNUSED(u1);
diff --git a/common/vmem.c b/common/vmem.c
index ffe9b32..9ff3b96 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -182,6 +182,9 @@ static struct sp_mem *sp_find_used_closest(struct sp_reg_root *r, vm_t start)
struct sp_mem *closest = 0;
size_t md = (size_t)(-1);
struct sp_node *n = sp_root(r->used_regions);
+ if(!n)
+ return mem_container(sp_root(r->free_regions));
+
while(n){
struct sp_mem *t = mem_container(n);
size_t d = ABS((ssize_t)start - (ssize_t)t->start);
@@ -415,12 +418,12 @@ size_t uvmem_size()
* NOTE: not actually optimal, this doesn't bother to go through possible
* permutations etc. which would be slow and I don't want to implement it.
*/
-vm_t map_fill_region(struct vm_branch_t *b, vm_t start, size_t bytes, uint8_t flags)
+vm_t map_fill_region(struct vm_branch *b, vm_t start, size_t bytes, uint8_t flags)
{
pm_t offset = 0;
pm_t runner = __page(start);
size_t pages = __pages(bytes);
- enum mm_order_t top = __mm_max_order;
+ enum mm_order top = __mm_max_order;
/* actual start might not be the same as the user specified start */
start = __addr(runner);
diff --git a/include/apos/arch.h b/include/apos/arch.h
new file mode 100644
index 0000000..b846876
--- /dev/null
+++ b/include/apos/arch.h
@@ -0,0 +1,6 @@
+#ifndef APOS_ARCH_H
+#define APOS_ARCH_H
+
+void arch_setup(void *fdt);
+
+#endif /* APOS_ARCH_H */
diff --git a/include/apos/conf.h b/include/apos/conf.h
new file mode 100644
index 0000000..844ce37
--- /dev/null
+++ b/include/apos/conf.h
@@ -0,0 +1,9 @@
+#ifndef APOS_CONF_H
+#define APOS_CONF_H
+
+#include <apos/types.h>
+
+extern size_t __proc_stack_size;
+extern size_t __call_stack_size;
+
+#endif /* APOS_CONF_H */
diff --git a/include/apos/debug.h b/include/apos/debug.h
index 5830c45..1a3265f 100644
--- a/include/apos/debug.h
+++ b/include/apos/debug.h
@@ -2,26 +2,28 @@
#define APOS_DEBUG_H
#include <apos/attrs.h>
+#include <apos/pmem.h>
#ifdef DEBUG
-enum serial_dev_t {
+enum serial_dev {
/* only the NS16550A and compatible at the moment */
NS16550A,
};
-struct dbg_info_t {
- void *dbg_ptr;
- enum serial_dev_t dev;
+struct dbg_info {
+ pm_t dbg_ptr;
+ enum serial_dev dev;
};
void __fmt(1, 2) dbg(const char *fmt, ...);
-void dbg_init(void *pt, enum serial_dev_t dev);
-struct dbg_info_t dbg_from_fdt(void *fdt);
+void setup_dbg(pm_t pt, enum serial_dev dev);
+struct dbg_info dbg_from_fdt(void *fdt);
#else
#define dbg(...)
#define dbg_init(...)
+#define dbg_from_fdt(...)
#endif /* DEBUG */
diff --git a/include/apos/elf.h b/include/apos/elf.h
index df07b7f..4fe74d1 100644
--- a/include/apos/elf.h
+++ b/include/apos/elf.h
@@ -184,6 +184,6 @@ __packed struct section64_header {
#define program_header_prop(c, e, p) (c == ELFCLASS64 ? program64_header(e)->p : program32_header(e)->p)
#define section_header_prop(c, e, p) (c == ELFCLASS64 ? section64_header(e)->p : section32_header(e)->p)
-vm_t prepare_proc(struct tcb *t, vm_t p);
+vm_t load_elf(struct tcb *t, vm_t b);
#endif /* APOS_ELF_H */
diff --git a/include/apos/irq.h b/include/apos/irq.h
index 958b25f..3ce6556 100644
--- a/include/apos/irq.h
+++ b/include/apos/irq.h
@@ -1,6 +1,8 @@
#ifndef APOS_IRQ_H
#define APOS_IRQ_H
+void init_irq(void *fdt);
+void handle_irq();
void enable_irq();
void disable_irq();
diff --git a/include/apos/mem.h b/include/apos/mem.h
index 0b3bffd..e935fe4 100644
--- a/include/apos/mem.h
+++ b/include/apos/mem.h
@@ -37,7 +37,7 @@ extern size_t __mm_page_shift;
extern size_t __mm_max_order;
void init_mem(size_t max_order, size_t shifts[10], size_t page_shift);
-enum mm_mode_t get_mmode(void *fdt);
+enum mm_mode get_mmode(void *fdt);
#define BASE_PAGE_SIZE (__o_size(BASE_PAGE))
#define BASE_PAGE (MM_O0)
diff --git a/include/apos/pmem.h b/include/apos/pmem.h
index 01d89ce..2850f22 100644
--- a/include/apos/pmem.h
+++ b/include/apos/pmem.h
@@ -4,7 +4,8 @@
#include <apos/mem.h>
#include <apos/types.h>
-enum mm_order_t {
+#define ORDERS_NUM 10
+enum mm_order {
MM_O0,
MM_O1,
MM_O2,
@@ -20,12 +21,18 @@ enum mm_order_t {
typedef size_t pm_t;
typedef ssize_t pnum_t;
+/* arch */
+int arch_pmem_conf(void *fdt, size_t *max_order, size_t *base_bits, size_t bits[ORDERS_NUM]);
+
+/* common */
void update_pmap(pm_t offset);
-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);
+void free_page(enum mm_order order, pm_t paddr);
+void mark_used(enum mm_order order, pm_t paddr);
+pm_t alloc_page(enum mm_order order, pm_t offset);
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);
+void init_pmem(void *fdt);
+
#endif /* APOS_PMEM_H */
diff --git a/include/apos/proc.h b/include/apos/proc.h
index 6f272b1..f835394 100644
--- a/include/apos/proc.h
+++ b/include/apos/proc.h
@@ -4,7 +4,7 @@
#include <apos/tcb.h>
#include <apos/vmem.h>
-void jump_to_userspace(struct tcb *t, vm_t bin, int argc, char **argv);
-vm_t setup_call_stack(struct tcb *t, vm_t start, size_t bytes);
+void jump_to_userspace(struct tcb *t, int argc, char **argv);
+void init_proc(void *fdt, struct vm_branch *b);
#endif /* APOS_PROC_H */
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index 1d85e8b..0a07d7b 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -31,7 +31,7 @@ struct tcb {
vm_t entry;
- struct vm_branch_t *b_r;
+ struct vm_branch *b_r;
};
void threads_insert(struct tcb *t);
diff --git a/include/apos/vmem.h b/include/apos/vmem.h
index 93d2ed7..87a3aa6 100644
--- a/include/apos/vmem.h
+++ b/include/apos/vmem.h
@@ -39,13 +39,22 @@ 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);
+void map_vmem(struct vm_branch *branch,
+ pm_t paddr, vm_t vaddr, uint8_t flags, enum mm_order order);
-void unmap_vmem(struct vm_branch_t *branch, vm_t vaddr);
-int mod_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t paddr, uint8_t flags);
-int stat_vmem(struct vm_branch_t *branch, vm_t vaddr, pm_t *paddr,
- enum mm_order_t *order, uint8_t *flags);
+void unmap_vmem(struct vm_branch *branch, vm_t vaddr);
+int mod_vmem(struct vm_branch *branch, vm_t vaddr, pm_t paddr, uint8_t flags);
+int stat_vmem(struct vm_branch *branch, vm_t vaddr, pm_t *paddr,
+ enum mm_order *order, uint8_t *flags);
+
+int setup_kernel_io(struct vm_branch *b, vm_t paddr);
+void populate_root_branch(struct vm_branch *b);
+struct vm_branch *init_vmem(void *fdt);
+
+void flush_tlb();
+void flush_tlb_all();
+
+/* defined in common */
int sp_mem_init(struct sp_reg_root *r, vm_t start, size_t nums);
@@ -57,7 +66,7 @@ vm_t alloc_uvmem(struct tcb *r, size_t size, uint8_t flags);
vm_t alloc_fixed_uvmem(struct tcb *r, vm_t start, size_t size, 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_fill_region(struct vm_branch *b, vm_t start, size_t bytes, uint8_t flags);
size_t uvmem_size();
void set_uvmem_size(size_t s);
diff --git a/include/libfdt.h b/include/libfdt.h
index aa95bd3..304abb7 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1,15 +1,16 @@
#ifndef APOS_LIBFDT_H
#define APOS_LIBFDT_H
#include "../dtc/libfdt/libfdt.h"
+#include <apos/types.h>
/* apos additions, implementation can be found in common/fdt.c */
-struct cell_info_t {
+struct cell_info {
uint32_t size_cells;
uint32_t addr_cells;
};
-struct cell_info_t get_cellinfo(void *fdt, int offset);
-struct cell_info_t get_reginfo(void *fdt, const char *path);
+struct cell_info get_cellinfo(void *fdt, int offset);
+struct cell_info get_reginfo(void *fdt, const char *path);
#if defined(DEBUG)
void __dbg_fdt(void *fdt, int node_offset, int depth);