aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-06-11 23:35:33 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-06-11 23:35:33 +0300
commit62ee0f7e1936a9eccb55fa360a1dce223819e0b8 (patch)
tree2c67698cac4e94cd7643f7acf19f1ada12f37472 /common
parent56fb0b774a8e89be1cb7ab1e5f464bbedd19fb22 (diff)
downloadkmi-62ee0f7e1936a9eccb55fa360a1dce223819e0b8.tar.gz
kmi-62ee0f7e1936a9eccb55fa360a1dce223819e0b8.zip
continue documentation
Diffstat (limited to 'common')
-rw-r--r--common/debug.c226
-rw-r--r--common/pmem.c175
-rw-r--r--common/proc.c2
3 files changed, 360 insertions, 43 deletions
diff --git a/common/debug.c b/common/debug.c
index 2bcdf7f..924c0dd 100644
--- a/common/debug.c
+++ b/common/debug.c
@@ -14,10 +14,18 @@
#include <stdarg.h>
#if defined(DEBUG)
-static struct dbg_info {
+
+/** Debug context structure. */
+struct dbg_info {
+ /** Address of serial device in memory. */
pm_t dbg_ptr;
+
+ /** Type of serial device. */
enum serial_dev dev;
-} dbg_info = (struct dbg_info){ 0 };
+};
+
+/** Static debugging information. */
+static struct dbg_info dbg_info = (struct dbg_info){ 0 };
/* forward declarations. */
static void __setup_dbg(pm_t pt, enum serial_dev dev);
@@ -43,43 +51,78 @@ void setup_io_dbg(struct vmem *b)
* try to implement some kind of basic driver subsystem, but this is good enough
* for now. */
+/** NS16550A and compatible serial drivers. */
struct __packed ns16550a {
- union {
- struct {
- uint8_t data;
- uint8_t irq;
- };
+ /** Receiver buffer/transmitter holding register. */
+ uint8_t data;
- struct {
- uint8_t lsbr;
- uint8_t msbr;
- };
- };
+ /** Interrupt enable register. */
+ uint8_t irq;
+ /** Interrupt identity/FIFO control register. */
uint8_t irq_id;
+
+ /** Line control register. */
uint8_t lcr;
+
+ /** Modem control register. */
uint8_t mcr;
+
+ /** Line status register. */
uint8_t lsr;
+
+ /** Modem status register. */
uint8_t msr;
+
+ /** Scratch register. */
uint8_t scr;
};
+/** Line status data ready. */
#define LSR_DR (1 << 0)
+
+/** Line status overrun error. */
#define LSR_OE (1 << 1)
+
+/** Line status parity error. */
#define LSR_PE (1 << 2)
+
+/** Line status framing error. */
#define LSR_FE (1 << 3)
+
+/** Line status break interrupt. */
#define LSR_BI (1 << 4)
+
+/** Line status transmitter holding register. */
#define LSR_THRE (1 << 5)
+
+/** Line status transmitter empty. */
#define LSR_TEMT (1 << 6)
+
+/** Line status error in RCVR FIFO. */
#define LSR_ERR (1 << 7)
+/**
+ * Address of ns16550a port. If other serial drivers are added, this should
+ * maybe be made a void *.
+ */
static struct ns16550a *port = 0;
+/**
+ * Serial transmitter empty.
+ *
+ * @return \c 0 if not empty, non-zero otherwise.
+ */
static int __serial_tx_empty()
{
return port->lsr & LSR_THRE;
}
+/**
+ * Put character out onto serial lines.
+ *
+ * @param c Character to output.
+ */
static void __putchar(char c)
{
if (!port)
@@ -91,6 +134,12 @@ static void __putchar(char c)
port->data = c;
}
+/**
+ * Convert serial device name (from FDT) to serial device enumerator.
+ *
+ * @param dev_name Device name string.
+ * @return Corresponding enumerator value.
+ */
static enum serial_dev __serial_dev_enum(const char *dev_name)
{
if (strncmp("ns16550", dev_name, 7) == 0)
@@ -99,6 +148,12 @@ static enum serial_dev __serial_dev_enum(const char *dev_name)
return -1;
}
+/**
+ * Get debugging info from FDT.
+ *
+ * @param fdt Global FDT pointer.
+ * @return Filled \ref dbg_info structure.
+ */
static struct dbg_info __dbg_from_fdt(const void *fdt)
{
int chosen_offset = fdt_path_offset(fdt, "/chosen");
@@ -122,6 +177,12 @@ static struct dbg_info __dbg_from_fdt(const void *fdt)
return (struct dbg_info){ dbg_ptr, dev };
}
+/**
+ * Set static port.
+ *
+ * @param pt Address of memory mapped serial device.
+ * @param dev Chosen device.
+ */
void __setup_dbg(vm_t pt, enum serial_dev dev)
{
switch (dev) {
@@ -134,29 +195,71 @@ void __setup_dbg(vm_t pt, enum serial_dev dev)
* defaults (set by U-boot) seem to work alright */
}
+/** Printf formatting left align flag. */
#define LEFT_FLAG (1 << 0)
+
+/** Printf formatting explicit sign flag. */
#define SIGN_FLAG (1 << 1)
+
+/** Printf formatting hash sign flag. */
#define HASH_FLAG (1 << 2)
+
+/** Printf formatting zero padding flag. */
#define ZERO_FLAG (1 << 3)
+
+/** Printf formatting ' flag. */
#define FMT_FLAG (1 << 4)
+
+/** Printf formatting space flag. */
#define SPACE_FLAG (1 << 5)
+
+/** Printf formatting long specifier flag. */
#define LONG_FLAG (1 << 6)
+
+/** Printf formatting long long specifier flag. */
#define LLONG_FLAG (1 << 7)
+
+/** Printf formatting short flag. */
#define SHORT_FLAG (1 << 8)
+
+/** Printf formatting char flag. */
#define CHAR_FLAG (1 << 9)
+
+/** Printf precision flag. */
#define PRECS_FLAG (1 << 11)
+
+/** Printf unsigned flag. */
#define UNSIGN_FLAG (1 << 12)
+
+/** Printf width flag. */
#define WIDTH_FLAG (1 << 13)
+
+/** Printf padding flag. */
#define PAD_FLAG (1 << 14)
+/** Printf continue flag. */
#define CONT 1
+
+/** Printf stop flag. */
#define STOP 0
+/**
+ * Check if character is ASCII decimal digit.
+ *
+ * @param c Character to check.
+ * @return \c true if character is ASCII decimal digit, \c false otherwise.
+ */
static bool __is_digit(char c)
{
return (c >= '0') && (c <= '9');
}
+/**
+ * Convert string to corresponding number (assuming int).
+ *
+ * @param s Number string.
+ * @return Corresponding number.
+ */
static int __atoi(const char *s)
{
unsigned int i = 0;
@@ -167,6 +270,25 @@ static int __atoi(const char *s)
return i;
}
+/**
+ * Calculate signed char from value using type interpretation.
+ *
+ * @param x Type to interpret value as.
+ * @param value Value to interpret.
+ * @param base Base to interpret value in.
+ */
+#define handle_type(x, value, base) \
+ c = (x)value % (x)base; \
+ value = (x)value / (x)base;
+/**
+ * Convert number to string length.
+ *
+ * @param value Number to print.
+ * @param base Base to print in.
+ * @param flags Flags to output.
+ * @param print Print number as well.
+ * @return Length of corresponding string.
+ */
static size_t __integral_val(ssize_t value, size_t base, size_t flags,
bool print)
{
@@ -174,22 +296,19 @@ static size_t __integral_val(ssize_t value, size_t base, size_t flags,
size_t ret = 0;
signed char c = 0;
-#define handle_type(x) \
- c = (x)value % (x)base; \
- value = (x)value / (x)base;
if (!is_set(flags, UNSIGN_FLAG)) {
/* signed values, only with i format */
if (is_set(flags, LLONG_FLAG)) {
- handle_type(signed long long);
+ handle_type(signed long long, value, base);
} else if (is_set(flags, LONG_FLAG)) {
- handle_type(signed long);
+ handle_type(signed long, value, base);
} else if (is_set(flags, SHORT_FLAG)) {
- handle_type(signed short);
+ handle_type(signed short, value, base);
} else if (is_set(flags, CHAR_FLAG)) {
- handle_type(signed char);
+ handle_type(signed char, value, base);
} else {
- handle_type(signed int);
+ handle_type(signed int, value, base);
}
/* convert negative results into actual characters */
@@ -198,20 +317,18 @@ static size_t __integral_val(ssize_t value, size_t base, size_t flags,
} else {
/* unsigned values, everything else */
if (is_set(flags, LLONG_FLAG)) {
- handle_type(unsigned long long);
+ handle_type(unsigned long long, value, base);
} else if (is_set(flags, LONG_FLAG)) {
- handle_type(unsigned long);
+ handle_type(unsigned long, value, base);
} else if (is_set(flags, SHORT_FLAG)) {
- handle_type(unsigned short);
+ handle_type(unsigned short, value, base);
} else if (is_set(flags, CHAR_FLAG)) {
- handle_type(unsigned char);
+ handle_type(unsigned char, value, base);
} else {
- handle_type(unsigned int);
+ handle_type(unsigned int, value, base);
}
}
-#undef handle_type
-
if (base == 16)
c += c > 9 ? 'a' - 10 : '0';
else
@@ -226,6 +343,12 @@ static size_t __integral_val(ssize_t value, size_t base, size_t flags,
return ret + 1;
}
+/**
+ * Print prefix corresponding to \c base.
+ *
+ * @param base Base to integer.
+ * @return Length of prefix as string.
+ */
static size_t __print_prefix(size_t base)
{
size_t i = 0;
@@ -252,6 +375,13 @@ static size_t __print_prefix(size_t base)
return i;
}
+/**
+ * Print padding.
+ *
+ * @param pad Number of characters to print.
+ * @param pad_char Character to use as padding.
+ * @return Number of characters printed.
+ */
static size_t __print_padding(size_t pad, char pad_char)
{
size_t i = 0;
@@ -262,6 +392,13 @@ static size_t __print_padding(size_t pad, char pad_char)
return i;
}
+/**
+ * Print signed value.
+ *
+ * @param value Value to print.
+ * @param flags Flags to printing.
+ * @return Number of characters written.
+ */
static size_t __print_sign(ssize_t value, size_t flags)
{
if (is_set(flags, LLONG_FLAG))
@@ -286,12 +423,38 @@ static size_t __print_sign(ssize_t value, size_t flags)
return 0;
}
+/**
+ * Length of integral value as string.
+ *
+ * @param value Value to convert to string.
+ * @param base Base to interpret value as.
+ * @param flags Formatting flags.
+ * @return \see __integral_val().
+ */
+#define __integral_len(value, base, flags) __integral_val((value), (base), (flags), false)
+
+/**
+ * Print integral value as string.
+ *
+ * @param value Value to convert to string.
+ * @param base Base to interpret value as.
+ * @param flags Formatting flags.
+ * @return \see __integral_val().
+ */
+#define __integral_print(value, base, flags) __integral_val((value), (base), (flags), true)
+
+/**
+ * Print integral value.
+ *
+ * @param value Value to print.
+ * @param base Base to print value in.
+ * @param flags Flags to printing.
+ * @param width Minimum width of printing.
+ * @return Number of characters written.
+ */
static size_t __print_integral(ssize_t value, size_t base, size_t flags,
size_t width)
{
-#define __integral_len(a, b, c) __integral_val((a), (b), (c), false)
-#define __integral_print(a, b, c) __integral_val((a), (b), (c), true)
-
size_t ret = 0;
size_t raw_len = __integral_len(value, base, flags);
ssize_t pad = is_set(flags, PAD_FLAG) ? width - raw_len : 0;
@@ -338,9 +501,6 @@ static size_t __print_integral(ssize_t value, size_t base, size_t flags,
}
return ret;
-
-#undef __integral_len
-#undef __integral_print
}
void dbg(const char *fmt, ...)
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 */
diff --git a/common/proc.c b/common/proc.c
index 001e127..6de22c1 100644
--- a/common/proc.c
+++ b/common/proc.c
@@ -10,6 +10,7 @@
#include <apos/initrd.h>
#include <arch/arch.h>
#include <arch/proc.h>
+#include <arch/cpu.h>
stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp)
{
@@ -33,6 +34,7 @@ stat_t init_proc(void *fdt)
return ERR_OOMEM;
/* set current tcb */
+ cpu_assign(t);
use_tcb(t);
use_vmem(t->proc.vmem);