aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/config.h2
-rw-r--r--arch/riscv/include/pages.h5
-rw-r--r--arch/riscv/init/init.c73
-rw-r--r--common/pmem.c97
-rw-r--r--common/string.c2
-rw-r--r--include/apos/pmem.h3
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)