aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv64/config.h53
-rw-r--r--arch/riscv64/gen/asm-offsets.c26
-rw-r--r--arch/riscv64/include/tcb.h8
-rw-r--r--arch/riscv64/init/init.c29
-rw-r--r--arch/riscv64/init/start.S1
-rw-r--r--arch/riscv64/kernel/irq.c12
-rw-r--r--common/tcb.c10
-rw-r--r--docs/boot.md11
-rw-r--r--docs/doxygen.conf4
-rw-r--r--include/apos/assert.h30
-rw-r--r--include/apos/atomic.h367
-rw-r--r--include/arch/cpu.h8
-rw-r--r--include/arch/irq.h12
-rw-r--r--include/arch/pmem.h41
-rw-r--r--uncrustify.conf3
15 files changed, 576 insertions, 39 deletions
diff --git a/arch/riscv64/config.h b/arch/riscv64/config.h
index 33c84a0..bdf31ae 100644
--- a/arch/riscv64/config.h
+++ b/arch/riscv64/config.h
@@ -7,44 +7,74 @@
* and immutable parameters. Included on the command line by
* -include.
*
+ * Assume Sv39, probably wouldn't be too difficult to use runtime parameters
+ * instead. First 4K is reserved for NULL, but I suppose it could be mapped
+ * later if *absolutely* necessary.
+ *
* @todo Consider separating user-specified and immutable parameters.
+ * @todo Write more thorough documentation, maybe a separate .md file?
*/
#include <apos/sizes.h>
/* --- START ARCH USER CONFIG VALUES --- */
-/* physical address to which the kernel will be loaded */
+/** Physical address to where the OS image will be loaded. */
#define RAM_BASE 0x80000000
+/* --- END ARCH USER CONFIG VALUES --- */
+
+/* don't touch >:( */
+
+/** Physical address to where the kernel proper will be relocated. */
#define PM_KERN_BASE (RAM_BASE + SZ_512K)
+
+/** Maximum size of the kernel proper. Largely arbitrary. */
#define PM_KERN_SIZE (SZ_256K)
+
+/** Highest allowed physical address where kernel stuff may lie. */
#define PM_KERN_TOP (PM_KERN_BASE + PM_KERN_SIZE)
-/* --- END ARCH USER CONFIG VALUES --- */
-/* don't touch >:( */
+/** Physical memory stack base. In this case, right after the kernel. */
+#define PM_STACK_BASE (PM_KERN_BASE + PM_KERN_SIZE)
-#define PM_STACK_BASE (PM_KERN_BASE + SZ_256K)
+/** Size of physical memory stack. */
#define PM_STACK_SIZE (SZ_256K)
+
+/** Top of physical memory stack. */
#define PM_STACK_TOP (PM_STACK_BASE + PM_STACK_SIZE)
-#if __riscv_xlen == 64
+#if defined(riscv64)
/* 64bit */
+
+/** Direct map offset. */
#define VM_DMAP (0xffffffc000000000) /* testing for now */
+
+/** Virtual address of kernel proper inside direct mapping. */
#define VM_KERN (VM_DMAP + SZ_256K)
+/** Page reserved for kernel I/O. */
#define IO_PAGE 511UL
+
+/** Direct mapping starts from this page. */
#define KSTART_PAGE 256UL
+
+/** The RPC stack page. */
#define CSTACK_PAGE 255UL
-/* assume Sv39, probably wouldn't be too difficult to use runtime parameters
- * instead. First 4K is reserved for NULL, but I suppose it could be mapped
- * later if *absolutely* necessary. */
+/** User virtual memory space start. */
#define UVMEM_START (SZ_4K)
+
+/** User virtual memory space end. */
#define UVMEM_END (SZ_256G - SZ_1G)
-#define PROC_STACK_TOP (SZ_256G)
-#define PROC_STACK_BASE (SZ_256G - SZ_1G)
+/** RPC stack top. */
+#define RPC_STACK_TOP (SZ_256G)
+
+/** RPC stack base. */
+#define RPC_STACK_BASE (SZ_256G - SZ_1G)
+
#else
/* 32bit */
+
/* TODO: figure this stuff out */
#define VM_DMAP (0x000000000)
#define VM_KERN (VM_DMAP + SZ_256K)
@@ -55,9 +85,6 @@
#define KSTART_PAGE 512UL
#define CSTACK_PAGE 511UL
-/* assume Sv39, probably wouldn't be too difficult to use runtime parameters
- * instead. First 4K is reserved for NULL, but I suppose it could be mapped
- * later if *absolutely* necessary. */
#define UVMEM_START (SZ_4K)
#define UVMEM_END (SZ_4G - SZ_8M)
diff --git a/arch/riscv64/gen/asm-offsets.c b/arch/riscv64/gen/asm-offsets.c
index fbe2726..71a1c9a 100644
--- a/arch/riscv64/gen/asm-offsets.c
+++ b/arch/riscv64/gen/asm-offsets.c
@@ -7,12 +7,36 @@
#include <apos/utils.h>
#include "../kernel/regs.h"
-/* largely based on linux */
+/**
+ * Insert assembly comment with calculated value.
+ * Largely based on linux
+ *
+ * @param sym Name of symbol.
+ * @param val Value of symbol.
+ */
#define DEFINE(sym, val) \
__asm__ volatile ("\n#-> " #sym " %0 " #val "\n" : : "i" (val))
+
+/**
+ * Insert offset of member in structure.
+ *
+ * @param m Member.
+ * @param s Structure.
+ */
#define OFFSETOF(m, s) DEFINE(offsetof_##m, offsetof(s, m))
+
+/**
+ * Insert size of structure.
+ *
+ * @param n Name of structure.
+ * @param s Structure.
+ */
#define SIZEOF(n, s) DEFINE(sizeof_##n, sizeof(s))
+/**
+ * Generate assembly with calculated offsets and sizes.
+ * See arch/riscv64/gen/source.mk for how the assembly is used.
+ */
void asm_offsets()
{
OFFSETOF(ra, struct riscv_regs);
diff --git a/arch/riscv64/include/tcb.h b/arch/riscv64/include/tcb.h
index be6d58a..8cd32ed 100644
--- a/arch/riscv64/include/tcb.h
+++ b/arch/riscv64/include/tcb.h
@@ -6,9 +6,13 @@
* riscv64 definitions of arch-specific tcb data.
*/
+/**
+ * riscv-specific thread handling stuff.
+ *
+ * Empty for now, but should probably be filled with stuff like register
+ * saving of something
+ */
struct arch_tcbd {
- /* empty for now, but should probably be filled with stuff like register
- * saving of something */
};
#endif /* ARCH_RISCV_TCB_H */
diff --git a/arch/riscv64/init/init.c b/arch/riscv64/init/init.c
index 5fe463a..db428dd 100644
--- a/arch/riscv64/init/init.c
+++ b/arch/riscv64/init/init.c
@@ -11,13 +11,22 @@
#include <arch/vmem.h>
#include "../kernel/csr.h"
-/* assume 64 bit for now */
+/** Temporary virtual memory space.
+ * Assume 64bit riscv for now.
+ */
struct vmem *root_branch;
+/**
+ * Create page table entry.
+ * Copy from \ref arch/riscv64/kernel/vmem.c.
+ *
+ * @param a Virtual address.
+ * @param f PTE flags.
+ */
#define to_pte(a, f) (((a) >> 12) << 10 | (f))
-/* assume Sv39 for now */
-void init_bootmem()
+/** Jump into virtual memory. */
+static void init_bootmem()
{
size_t flags = VM_V | VM_X | VM_R | VM_W;
@@ -41,7 +50,8 @@ void init_bootmem()
csr_write(CSR_SATP, SATP_MODE_Sv39 | ((uintptr_t)root_branch >> 12));
}
-void move_kernel()
+/** Relocate kernel proper. */
+static void move_kernel()
{
extern char *__init_end;
extern char *__kernel_size;
@@ -53,6 +63,12 @@ void move_kernel()
dst[i] = src[i];
}
+/**
+ * Convert an existing physical address in a register to a virtual address.
+ * There is probably an easier way to do this, but this seems to work alright.
+ *
+ * @param reg Register to modify.
+ */
#define __va_reg(reg) \
{ \
vm_t reg = 0; \
@@ -61,6 +77,11 @@ void move_kernel()
__asm__ ("mv " QUOTE(reg) ", %0" ::"rK" (reg) :); \
}
+/**
+ * Main driver for the init loader.
+ *
+ * @param fdt Global FDT pointer, provided by bootloader.
+ */
void init(void *fdt)
{
extern char *__init_end;
diff --git a/arch/riscv64/init/start.S b/arch/riscv64/init/start.S
index 7842946..f5ed2fe 100644
--- a/arch/riscv64/init/start.S
+++ b/arch/riscv64/init/start.S
@@ -1,5 +1,6 @@
.section .init.start
.global _start
+/* Entry point to the kernel loader. */
_start:
li sp, PM_STACK_TOP
call init
diff --git a/arch/riscv64/kernel/irq.c b/arch/riscv64/kernel/irq.c
index 15fa750..6fdfe85 100644
--- a/arch/riscv64/kernel/irq.c
+++ b/arch/riscv64/kernel/irq.c
@@ -8,7 +8,13 @@
#include <arch/irq.h>
#include "csr.h"
-extern void handle_irq(void);
+/** Defined in arch/riscv64/kernel/entry.S. */
+extern void handle_irq();
+
+/** Called from arch/riscv64/kernel/entry.S. */
+void handle_sys_irq()
+{
+}
void init_irq(void *fdt)
{
@@ -20,10 +26,6 @@ void init_irq(void *fdt)
info("CSR_SIE: %lx\n", s);
}
-void handle_sys_irq()
-{
-}
-
/* very simple for now */
void enable_irq()
{
diff --git a/common/tcb.c b/common/tcb.c
index 84218dc..1382f67 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -56,7 +56,7 @@ static id_t __alloc_tid(struct tcb *t)
}
/* TODO: add error checking */
-static vm_t __setup_call_stack(struct tcb *t, size_t bytes)
+static vm_t __setup_rpc_stack(struct tcb *t, size_t bytes)
{
pm_t offset = 0;
size_t pages = __pages(bytes);
@@ -64,11 +64,11 @@ static vm_t __setup_call_stack(struct tcb *t, size_t bytes)
for (size_t i = 1; i <= pages; ++i) {
offset = alloc_page(BASE_PAGE, offset);
map_vpage(t->proc.vmem, offset,
- PROC_STACK_TOP - BASE_PAGE_SIZE * i,
+ RPC_STACK_TOP - BASE_PAGE_SIZE * i,
flags, BASE_PAGE);
}
- return PROC_STACK_TOP - BASE_PAGE_SIZE * pages;
+ return RPC_STACK_TOP - BASE_PAGE_SIZE * pages;
}
static vm_t __setup_thread_stack(struct tcb *t, size_t bytes)
@@ -85,9 +85,9 @@ stat_t alloc_stacks(struct tcb *t)
if (!t->thread_stack)
return ERR_OOMEM;
- /* call stack always starts at the same place in vmem.
+ /* rpc stack always starts at the same place in vmem.
* TODO: is this a security issue? */
- if (!__setup_call_stack(p, __call_stack_size))
+ if (!__setup_rpc_stack(p, __call_stack_size))
return ERR_OOMEM;
/* TODO: this only allows for a global stack size, what if a user wants
diff --git a/docs/boot.md b/docs/boot.md
new file mode 100644
index 0000000..2131d93
--- /dev/null
+++ b/docs/boot.md
@@ -0,0 +1,11 @@
+I need to figure out how to write MarkDown files, but the general procedure of a
+boot is that we
+
+1) Assume we start of in real memory mode, i.e. no MMU active.
+
+2) arch/whatever/init/init.c kickstarts us into virtual memory with a direct
+mapping, with offset VM_DMAP aliasing to physical address 0.
+
+3) The kernel proper is moved to its correct location in this direct mapping.
+
+4) The kernel proper is jumped to, after which the kernel does whatever.
diff --git a/docs/doxygen.conf b/docs/doxygen.conf
index d113ff4..32f764f 100644
--- a/docs/doxygen.conf
+++ b/docs/doxygen.conf
@@ -2214,7 +2214,7 @@ ENABLE_PREPROCESSING = YES
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
@@ -2254,7 +2254,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED = DEBUG
+PREDEFINED = DEBUG __GNUC__ riscv64 riscv32
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
diff --git a/include/apos/assert.h b/include/apos/assert.h
index 3255481..97523c7 100644
--- a/include/apos/assert.h
+++ b/include/apos/assert.h
@@ -20,6 +20,12 @@
/* TODO: should this exit or do something explosive like that? */
#if !defined(DNDEBUG)
+
+/**
+ * The kernel is in an irrepairable state, just give up.
+ *
+ * @param x Condition to check for.
+ */
#define catastrophic_assert(x) \
do { \
if (unlikely(!(x))) { \
@@ -29,6 +35,15 @@
} \
} while (0);
+/**
+ * The function cannot continue without this assertion, but doesn't necessarily
+ * mean that the kernel is borked.
+ *
+ * @warning Implicit return.
+ *
+ * @param x Condition to check for.
+ * @param r Return value on failed check.
+ */
#define hard_assert(x, r) \
{ \
if (unlikely(!(x))) { \
@@ -37,6 +52,11 @@
} \
}
+/**
+ * Unexpected case, but not likely to cause problems, likely a bug.
+ *
+ * @param x Condition to check for.
+ */
#define soft_assert(x) \
do { \
if (unlikely(!(x))) { \
@@ -49,8 +69,14 @@
#define soft_assert(x)
#endif
-/* use when return value doesn't exist, like hard_assert(x,
- * RETURN_VOID); */
+/**
+ * Use when return value doesn't exist.
+ *
+ * Example:
+ * @code{.c}
+ * void func() { hard_assert(x, RETURN_VOID); }
+ * @endcode
+ */
#define RETURN_VOID
#endif /* APOS_ASSERT_H */
diff --git a/include/apos/atomic.h b/include/apos/atomic.h
index a4292d6..d8d5368 100644
--- a/include/apos/atomic.h
+++ b/include/apos/atomic.h
@@ -4,80 +4,218 @@
/**
* @file atomic.h
* Atomics, closely modeled after C17 stdatomic.h. Largely dependent on the
- * compiler at the moment.
+ * compiler at the moment, if I run into an architecture that required the OS'
+ * help to implement these I'll have to look into how to do that, but for now
+ * this is probably good enough.
*/
#include <apos/utils.h> /* GLUE */
+/**
+ * Memory ordering modes.
+ *
+ * @remark Look up details somewhere elsewhere, as I'm not an expert on memory ordering.
+ * Would like to be, though.
+ */
typedef enum {
+ /** Relaxed memory ordering. */
memory_order_relaxed = __ATOMIC_RELAXED,
+ /** Consume memory ordering. */
memory_order_consume = __ATOMIC_CONSUME,
+ /** Acquire memory ordering. */
memory_order_acquire = __ATOMIC_ACQUIRE,
+ /** Release memory ordering. */
memory_order_release = __ATOMIC_RELEASE,
+ /** Acquire and release memory ordering. */
memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ /** Sequential memory ordering. */
memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
+/** Atomic boolean. */
typedef _Atomic _Bool atomic_bool;
+
+/** Atomic char. */
typedef _Atomic char atomic_char;
+
+/** Atomic signed char. */
typedef _Atomic signed char atomic_schar;
+
+/** Atomic unsigned char. */
typedef _Atomic unsigned char atomic_uchar;
+
+/** Atomic signed short. */
typedef _Atomic short atomic_short;
+
+/** Atomic unsigned short. */
typedef _Atomic unsigned short atomic_ushort;
+
+/** Atomic signed int. */
typedef _Atomic int atomic_int;
+
+/** Atomic unsigned int. */
typedef _Atomic unsigned int atomic_uint;
+
+/** Atomic signed long. */
typedef _Atomic long atomic_long;
+
+/** Atomic unsigned long. */
typedef _Atomic unsigned long atomic_ulong;
+
+/** Atomic signed long long. */
typedef _Atomic long long atomic_llong;
+
+/** Atomic unsigned long long. */
typedef _Atomic unsigned long long atomic_ullong;
+
+/** Atomic 16bit char. */
typedef _Atomic __CHAR16_TYPE__ atomic_char16_t;
+
+/** Atomic 32bit char. */
typedef _Atomic __CHAR32_TYPE__ atomic_char32_t;
+
+/** Atomic \ref wchar_t. */
typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t;
+
+/** Atomic \ref int_least8_t. */
typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t;
+
+/** Atomic \ref uint_least8_t. */
typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t;
+
+/** Atomic \ref int_least16_t. */
typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t;
+
+/** Atomic \ref uint_least16_t. */
typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t;
+
+/** Atomic \ref int_least32_t. */
typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t;
+
+/** Atomic \ref uint_least32_t. */
typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t;
+
+/** Atomic \ref int_least64_t. */
typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t;
+
+/** Atomic \ref uint_least64_t. */
typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t;
+
+/** Atomic \ref int_fast8_t. */
typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t;
+
+/** Atomic \ref uint_fast8_t. */
typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t;
+
+/** Atomic \ref int_fast16_t. */
typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t;
+
+/** Atomic \ref uint_fast16_t. */
typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t;
+
+/** Atomic \ref int_fast32_t. */
typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t;
+
+/** Atomic \ref uint_fast32_t. */
typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t;
+
+/** Atomic \ref int_fast64_t. */
typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t;
+
+/** Atomic \ref uint_fast64_t. */
typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t;
+
+/** Atomic \ref intptr_t. */
typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t;
+
+/** Atomic \ref uintptr_t. */
typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t;
+
+/** Atomic \ref size_t. */
typedef _Atomic __SIZE_TYPE__ atomic_size_t;
+
+/** Atomic \ref ptrdiff_t. */
typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t;
+
+/** Atomic \ref intmax_t. */
typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t;
+
+/** Atomic \ref uintmax_t. */
typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
+/**
+ * Atomic variable initialization. Can safely be ignored.
+ *
+ * @param VALUE Value to be used in initialization.
+ * @return \c VALUE
+ */
#define ATOMIC_VAR_INIT(VALUE) (VALUE)
+
+/**
+ * Atomic pointer initialization.
+ *
+ * @param PTR Pointer to where value should be stored.
+ * @param VAL Value to store.
+ */
#define atomic_init(PTR, VAL) atomic_store_explicit(PTR, VAL, __ATOMIC_RELAXED)
+/**
+ * Kill dependency.
+ * @todo Figure out what it means.
+ *
+ * @param y Value whose dependencies should be killed.
+ * @return \c y
+ */
#define kill_dependency(y) (y)
+/**
+ * Check if given type is lock free.
+ *
+ * @param x Type to check.
+ * @return \c 0 if never lock free, \c 1 if sometimes lock free, \c 2 if always lock
+ * free.
+ */
#if defined(__GNUC__)
#define CMPLR_LOCK_FREE(x) GLUE(__GCC_ATOMIC_, x)##_LOCK_FREE
#elif defined(__clang__)
#define CMPLR_LOCK_FREE(x) GLUE(__CLANG_ATOMIC_, x)##_LOCK_FREE
#endif
+/** Whether \ref atomic_bool is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_BOOL_LOCK_FREE CMPLR_LOCK_FREE(BOOL)
+
+/** Whether \ref atomic_char is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_CHAR_LOCK_FREE CMPLR_LOCK_FREE(CHAR)
+
+/** Whether \ref atomic_char16_t is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_CHAR16_T_LOCK_FREE CMPLR_LOCK_FREE(CHAR16_T)
+
+/** Whether \ref atomic_char32_t is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_CHAR32_T_LOCK_FREE CMPLR_LOCK_FREE(CHAR32_T)
+
+/** Whether \ref atomic_wchar_t is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_WCHAR_T_LOCK_FREE CMPLR_LOCK_FREE(WCHAR32_T)
+
+/** Whether \ref atomic_short is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_SHORT_LOCK_FREE CMPLR_LOCK_FREE(SHORT)
+
+/** Whether \ref atomic_int is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_INT_LOCK_FREE CMPLR_LOCK_FREE(INT)
+
+/** Whether \ref atomic_long is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_LONG_LOCK_FREE CMPLR_LOCK_FREE(LONG)
+
+/** Whether \ref atomic_llong is lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_LLONG_LOCK_FREE CMPLR_LOCK_FREE(LLONG)
+
+/** Whether atomic pointers are lock free. \see CMPLR_LOCK_FREE(). */
#define ATOMIC_POINTER_LOCK_FREE CMPLR_LOCK_FREE(POINTER)
+/**
+ * Helper macro for creating builtin symbols.
+ *
+ * @param x Base name of symbol.
+ */
#if defined(__GNUC__)
#define C11_ATOMIC(x) GLUE(__atomic_, x)
#elif defined(__clang__)
@@ -91,37 +229,120 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
* void atomic_signal_fence(memory_order);
*/
+/**
+ * Atomic thread fence.
+ *
+ * @param order Memory ordering. \see memory_order.
+ */
#define atomic_thread_fence(order) C11_ATOMIC(thread_fence)(order)
+
+/**
+ * Atomic signal fence.
+ *
+ * @param order Memory ordering. \see memory_order.
+ */
#define atomic_signal_fence(order) C11_ATOMIC(signal_fence)(order)
+/**
+ * Whether object is lock free.
+ *
+ * @param obj Object to check.
+ * @return \ref true if the object is lock free, \ref false otherwise.
+ */
#if defined(__GNUC__)
#define atomic_is_lock_free(obj) C11_ATOMIC(is_lock_free)(sizeof(*(obj)), (obj))
#elif defined(__clang__)
#define atomic_is_lock_free(obj) C11_ATOMIC(is_lock_free)(sizeof(*(obj)))
#endif
+/**
+ * Helper macro for creating some more builtin symbols.
+ * GCC uses \c _n suffixes for functions for equivalent functions in Clang, and
+ * this macro automatically appends \c _n when needed.
+ *
+ * @param x Base name of symbol.
+ */
#if defined(__GNUC__)
#define N_ATOMIC(x) GLUE(C11_ATOMIC(x), _n)
#elif defined(__clang__)
#define N_ATOMIC(x) C11_ATOMIC(x)
#endif
+/**
+ * Explicit memory ordering for atomic store.
+ *
+ * @param obj Pointer to store destination.
+ * @param val Value to be stored.
+ * @param mode Memory ordering. \see memory_order.
+ */
#define atomic_store_explicit(obj, val, mode) N_ATOMIC(store)(obj, val, mode)
-#define atomic_store(obj, val) \
+/**
+ * Atomic memory store with implicit strongest memory ordering.
+ *
+ * @param obj Pointer to store destination.
+ * @param val Value to be stored.
+ */
+#define atomic_store(obj, val) \
atomic_store_explicit(obj, val, __ATOMIC_SEQ_CST);
+/**
+ * Explicit memory ordering for atomic load.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to load source.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Value at \c obj.
+ */
#define atomic_load_explicit(obj, mode) N_ATOMIC(load)(obj, mode)
-#define atomic_load(obj) atomic_load_explicit(obj, \
- ATOMIC_SEQ_CST)
+/**
+ * Atomic memory load with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to load source.
+ * @return Value at \c obj.
+ */
+#define atomic_load(obj) \
+ atomic_load_explicit(obj, __ATOMIC_SEQ_CST)
+/**
+ * Explicit memory ordering for atomic exchange.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to exchange destination.
+ * @param val Value to be inserted at \c obj.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Value at \c obj.
+ */
#define atomic_exchange_explicit(obj, val, mode) \
N_ATOMIC(exchange)(obj, val, mode)
+/**
+ * Atomic memory exchange with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to exchange destination.
+ * @param val Value to be inserted at \c obj.
+ * @return Value at \c obj.
+ */
#define atomic_exchange(obj, val) \
atomic_exchange_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit strong memory compare and exchange.
+ * If \c obj and \c val are equal, the contents of \c obj are replaced with \c
+ * des. Otherwise, the contents of \c des is replaced with the contents of \c
+ * obj. The exchange is not allowed to spuriously fail.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object to be compared.
+ * @param val Value to be compared against.
+ * @param des Value to be copied if \c obj and \c val equal.
+ * @param suc Memory ordering of succesful exchange. \see memory_order.
+ * @param fail Memory ordering of unsuccesful exchange. \see memory_order.
+ * @return \ref true if \c obj and \c val equal, \ref false otherwise.
+ */
#if defined(__GNUC__)
#define atomic_compare_exchange_strong_explicit(obj, val, des, suc, fail) \
N_ATOMIC(compare_exchange)(obj, val, des, 0, suc, fail)
@@ -130,10 +351,35 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
N_ATOMIC(compare_exchange_strong)(obj, val, des, suc, fail)
#endif
+/**
+ * Strong memory compare and exchange with implicit strongest ordering. \see
+ * atomic_compare_exchange_strong_explicit().
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object to be compared.
+ * @param val Value to be compared agains.
+ * @param des Value to be copied if \c obj and \c val equal.
+ * @return \ref true if \c obj and \c val equal, \ref false otherwise.
+ */
#define atomic_compare_exchange_strong(obj, val, des) \
atomic_compare_exchange_strong_explicit( \
obj, val, des, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+/**
+ * Explicit weak memory compare and exchange.
+ * If \c obj and \c val are equal, the contents of \c obj are replaced with \c
+ * des. Otherwise, the contents of \c des is replaced with the contents of \c
+ * obj. The exchange is allowed to spuriously fail.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be compared against.
+ * @param des Value to be copied if \c obj and \c val equal.
+ * @param suc Memory ordering on succesful exchange. \see memory_order.
+ * @param fail Memory ordering on unsuccesful exchange. \see memory_order.
+ * @return \ref true if \c obj and \c val equal and exchange was succesful, \ref
+ * false otherwise.
+ */
#if defined(__GNUC__)
#define atomic_compare_exchange_weak_explicit(obj, val, des, suc, fail) \
N_ATOMIC(compare_exchange)(obj, val, des, 1, suc, fail)
@@ -142,43 +388,156 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
N_ATOMIC(compare_exchange_weak)(obj, val, des, suc, fail)
#endif
+/**
+ * Weak memory compare and exchange with implicit strongest ordering.
+ * \see atomic_compare_exchange_weak_explicit().
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be compared against.
+ * @param des Value to be copied if \c obj and \c val equal.
+ * @return \ref true if \c obj and \c val equal and exchange was succesful, \ref
+ * false otherwise.
+ */
#define atomic_compare_exchange_weak(obj, val, des) \
atomic_compare_exchange_weak_explicit(obj, val, des, __ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place addition.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be added to object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before addition.
+ */
#define atomic_fetch_add_explicit(obj, val, mode) \
C11_ATOMIC(fetch_add)(obj, val, mode)
+/**
+ * Atomic in-place addition with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be added to object.
+ * @return Contents of \c obj before addition.
+ */
#define atomic_fetch_add(obj, val) \
atomic_fetch_add_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place subtraction.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be subtracted from object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before subtraction.
+ */
#define atomic_fetch_sub_explicit(obj, val, mode) \
C11_ATOMIC(fetch_sub)(obj, val, mode)
+/**
+ * Atomic in-place subtraction with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to be subtracted from object.
+ * @return Contents of \c obj before subtraction.
+ */
#define atomic_fetch_sub(obj, val) \
atomic_fetch_sub_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place bitwise \c AND.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c AND with contents of object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before bitwise \c AND.
+ */
#define atomic_fetch_and_explicit(obj, val, mode) \
C11_ATOMIC(fetch_and)(obj, val, mode)
+/**
+ * Atomic in-place bitwise \c AND with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c AND with contents of object.
+ * @return Contents of \c obj before bitwise \c AND.
+ */
#define atomic_fetch_and(obj, val) \
atomic_fetch_and_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place bitwise \c XOR.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c XOR with contents of object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before bitwise \c XOR.
+ */
#define atomic_fetch_xor_explicit(obj, val, mode) \
C11_ATOMIC(fetch_xor)(obj, val, mode)
+/**
+ * Atomic in-place bitwise \c XOR with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c XOR with contents of object.
+ * @return Contents of \c obj before bitwise \c XOR.
+ */
#define atomic_fetch_xor(obj, val) \
atomic_fetch_xor_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place bitwise \c OR.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c OR with contents of object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before bitwise \c OR.
+ */
#define atomic_fetch_or_explicit(obj, val, mode) \
C11_ATOMIC(fetch_or)(obj, val, mode)
+/**
+ * Atomic in-place bitwise \c OR with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c OR with contents of object.
+ * @return Contents of \c obj before bitwise \c OR.
+ */
#define atomic_fetch_or(obj, val) \
atomic_fetch_or_explicit(obj, val, __ATOMIC_SEQ_CST)
+/**
+ * Explicit atomic in-place bitwise \c NAND.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c OR with contents of object.
+ * @param mode Memory ordering. \see memory_order.
+ * @return Contents of \c obj before bitwise \c NAND.
+ */
#define atomic_fetch_nand_explicit(obj, val, mode) \
C11_ATOMIC(fetch_nand)(obj, val, mode)
+/**
+ * Atomic in-place bitwise \c NAND with implicit strongest memory ordering.
+ * Type is deduced from \c obj.
+ *
+ * @param obj Pointer to object.
+ * @param val Value to bitwise \c NAND with contents of object.
+ * @return Contents of \c obj before bitwise \c NAND.
+ */
#define atomic_fetch_nand(obj, val) \
atomic_fetch_nand_explicit(obj, val, __ATOMIC_SEQ_CST)
diff --git a/include/arch/cpu.h b/include/arch/cpu.h
index 23b2911..763ebba 100644
--- a/include/arch/cpu.h
+++ b/include/arch/cpu.h
@@ -15,7 +15,15 @@
#include "../../arch/riscv32/include/cpu.h"
#endif
+/**
+ * Get current CPU ID.
+ * ID must be in range \c 0 .. \c num_cpus, where \c num_cpus is the number of
+ * cpus on this system.
+ *
+ * @return Current CPU ID.
+ */
id_t cpu_id();
+
/* TODO: add more cpu handling functions */
#endif /* APOS_CPU_H */
diff --git a/include/arch/irq.h b/include/arch/irq.h
index 5526b18..7c6a365 100644
--- a/include/arch/irq.h
+++ b/include/arch/irq.h
@@ -5,6 +5,8 @@
* @file irq.h
* Arch-specific interrupt handling, generally implemented in
* arch/whatever/kernel/irq.c
+ *
+ * @todo These should probably also be stat_t...
*/
#if defined(riscv64)
@@ -13,9 +15,17 @@
#include "../../arch/riscv32/include/irq.h"
#endif
+/**
+ * Initialize IRQ subsystem.
+ *
+ * @param fdt Global FDT pointer.
+ */
void init_irq(void *fdt);
-void handle_irq();
+
+/** Enable IRQs. */
void enable_irq();
+
+/** Disable IRQs. */
void disable_irq();
#endif /* APOS_IRQ_H */
diff --git a/include/arch/pmem.h b/include/arch/pmem.h
index c9423b2..21a721a 100644
--- a/include/arch/pmem.h
+++ b/include/arch/pmem.h
@@ -16,6 +16,47 @@
#include "../../arch/riscv32/include/pmem.h"
#endif
+/**
+ * Get physical memory parameters.
+ *
+ * The kernel assumes all virtual addresses can be represented approximately as
+ * follows:
+ *
+ * @code
+ * Content ... 0 1 1 0 0 1 0 1 0
+ * -----------------------------
+ * Index ... 9 8 7 6 5 4 3 2 1
+ * --- --- --- +++++++
+ * O2 O1 O0 Base
+ * @endcode
+ *
+ * Where \c Base is a portion of the address that is directly passed through
+ * without any lookups, and each \c O0, \c O1, \c O2 are increasingly higher
+ * order pages, where each order is an index into the higher order.
+ *
+ * For example, in the diagram above:
+ * The base page is four bits, and each page order consists of four pages of
+ * one order lower (two bits), and there are three orders, so
+ * @code
+ * max_order = 2
+ * base_bits = 4
+ * bits[0] = 2
+ * bits[1] = 2
+ * bits[2] = 2
+ * bits[3] = 0
+ * ...
+ * @endcode
+ *
+ * @todo Move documentation into its own .md
+ *
+ * @param fdt Global FDT pointer.
+ * @param max_order Highest order pages the arch supports.
+ * @param base_bits Size of base page as number of bits in bitmask.
+ * Eg. 12bits -> 4k page.
+ * @param bits Size in bits as bitmask of corresponding page order. Zeroed out
+ * beforehand.
+ * @return \ref OK when query succesful, arch specific otherwise.
+ */
stat_t stat_pmem_conf(void *fdt, size_t *max_order, size_t *base_bits,
size_t bits[NUM_ORDERS]);
diff --git a/uncrustify.conf b/uncrustify.conf
index 8649f3e..7221de0 100644
--- a/uncrustify.conf
+++ b/uncrustify.conf
@@ -1,5 +1,8 @@
# Uncrustify-0.72.0_f
+# TODO: add slightly more strict rules, there are a few too many 'ignore'
+# directives for my liking.
+
#
# General options
#