diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-06-11 23:35:33 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-06-11 23:35:33 +0300 |
| commit | 62ee0f7e1936a9eccb55fa360a1dce223819e0b8 (patch) | |
| tree | 2c67698cac4e94cd7643f7acf19f1ada12f37472 /common/pmem.c | |
| parent | 56fb0b774a8e89be1cb7ab1e5f464bbedd19fb22 (diff) | |
| download | kmi-62ee0f7e1936a9eccb55fa360a1dce223819e0b8.tar.gz kmi-62ee0f7e1936a9eccb55fa360a1dce223819e0b8.zip | |
continue documentation
Diffstat (limited to 'common/pmem.c')
| -rw-r--r-- | common/pmem.c | 175 |
1 files changed, 165 insertions, 10 deletions
diff --git a/common/pmem.c b/common/pmem.c index dae26ea..fdde12a 100644 --- a/common/pmem.c +++ b/common/pmem.c @@ -33,53 +33,122 @@ #include <apos/bits.h> /* is_nset etc */ #include <libfdt.h> -/* NOTE: these are all for pnum_t, i.e. O0_SHIFT is from 0 */ +/** + * Loop through all page usage bits in current bitmap. + * + * @param var Memory leaf or branch containing bitmap. + * @param start Start looking from this index. + * @param end Stop looking before this index. + * @param attr Attribute name of bitmap. + * @param neg Negate whether we're looking for full or empty pages. + * + * \note These are all for pnum_t, i.e. O0_SHIFT is from 0 + */ #define __foreach_page(var, start, end, attr, neg) \ for (pnum_t page = start; page < end; ++page) \ if (neg (bitmap_is_set(var->attr, page))) continue; \ else \ +/** Easier to read negation. */ #define NEG ! -#define foreach_full_page(var, start, order) \ + +/** + * Loop through all full pages. + * + * @param var Memory leaf or branch containing bitmap. + * @param start Start looking from this index. + */ +#define foreach_full_page(var, start) \ __foreach_page(var, start, var->entries, full, NEG) -#define foreach_not_full_page(var, start, order) \ +/** + * Loop through all not full pages. + * + * @param var Memory leaf or branch containing bitmap. + * @param start Start looking from this index. + */ +#define foreach_not_full_page(var, start) \ __foreach_page(var, start, var->entries, full, ) -#define foreach_used_page(var, start, order) \ +/** + * Loop through all used pages. + * + * @param var Memory leaf or branch containing bitmap. + * @param start Start looking from this index. + */ +#define foreach_used_page(var, start) \ __foreach_page(var, start, var->entries, used, NEG) -#define foreach_not_used_page(var, start, order) \ +/** + * Loop through all not used pages. + * + * @param var Memory leaf or branch containing bitmap. + * @param start Start looking from this index. + */ +#define foreach_not_used_page(var, start) \ __foreach_page(var, start, var->entries, used, ) /* curiously, all my optimisation efforts were in vain, and eight bits is the * best alternative. */ + +/** Memory bitmap base size. */ typedef uint8_t mm_info_t; + +/** Beauty typedef for void *, used for bitmaps in this file. */ typedef void mm_node_t; +/** Memory page leaf. */ struct mm_leaf { + /** Number of entries in leaf. */ pnum_t entries; + + /** Bitmap of used pages. */ mm_info_t *used; }; +/** Memory page branch. */ struct mm_branch { + /** Number of entries in branch. */ pnum_t entries; + + /** Bitmap of full nodes. */ mm_info_t *full; + + /** Pointer to array of next order indexes. */ mm_node_t **next; }; +/** Order map. */ struct mm_omap { + /** Base address of map. */ pm_t base; + + /** Pointer to array of nodes. */ mm_node_t **orders; + + /** Order of map. */ enum mm_order order; }; +/** Physical map. */ struct mm_pmap { - struct mm_omap *omap[9]; + /** Order map, one per order up to maximum order. */ + struct mm_omap *omap[NUM_ORDERS]; }; +/** Static physical map address. \note If I support NUMA, this should not be + * static, rather one physical map per NUMA region. */ static struct mm_pmap *pmap = 0; +/** + * Helper function for marking a page used. + * + * @param op Order node pointer. + * @param pnum Physical page number to mark free. + * @param tgt Target order. + * @param src Source order. + * @param dst Destination order. + */ static void __mark_free(mm_node_t *op, pnum_t pnum, enum mm_order tgt, enum mm_order src, enum mm_order dst) { @@ -99,9 +168,9 @@ static void __mark_free(mm_node_t *op, pnum_t pnum, enum mm_order tgt, bitmap_clear(o->full, idx); } -/* this could probably use an int for status, but eh */ void free_page(enum mm_order order, pm_t paddr) { + /** \todo This could probably use an int for status, but eh */ for (size_t i = MM_O0; i <= __mm_max_order; ++i) { if (!pmap->omap[i]) continue; @@ -119,6 +188,16 @@ void free_page(enum mm_order order, pm_t paddr) } } +/** + * Helper function for marking a page used. + * + * @param op Order node pointer. + * @param pnum Page number to mark used. + * @param tgt Target order. + * @param src Source order. + * @param dst Destination order. + * @return \ref true if order is filled, \ref false otherwise. + */ static bool __mark_used(mm_node_t *op, pnum_t pnum, enum mm_order tgt, enum mm_order src, enum mm_order dst) { @@ -173,6 +252,15 @@ void mark_used(enum mm_order order, pm_t paddr) } } +/** + * Look for next free page. + * + * @param op Operand node pointer. + * @param offset Offset to where to start looking for available pages from. + * @param src Source order. + * @param dst Destination order. + * @return Page number of found index. + */ static pnum_t __enum_order(mm_node_t *op, pnum_t offset, enum mm_order src, enum mm_order dst) { @@ -180,7 +268,7 @@ static pnum_t __enum_order(mm_node_t *op, pnum_t offset, enum mm_order src, if (src == dst) { struct mm_leaf *o = (struct mm_leaf *)op; - foreach_not_used_page(o, idx, src) + foreach_not_used_page(o, idx) { return page << order_offset(src); } @@ -189,7 +277,7 @@ static pnum_t __enum_order(mm_node_t *op, pnum_t offset, enum mm_order src, } struct mm_branch *o = (struct mm_branch *)op; - foreach_not_full_page(o, idx, src) + foreach_not_full_page(o, idx) { /* if the suggested search index is full, the following level * would get an incorrect offset if trying to follow the original @@ -237,10 +325,20 @@ pm_t alloc_page(enum mm_order order, pm_t offset) return paddr; } -/* unfortunate that populating the mm info is so complicated */ +/** + * Populate order node map. + * + * @param op Address to where to write order node pointer. + * @param cont Physical address where to continue writing data to. + * @param src Source order. + * @param dst Destination order. + * @param num Number of nodes in this order to populate. + * @return Physical address to continue from. + */ static pm_t __populate_order(mm_node_t **op, pm_t cont, enum mm_order src, enum mm_order dst, size_t num) { + /* unfortunate that populating the mm info is so complicated */ if (src == dst) { struct mm_leaf *o = (struct mm_leaf *)move_forward( cont, sizeof(struct mm_leaf)); @@ -272,6 +370,15 @@ static pm_t __populate_order(mm_node_t **op, pm_t cont, enum mm_order src, return cont; } +/** + * Probe order node map. + * + * @param cont Number of bytes written so far. + * @param src Source order. + * @param dst Destination order. + * @param num Number of nodes in this order to calculate. + * @return Number of bytes written so far. + */ static pm_t __probe_order(pm_t cont, enum mm_order src, enum mm_order dst, size_t num) { @@ -292,6 +399,15 @@ static pm_t __probe_order(pm_t cont, enum mm_order src, enum mm_order dst, return cont; } +/** Populate order map. + * + * @param omap Address where to write order map pointer. + * @param cont Address where to continue writing map data. + * @param base Base of order map. + * @param entries Number of order node entries in order map. + * @param order Order of this order map. + * @return Address to continue writing data to. + */ static pm_t __populate_omap(struct mm_omap **omap, pm_t cont, pm_t base, size_t entries, enum mm_order order) { @@ -314,6 +430,14 @@ static pm_t __populate_omap(struct mm_omap **omap, pm_t cont, pm_t base, return cont; } +/** + * Probe order map. + * + * @param cont Number of bytes written so far. + * @param entries Number of order node entries in this order map. + * @param order Order of this order map. + * @return Number of bytes written so far. + */ static pm_t __probe_omap(pm_t cont, size_t entries, enum mm_order order) { cont += sizeof(struct mm_omap); @@ -375,6 +499,12 @@ pm_t probe_pmap(pm_t ram_base, size_t ram_size) return cont; } +/** + * Helper function for marking area used. + * + * @param base Base address of area. + * @param top Top address of top. + */ static void __mark_area_used(pm_t base, pm_t top) { size_t area_left = top - base; @@ -389,6 +519,11 @@ static void __mark_area_used(pm_t base, pm_t top) mark_used(BASE_PAGE, runner); } +/** + * Mark reserved memory region used, to avoid it getting accidentally allocated. + * + * @param fdt Global FDT pointer. + */ static void __mark_reserved_mem(void *fdt) { int rmem_offset = fdt_path_offset(fdt, "/reserved-memory/mmode_resv0"); @@ -407,6 +542,12 @@ static void __mark_reserved_mem(void *fdt) __mark_area_used((pm_t)__va(base), (pm_t)__va(top)); } +/** + * Read top of RAM from FDT. + * + * @param fdt Global FDT pointer. + * @return Physical address of top of RAM. + */ static pm_t __get_ramtop(void *fdt) { struct cell_info ci = get_reginfo(fdt, "/memory"); @@ -423,12 +564,26 @@ static pm_t __get_ramtop(void *fdt) return (pm_t)fdt_load_int_ptr(ci.size_cells, mem_reg) + base; } +/** + * Read top of FDT. + * + * @param fdt Global FDT pointer. + * @return Physical address of top of FDT. + */ static pm_t __get_fdttop(void *fdt) { const char *b = (const char *)fdt; return (pm_t)(b + fdt_totalsize(fdt)); } +/** + * Return base of FDT. + * + * Technically pretty useless, but here mainly for cohesion. + * + * @param fdt Global FDT pointer. + * @return \c fdt. + */ static pm_t __get_fdtbase(void *fdt) { /* lol */ |
