diff options
author | Zachary Yedidia <zyedidia@gmail.com> | 2022-05-12 16:53:06 -0700 |
---|---|---|
committer | Zachary Yedidia <zyedidia@gmail.com> | 2022-05-12 16:53:06 -0700 |
commit | 723c7189369c98bbf6f2243a3292ad05a1658f16 (patch) | |
tree | f730efbacd10e27e6028440817dcf68e78e692ec | |
parent | 357d6622fe0d993dbd67898f4e4d420c9c17f50f (diff) |
Boot a basic programlink-high
-rw-r--r-- | kern/boot.c | 5 | ||||
-rw-r--r-- | kern/interrupts-asm.s | 5 | ||||
-rw-r--r-- | kern/kern.c | 9 | ||||
-rw-r--r-- | kern/kern.mk | 16 | ||||
-rw-r--r-- | kern/kmalloc.c | 9 | ||||
-rw-r--r-- | kern/kmalloc.h | 1 | ||||
-rw-r--r-- | kern/kmalloc_old.c | 243 | ||||
-rw-r--r-- | kern/p-basic.c | 5 | ||||
-rw-r--r-- | kern/proc.c | 28 | ||||
-rw-r--r-- | kern/proc.h | 11 | ||||
-rw-r--r-- | kern/syscall.c | 21 | ||||
-rw-r--r-- | kern/vm.c | 13 | ||||
-rw-r--r-- | kern/vm.h | 9 | ||||
-rw-r--r-- | prog/basic/Makefile | 14 | ||||
-rw-r--r-- | prog/basic/basic.ld | 20 | ||||
-rw-r--r-- | prog/basic/basic.s | 6 | ||||
-rw-r--r-- | todo.txt | 4 | ||||
-rwxr-xr-x | tools/exify/exify.sh | 6 |
18 files changed, 121 insertions, 304 deletions
diff --git a/kern/boot.c b/kern/boot.c index f75422f..120e202 100644 --- a/kern/boot.c +++ b/kern/boot.c @@ -18,9 +18,6 @@ static void __attribute__((section(".text.boot"))) dmap_kernel_sections(); void __attribute__((section(".text.boot"))) cstart(); extern void __attribute__((section(".text.boot"))) _hlt(); -// 1mb -#define SEC_SIZE (1 << 20) - // map va to pa in the kernel pagetable static void vm_kernel_map(uintptr_t va, uintptr_t pa) { pte_1mb_t* pgtbl = (pte_1mb_t*) ka2pa((uintptr_t) kernel_pagetable); @@ -45,7 +42,7 @@ static void dmap_kernel_section(uintptr_t pa) { // double map all kernel regions static void dmap_kernel_sections() { // map kernel - for (uintptr_t pa = 0; pa < MEMSIZE_PHYSICAL; pa += SEC_SIZE) { + for (uintptr_t pa = 0; pa < MEMSIZE_PHYSICAL; pa += SIZE_1MB) { dmap_kernel_section(pa); } // map uart, gpio, watchdog timer diff --git a/kern/interrupts-asm.s b/kern/interrupts-asm.s index cca05ce..ee440aa 100644 --- a/kern/interrupts-asm.s +++ b/kern/interrupts-asm.s @@ -29,14 +29,13 @@ asm_undef_insn: ldr sp, =kstack ldr pc, _vec_undef_insn asm_software_irq: - ldr sp, =curproc + ldr sp, =kstack sub lr, lr, #4 push {lr} stmfd sp, {r0-r14}^ + sub sp, sp, #60 mov r0, sp - ldr sp, =kstack bl syscall - ldr sp, =curproc ldm sp, {r0-r15}^ asm_prefetch_abort: ldr sp, =kstack diff --git a/kern/kern.c b/kern/kern.c index b70d9ed..bb821dc 100644 --- a/kern/kern.c +++ b/kern/kern.c @@ -8,6 +8,8 @@ #include "sys.h" #include "uart.h" #include "vm.h" +#include "proc.h" +#include "kmalloc.h" void reboot() { printf("DONE!!!\n"); @@ -35,9 +37,16 @@ void kernel_start() { uart_init(115200); init_printf(NULL, uart_putc); irq_init(); + kmalloc_init(); printf("kernel booted\n"); + proc_t p_basic; + extern unsigned char prog_basic[]; + extern size_t prog_basic_sz; + proc_new(&p_basic, &prog_basic[0], prog_basic_sz); + proc_run(&p_basic); + reboot(); return; } diff --git a/kern/kern.mk b/kern/kern.mk index a5dd7e2..19dfa6e 100644 --- a/kern/kern.mk +++ b/kern/kern.mk @@ -7,18 +7,4 @@ KERN_HSRC = $(wildcard $(KERN)/*.h) $(wildcard $(PIOS)/libc/*.h) KERN_SSRC = $(wildcard $(KERN)/*.s) KERN_OBJ_NOSAN = $(KERN)/ksan.o $(KERN)/boot.o $(KERN)/uart.o $(KERN)/start.o $(KERN)/gpio.o $(KERN)/kmalloc.o $(PIOS)/libc/tinyprintf.o - -KERN_OBJ = $(KERN)/boot.o \ - $(KERN)/start.o \ - $(KERN)/uart.o \ - $(KERN)/gpio.o \ - $(KERN)/kern.o \ - $(KERN)/interrupts-asm.o \ - $(KERN)/interrupts.o \ - $(KERN)/syscall.o \ - $(KERN)/kmalloc.o \ - $(KERN)/vm.o \ - $(KERN)/proc.o \ - $(KERN)/ksan.o \ - $(PIOS)/libc/libc.o \ - $(PIOS)/libc/tinyprintf.o +KERN_OBJ = $(KERN_CSRC:.c=.o) $(KERN_SSRC:.s=.o) diff --git a/kern/kmalloc.c b/kern/kmalloc.c index b6d4cf5..e57b87f 100644 --- a/kern/kmalloc.c +++ b/kern/kmalloc.c @@ -76,11 +76,11 @@ static free_page_t* pn_to_free(uintptr_t pn) { extern char _kheap_start; -// Initialize everything needed for kalloc -void init_kalloc() { +// Initialize everything needed for kmalloc +void kmalloc_init() { // Iterate through all heap memory, mark as free, and coalesce blocks // together if possible - uintptr_t heap_start = (uintptr_t) &_kheap_start; + uintptr_t heap_start = ka2pa((uintptr_t) &_kheap_start); for (uintptr_t pa = heap_start; pa < MEMSIZE_PHYSICAL; pa += PAGESIZE) { uintptr_t pn = pagenum(pa); pages[pn].free = true; @@ -97,6 +97,7 @@ void init_kalloc() { order++; pages[pn].order = 0; pn = bpn; + continue; } break; } @@ -104,7 +105,7 @@ void init_kalloc() { // Now we set up the free lists by looping over each block and adding it to // the list - uintptr_t pn = 0; + uintptr_t pn = pagenum(heap_start); while (pn < pagenum(MEMSIZE_PHYSICAL)) { phys_page_t page = pages[pn]; assert(valid(pn, page.order)); diff --git a/kern/kmalloc.h b/kern/kmalloc.h index 82cbba0..3c4c54b 100644 --- a/kern/kmalloc.h +++ b/kern/kmalloc.h @@ -3,6 +3,7 @@ #include <stdint.h> #include <string.h> +void kmalloc_init(); void* kmalloc(size_t size); void* kmalloc_aligned(size_t size, size_t align); void kfree(void* p); diff --git a/kern/kmalloc_old.c b/kern/kmalloc_old.c deleted file mode 100644 index 6d43506..0000000 --- a/kern/kmalloc_old.c +++ /dev/null @@ -1,243 +0,0 @@ -#include <stdbool.h> -#include <stdint.h> - -#include "kern.h" -#include "kmalloc.h" - -union align { - double d; - void* p; - void (*fp)(void); -}; - -typedef union free_hdr { /* block header */ - struct { - union free_hdr* ptr; /* next block if on free list */ - unsigned size; /* size of this block */ - } s; - union align x; /* force alignment of blocks */ -} free_hdr_t; - -extern char _kheap_start; -uintptr_t heap_start() { - return (uintptr_t) &_kheap_start; -} - -static uintptr_t _kheap_end = (uintptr_t) &_kheap_start; -uintptr_t heap_end() { - return _kheap_end; -} - -static inline uintptr_t align_off(uintptr_t ptr, size_t align) { - return ((~ptr) + 1) & (align - 1); -} - -static void* sbrk(size_t size, size_t align) { - void* ret = (void*) _kheap_end; - _kheap_end += size; - _kheap_end += align_off(_kheap_end, __alignof__(free_hdr_t)); - return ret; -} - -static free_hdr_t base; /* empty list to get started */ -static free_hdr_t* freep = NULL; /* start of free list */ - -static void kr_free(void* ap); - -#define NALLOC 1024 /* minimum #units to request */ -/* morecore: ask system for more memory */ -static free_hdr_t* morecore(unsigned nu) { - char* cp; - free_hdr_t* up; - if (nu < NALLOC) - nu = NALLOC; - cp = sbrk(nu * sizeof(free_hdr_t)); - if (cp == (char*) -1) /* no space at all */ - return NULL; - up = (free_hdr_t*) cp; - up->s.size = nu; - kr_free((void*) (up + 1)); - return freep; -} - -static void* kr_malloc(size_t nbytes) { - free_hdr_t *p, *prevp; - unsigned nunits; - nunits = (nbytes + sizeof(free_hdr_t) - 1) / sizeof(free_hdr_t) + 1; - if ((prevp = freep) == NULL) { /* no free list yet */ - base.s.ptr = freep = prevp = &base; - base.s.size = 0; - } - for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr) { - if (p->s.size >= nunits) { /* big enough */ - if (p->s.size == nunits) /* exactly */ - prevp->s.ptr = p->s.ptr; - else { /* allocate tail end */ - p->s.size -= nunits; - p += p->s.size; - p->s.size = nunits; - } - freep = prevp; - return (void*) (p + 1); - } - if (p == freep) /* wrapped around free list */ - if ((p = morecore(nunits)) == NULL) - return NULL; /* none left */ - } -} - -/* free: put block ap in free list */ -static void kr_free(void* ap) { - free_hdr_t *bp, *p; - bp = (free_hdr_t*) ap - 1; /* point to block header */ - for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) - if (p >= p->s.ptr && (bp > p || bp < p->s.ptr)) - break; /* freed block at start or end of arena */ - if (bp + bp->s.size == p->s.ptr) { /* join to upper nbr */ - bp->s.size += p->s.ptr->s.size; - bp->s.ptr = p->s.ptr->s.ptr; - } else - bp->s.ptr = p->s.ptr; - if (p + p->s.size == bp) { /* join to lower nbr */ - p->s.size += bp->s.size; - p->s.ptr = bp->s.ptr; - } else - p->s.ptr = bp; - freep = p; -} - -#if (SANITIZE == 0) - -void* kmalloc(size_t sz) { - return kr_malloc(sz); -} - -void kfree(void* p) { - kr_free(p); -} - -#else - -typedef struct asan_hdr { - size_t size; - struct asan_hdr* next; - struct asan_hdr* prev; -} asan_hdr_t; - -static asan_hdr_t* alloc_list; - -static void ll_insert(asan_hdr_t* n) { - n->next = alloc_list; - n->prev = NULL; - if (alloc_list) - alloc_list->prev = n; - alloc_list = n; -} - -static void ll_remove(asan_hdr_t* n) { - if (n->next) - n->next->prev = n->prev; - if (n->prev) - n->prev->next = n->next; - else - alloc_list = n->next; -} - -static char* blk_start(asan_hdr_t* h) { - return (char*) h + sizeof(asan_hdr_t); -} - -static char* blk_end(asan_hdr_t* h) { - return (char*) h + sizeof(asan_hdr_t) + h->size; -} - -void* kmalloc(size_t sz) { - asan_hdr_t* h = (asan_hdr_t*) kr_malloc(sz + sizeof(asan_hdr_t)); - h->size = sz; - ll_insert(h); - return (void*) blk_start(h); -} - -void kfree(void* p) { - asan_hdr_t* h = (asan_hdr_t*) ((char*) p - sizeof(asan_hdr_t)); - ll_remove(h); - kr_free(h); -} - -static bool asan = false; - -static bool in_range(char* addr, char* start, char* end) { - return addr >= start && addr < end; -} - -static void asan_access(unsigned long addr, size_t sz, bool write) { - if (!asan) { - return; - } - - extern char _ktext_start, _ktext_end; - if (write && in_range((char*) addr, &_ktext_start, &_ktext_end)) { - panic("write to code segment: 0x%lx\n", addr); - } - extern char _krodata_start, _krodata_end; - if (write && in_range((char*) addr, &_krodata_start, &_krodata_end)) { - panic("write to read-only data segment: 0x%lx\n", addr); - } - if (in_range((char*) addr, &_kheap_start, (char*) _kheap_end)) { - asan_hdr_t* h = alloc_list; - while (h) { - if (in_range((char*) addr, blk_start(h), blk_end(h))) { - return; - } - h = h->next; - } - panic("illegal heap memory access: 0x%lx\n", addr); - } -} - -void __asan_load1_noabort(unsigned long addr) { - asan_access(addr, 1, false); -} -void __asan_load2_noabort(unsigned long addr) { - asan_access(addr, 2, false); -} -void __asan_load4_noabort(unsigned long addr) { - asan_access(addr, 4, false); -} -void __asan_load8_noabort(unsigned long addr) { - asan_access(addr, 8, false); -} -void __asan_loadN_noabort(unsigned long addr, size_t sz) { - asan_access(addr, sz, false); -} - -void __asan_store1_noabort(unsigned long addr) { - asan_access(addr, 1, true); -} -void __asan_store2_noabort(unsigned long addr) { - asan_access(addr, 2, true); -} -void __asan_store4_noabort(unsigned long addr) { - asan_access(addr, 4, true); -} -void __asan_store8_noabort(unsigned long addr) { - asan_access(addr, 8, true); -} -void __asan_storeN_noabort(unsigned long addr, size_t sz) { - asan_access(addr, sz, true); -} - -void __asan_handle_no_return() {} -void __asan_before_dynamic_init(const char* module_name) {} -void __asan_after_dynamic_init() {} - -void asan_enable() { - /* asan = true; */ -} - -#endif - -void* kmalloc_aligned(size_t sz, size_t align) { - uintptr_t x = (uintptr_t) kmalloc(sz + align); - return (void*) (x + align_off(x, align)); -} diff --git a/kern/p-basic.c b/kern/p-basic.c new file mode 100644 index 0000000..2c4d42e --- /dev/null +++ b/kern/p-basic.c @@ -0,0 +1,5 @@ +#include <string.h> +unsigned char prog_basic[] = { + 0x00, 0x00, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0xef, +}; +size_t prog_basic_sz = sizeof(prog_basic); diff --git a/kern/proc.c b/kern/proc.c index 1a87cde..32ea910 100644 --- a/kern/proc.c +++ b/kern/proc.c @@ -1,17 +1,33 @@ +#include "kern.h" #include "proc.h" #include "vm.h" +#include "kmalloc.h" static pid_t id; proc_t procs[NPROC]; proc_t* curproc; -void proc_new(proc_t* proc) { - *proc = (proc_t) { - .id = id++, - .pt = kalloc_pt(), - .state = PROC_RUNNABLE, - }; +void proc_new(proc_t* proc, uint8_t* code, size_t codesz) { + proc->id = id++; + proc->pt = kalloc_pt(); + proc->state = PROC_RUNNABLE; + proc->code = code; + proc->codesz = codesz; + // map kernel into pt + for (uintptr_t pa = 0; pa < MEMSIZE_PHYSICAL; pa += SIZE_1MB) { + vm_map(proc->pt, pa2ka(pa), pa, PAGE_1MB); + } + // map kernel devices + vm_map(proc->pt, pa2ka(0x20000000), 0x20000000, PAGE_1MB); + vm_map(proc->pt, pa2ka(0x20100000), 0x20100000, PAGE_1MB); + vm_map(proc->pt, pa2ka(0x20200000), 0x20200000, PAGE_1MB); + // map proc code into pt + void* pgs = kmalloc(proc->codesz); + memcpy(pgs, proc->code, proc->codesz); + for (size_t n = 0; n < proc->codesz; n += SIZE_4KB) { + vm_map(proc->pt, PROC_ENTRY + n, ka2pa((uintptr_t) pgs + n), PAGE_4KB); + } proc->regs.pc = PROC_ENTRY; } diff --git a/kern/proc.h b/kern/proc.h index f06a789..b3ca923 100644 --- a/kern/proc.h +++ b/kern/proc.h @@ -1,14 +1,13 @@ #pragma once #include <stdint.h> +#include <string.h> #include "vm.h" #define PROC_ENTRY 0x8000 #define NPROC 16 -typedef uint32_t pid_t; - typedef struct { uint32_t r0; uint32_t r1; @@ -36,8 +35,14 @@ typedef enum { typedef struct { regs_t regs; - pid_t id; + uint32_t id; pagetable_t* pt; + uint8_t* code; + size_t codesz; + proc_state_t state; } proc_t; + +void proc_new(proc_t* proc, uint8_t* code, size_t codesz); +void proc_run(proc_t* proc); diff --git a/kern/syscall.c b/kern/syscall.c index 21f1474..8d9e099 100644 --- a/kern/syscall.c +++ b/kern/syscall.c @@ -3,24 +3,7 @@ #include "kern.h" #include "syscall.h" #include "vm.h" - -typedef struct { - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t r12; - uint32_t r13; - uint32_t r14; -} user_regs_t; +#include "proc.h" unsigned syscall_alloc_page(uint32_t page_addr, uint32_t page_size) { assert(page_addr == SYSCALL_ARG_ANY_PAGE); @@ -42,7 +25,7 @@ unsigned syscall_vm_map(uint32_t va, return -1; } -void syscall(user_regs_t* regs) { +void syscall(regs_t* regs) { unsigned sysno = regs->r0; switch (sysno) { case SYSCALL_EXIT: @@ -6,14 +6,16 @@ pagetable_t* kalloc_pt() { pagetable_t* l1pt = (pagetable_t*) kmalloc(sizeof(pagetable_t)); + assert(l1pt); memset(l1pt, 0, sizeof(pagetable_t)); return l1pt; } static void init_second_level(pde_t* pde) { pte_small_t* pgtbl = kmalloc(256 * sizeof(pte_small_t)); + assert(pgtbl); memset(pgtbl, 0, 256 * sizeof(pte_small_t)); - pde->addr = (uintptr_t) pgtbl >> 10; + pde->addr = ka2pa((uintptr_t) pgtbl) >> 10; pde->tag = 0b01; } @@ -21,6 +23,9 @@ void vm_map(pagetable_t* pt, uintptr_t va, uintptr_t pa, pg_typ_t typ) { unsigned idx = va >> 20; l1pte_t* l1pte = &pt->entries[idx]; + // TODO: allow remapping + assert(l1pte->pde.tag == 0); + switch (typ) { case PAGE_UNMAPPED: l1pte->pde.tag = 0b00; @@ -33,7 +38,7 @@ void vm_map(pagetable_t* pt, uintptr_t va, uintptr_t pa, pg_typ_t typ) { if (l1pte->pde.tag == 0b00) { init_second_level(&l1pte->pde); } - pte_small_t* l2pt = (pte_small_t*) (l1pte->pde.addr << 10); + pte_small_t* l2pt = (pte_small_t*) pa2ka((uintptr_t) l1pte->pde.addr << 10); pte_small_t* l2pte = &l2pt[bits_get(va, 12, 19)]; l2pte->addr = pa >> 12; l2pte->ap = AP_NO_ACCESS; @@ -49,5 +54,7 @@ void vm_unmap(pagetable_t* pt, uintptr_t va) { } void vm_set_pt(pagetable_t* pt) { - sys_set_tlb_base((uintptr_t) pt); + sys_set_tlb_base(ka2pa((uintptr_t) pt)); + sys_invalidate_tlb(); + sys_clean_and_invalidate_cache(); } @@ -2,8 +2,8 @@ #include <stdint.h> -#define pa2ka(pa) ((pa | (1UL << 31))) -#define ka2pa(ka) ((ka & ~(1UL << 31))) +#define pa2ka(pa) (((pa) | (1UL << 31))) +#define ka2pa(ka) (((ka) & ~(1UL << 31))) typedef struct { unsigned tag : 2; @@ -92,6 +92,11 @@ enum { DOM_MANAGER = 0b11, // TLB access bits are ignored }; +#define SIZE_4KB (1 << 12) +#define SIZE_16KB (1 << 14) +#define SIZE_1MB (1 << 20) +#define SIZE_16MB (1 << 24) + typedef enum { PAGE_UNMAPPED, PAGE_4KB, diff --git a/prog/basic/Makefile b/prog/basic/Makefile new file mode 100644 index 0000000..f87fcbd --- /dev/null +++ b/prog/basic/Makefile @@ -0,0 +1,14 @@ +include ../../defs.mk + +PROG = basic +MEMMAP = $(PROG).ld + +$(PROG).elf: $(MEMMAP) $(PROG).o + $(LD) $(LDFLAGS) $(filter-out $<,$^) $(LDLIBS) -o $@ + +$(PIOS)/kern/p-$(PROG).c: $(PROG).bin + $(PIOS)/tools/exify/exify.sh $< > $@ $(PROG) + +exostall: $(PIOS)/kern/p-$(PROG).c + +.PHONY: exostall diff --git a/prog/basic/basic.ld b/prog/basic/basic.ld new file mode 100644 index 0000000..9762c82 --- /dev/null +++ b/prog/basic/basic.ld @@ -0,0 +1,20 @@ +SECTIONS +{ + .text 0x8000 : { + KEEP(*(.text.boot)) + *(.text*) + . = ALIGN(8); + } + .rodata : { *(.rodata*) } + .data : { + *(.data*) + . = ALIGN(4); + } + .bss : { + . = ALIGN(4); + *(.bss*) + *(COMMON) + . = ALIGN(8); + . = ALIGN(8); + } +} diff --git a/prog/basic/basic.s b/prog/basic/basic.s new file mode 100644 index 0000000..513b22e --- /dev/null +++ b/prog/basic/basic.s @@ -0,0 +1,6 @@ +.section ".text.boot" + +.globl start +_start: + mov r0, #0 + swi 0 @@ -6,3 +6,7 @@ riscv/portable gpu https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-4/ + +exo: +- asan +- user mode diff --git a/tools/exify/exify.sh b/tools/exify/exify.sh index ee8b204..830abab 100755 --- a/tools/exify/exify.sh +++ b/tools/exify/exify.sh @@ -1,5 +1,7 @@ #!/bin/bash -echo "uint8_t prog[] = {" -hexdump -e '"\t" 8/1 "0x%02x, " "\n"' hello.bin +echo "#include <string.h>" +echo "unsigned char prog_$2[] = {" +hexdump -e '"\t" 8/1 "0x%02x, " "\n"' $1 echo "};" +echo "size_t prog_$2_sz = sizeof(prog_$2);" |