diff options
| -rw-r--r-- | arch/riscv/config.h | 2 | ||||
| -rw-r--r-- | arch/riscv/include/pages.h | 5 | ||||
| -rw-r--r-- | arch/riscv/init/init.c | 73 | ||||
| -rw-r--r-- | common/pmem.c | 97 | ||||
| -rw-r--r-- | common/string.c | 2 | ||||
| -rw-r--r-- | include/apos/pmem.h | 3 |
6 files changed, 159 insertions, 23 deletions
diff --git a/arch/riscv/config.h b/arch/riscv/config.h index 8bfe360..9db8d8f 100644 --- a/arch/riscv/config.h +++ b/arch/riscv/config.h @@ -1,6 +1,6 @@ #include <apos/sizes.h> #define PM_KERN 0x83800000 -#define PM_STACK_BASE 0x83900000 +#define PM_STACK_BASE (PM_KERN + SZ_2M) #define PM_STACK_TOP (PM_STACK_BASE + SZ_2M - 2) #define VM_KERN ((-1) - SZ_1G) diff --git a/arch/riscv/include/pages.h b/arch/riscv/include/pages.h index 1533f7b..82ce6c7 100644 --- a/arch/riscv/include/pages.h +++ b/arch/riscv/include/pages.h @@ -12,4 +12,9 @@ typedef uint64_t pm_t; #define MM_GPAGE MM_O2 #define MM_TPAGE MM_O3 +#define MM_KPAGE_SIZE SZ_4K +#define MM_MPAGE_SIZE SZ_2M +#define MM_GPAGE_SIZE SZ_1G +#define MM_TPAGE_SIZE SZ_512G + #endif /* APOS_RISCV_PAGES_H */ diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c index 86c2563..ca04bcd 100644 --- a/arch/riscv/init/init.c +++ b/arch/riscv/init/init.c @@ -127,12 +127,61 @@ static pm_t get_initrdtop(void *fdt) 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 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; + while(area_left >= MM_TPAGE_SIZE){ + mark_used(MM_TPAGE, base); + area_left -= MM_TPAGE_SIZE; + base += MM_TPAGE_SIZE; + } + + while(area_left >= MM_GPAGE_SIZE){ + mark_used(MM_GPAGE, base); + area_left -= MM_GPAGE_SIZE; + base += MM_GPAGE_SIZE; + } + + while(area_left >= MM_MPAGE_SIZE){ + mark_used(MM_MPAGE, base); + area_left -= MM_MPAGE_SIZE; + base += MM_MPAGE_SIZE; + } + + + 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 setup_pmem(void *fdt) { struct pmem_layout pmem = get_memlayout(fdt); @@ -148,14 +197,32 @@ static void setup_pmem(void *fdt) /* 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 */ - populate_pmap(pmem.base, pmem.top - pmem.base, align_up(top + 1, 2)); + pm_t pmap_base = align_up(top + 1, 2); + size_t actual_size = populate_pmap(pmem.base, pmem.top - pmem.base, + pmap_base); - /* TODO: mark used pages */ + /* 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 */ + /* 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); } void init(void *fdt) diff --git a/common/pmem.c b/common/pmem.c index 01429e5..ff19c95 100644 --- a/common/pmem.c +++ b/common/pmem.c @@ -2,8 +2,9 @@ #include <apos/string.h> /* memset */ #include <apos/bits.h> /* __is_nset etc */ +/* NOTE: these are all for pnum_t, i.e. O0_SHIFT is from 0 */ #if defined(O0_WIDTH) -#define MM_O0_SHIFT (O0_WIDTH) +#define MM_O0_SHIFT (0) #define MM_O0_WIDTH (1UL << (O0_WIDTH)) #define MM_O0_SIZE (1UL << MM_O0_SHIFT << PAGE_SHIFT) #else @@ -13,7 +14,7 @@ #endif #if defined(O1_WIDTH) -#define MM_O1_SHIFT (MM_O0_SHIFT + (O1_WIDTH)) +#define MM_O1_SHIFT (MM_O0_SHIFT + (O0_WIDTH)) #define MM_O1_WIDTH (1UL << (O1_WIDTH)) #define MM_O1_SIZE (1UL << MM_O1_SHIFT << PAGE_SHIFT) #else @@ -23,7 +24,7 @@ #endif #if defined(O2_WIDTH) -#define MM_O2_SHIFT (MM_O1_SHIFT + (O2_WIDTH)) +#define MM_O2_SHIFT (MM_O1_SHIFT + (O1_WIDTH)) #define MM_O2_WIDTH (1UL << (O2_WIDTH)) #define MM_O2_SIZE (1UL << MM_O2_SHIFT << PAGE_SHIFT) #else @@ -33,7 +34,7 @@ #endif #if defined(O3_WIDTH) -#define MM_O3_SHIFT (MM_O2_SHIFT + (O3_WIDTH)) +#define MM_O3_SHIFT (MM_O2_SHIFT + (O2_WIDTH)) #define MM_O3_WIDTH (1UL << (O3_WIDTH)) #define MM_O3_SIZE (1UL << MM_O3_SHIFT << PAGE_SHIFT) #else @@ -43,7 +44,7 @@ #endif #if defined(O4_WIDTH) -#define MM_O4_SHIFT (MM_O3_SHIFT + (O4_WIDTH)) +#define MM_O4_SHIFT (MM_O3_SHIFT + (O3_WIDTH)) #define MM_O4_SHIFT (1UL << (O4_WIDTH)) #define MM_O4_SIZE (1UL << MM_O4_SHIFT << PAGE_SHIFT) #else @@ -53,7 +54,7 @@ #endif #if defined(O5_WIDTH) -#define MM_O5_SHIFT (MM_O4_SHIFT + (O5_WIDTH)) +#define MM_O5_SHIFT (MM_O4_SHIFT + (O4_WIDTH)) #define MM_O5_WIDTH (1UL << (O5_WIDTH)) #define MM_O5_SIZE (1UL << MM_O5_SHIFT << PAGE_SHIFT) #else @@ -63,7 +64,7 @@ #endif #if defined(O6_WIDTH) -#define MM_O6_SHIFT (MM_O5_SHIFT + (O6_WIDTH)) +#define MM_O6_SHIFT (MM_O5_SHIFT + (O5_WIDTH)) #define MM_O6_WIDTH (1UL << (O6_WIDTH)) #define MM_O6_SIZE (1UL << MM_O6_SHIFT << PAGE_SHIFT) #else @@ -73,7 +74,7 @@ #endif #if defined(O7_WIDTH) -#define MM_O7_SHIFT (MM_O6_SHIFT + (O7_WIDTH)) +#define MM_O7_SHIFT (MM_O6_SHIFT + (O6_WIDTH)) #define MM_O7_WIDTH (1UL << (O7_WIDTH)) #define MM_O7_SIZE (1UL << MM_O7_SHIFT << PAGE_SHIFT) #else @@ -83,7 +84,7 @@ #endif #if defined(O8_WIDTH) -#define MM_O8_SHIFT (MM_O7_SHIFT + (O8_WIDTH)) +#define MM_O8_SHIFT (MM_O7_SHIFT + (O7_WIDTH)) #define MM_O8_WIDTH (1UL << (O8_WIDTH)) #define MM_O8_SIZE (1UL << MM_O8_SHIFT << PAGE_SHIFT) #else @@ -93,7 +94,7 @@ #endif #if defined(O9_WIDTH) -#define MM_O9_SHIFT (MM_O8_SHIFT + (O9_WIDTH)) +#define MM_O9_SHIFT (MM_O8_SHIFT + (O8_WIDTH)) #define MM_O9_WIDTH (1UL << (O9_WIDTH)) #define MM_O9_SIZE (1UL << MM_O9_SHIFT << PAGE_SHIFT) #else @@ -212,7 +213,7 @@ struct mm_pmap_t { static struct mm_pmap_t *pmap = 0; -static void __mark_free(mm_node_t * op, pnum_t pnum, +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) { size_t idx = pnum_to_index(pnum, src); @@ -224,14 +225,16 @@ static void __mark_free(mm_node_t * op, pnum_t pnum, } struct mm_branch_t *o = (struct mm_branch_t *)op; - __mark_free(o->next[idx], pnum, src - 1, dst); + if(src != tgt) + __mark_free(o->next[idx], pnum, tgt, src - 1, dst); + /* freeing a page results in always clearing a full bit? */ __clear_nbit(o->full[__o_container(idx)], __o_bit(idx)); } void free_page(enum mm_order_t order, paddr_t paddr) { - for (ssize_t i = MAX_ORDER; i >= order; --i) { + for (ssize_t i = MM_O0; i <= MAX_ORDER; ++i) { if (!pmap->omap[i]) continue; @@ -242,8 +245,9 @@ void free_page(enum mm_order_t order, paddr_t paddr) for (size_t j = 0; j < omap->order; ++j) __mark_free(omap->orders[j], paddr_to_pnum(paddr - omap->base), - omap->order, j); + order, omap->order, j); + return; } } @@ -284,7 +288,7 @@ static bool __mark_used(mm_node_t * op, pnum_t pnum, enum mm_order_t tgt, void mark_used(enum mm_order_t order, paddr_t paddr) { - for (ssize_t i = MAX_ORDER; i >= MM_O0; --i) { + for (ssize_t i = MM_O0; i <= MAX_ORDER; ++i) { if (!pmap->omap[i]) continue; @@ -445,12 +449,30 @@ static paddr_t __populate_order(mm_node_t ** op, paddr_t cont, return cont; } +static paddr_t __probe_order(paddr_t cont, enum mm_order_t src, enum mm_order_t dst, + size_t num) +{ + if(src == dst){ + cont += sizeof(struct mm_leaf_t); + cont += state_elems(num); + return cont; + } + + cont += sizeof(struct mm_branch_t); + cont += state_elems(num); + cont += next_elems(num); + + for(size_t i = 0; i < num; ++i) + cont = __probe_order(cont, src - 1, dst, __o_width(src - 1)); + + return cont; +} + static paddr_t __populate_omap(struct mm_omap_t **omap, paddr_t cont, paddr_t base, size_t entries, enum mm_order_t order) { struct mm_omap_t *lomap = (struct mm_omap_t *) move_forward(cont, sizeof(struct mm_omap_t)); - memset(lomap, 0, sizeof(struct mm_omap_t)); lomap->orders = (mm_node_t **) move_forward(cont, @@ -467,9 +489,22 @@ static paddr_t __populate_omap(struct mm_omap_t **omap, paddr_t cont, *omap = lomap; return cont; } + +static paddr_t __probe_omap(paddr_t cont, size_t entries, enum mm_order_t order) +{ + cont += sizeof(struct mm_omap_t); + cont += (order + 1) * sizeof(mm_node_t **); + + for(size_t i = 0; i <= order; ++i) + cont = __probe_order(cont, order, i, entries); + + return cont; +} + /* only call from init */ -void populate_pmap(paddr_t ram_base, size_t ram_size, paddr_t cont) +paddr_t populate_pmap(paddr_t ram_base, size_t ram_size, paddr_t cont) { + paddr_t start = cont; pmap = (struct mm_pmap_t *)move_forward(cont, sizeof(struct mm_pmap_t)); memset(pmap, 0, sizeof(struct mm_pmap_t)); @@ -486,6 +521,34 @@ void populate_pmap(paddr_t ram_base, size_t ram_size, paddr_t cont) ram_left -= mm_sizes[i] * entries; ram_region += (mm_sizes[i] * entries); } + + return cont - start; +} + +/* not a huge fan of having a separate probe_pmap function as that seems like an + * easy way to cause weird bugs. Should always at least check that probe_pmap + * returns the same value as populate_pmap, or possibly even add in some method + * to combine the two? */ +paddr_t probe_pmap(paddr_t ram_base, size_t ram_size) +{ + paddr_t cont = 0; + + cont += sizeof(struct mm_pmap_t); + + paddr_t ram_region = ram_base; + size_t ram_left = ram_size; + for(ssize_t i = MAX_ORDER; i >= MM_O0; --i){ + size_t entries = ram_left / mm_sizes[i]; + if(entries == 0) + continue; + + cont = __probe_omap(cont, entries, i); + + ram_left -= mm_sizes[i] * entries; + ram_region += (mm_sizes[i] * entries); + } + + return cont; } /* only call from kernel */ diff --git a/common/string.c b/common/string.c index 0870b78..810a703 100644 --- a/common/string.c +++ b/common/string.c @@ -251,7 +251,7 @@ __weak void *memset(void *ptr, int value, size_t num) char c = value; while (num--) - *(p--) = c; + *(p++) = c; return ptr; } diff --git a/include/apos/pmem.h b/include/apos/pmem.h index ec98cbf..826ae14 100644 --- a/include/apos/pmem.h +++ b/include/apos/pmem.h @@ -25,7 +25,8 @@ void mark_used(enum mm_order_t order, paddr_t paddr); paddr_t alloc_page(enum mm_order_t order, paddr_t offset); #if defined(INIT) -void populate_pmap(paddr_t ram_base, size_t ram_size, paddr_t cont); +paddr_t populate_pmap(paddr_t ram_base, size_t ram_size, paddr_t cont); +paddr_t probe_pmap(paddr_t ram_base, size_t ram_size); #endif #if defined(KERNEL) |
