kernel: separate headers into kernel and user headers

all kernel headers have been moved from include/mango to include/kernel
and include definitions that are only relevant to kernel-space.

any definitions that are relevant to both kernel- and user-space
(i.e. type definitions, syscall IDs) have been moved to
include/mango within libmango.
This commit is contained in:
2026-02-19 18:54:48 +00:00
parent e3dd48a0fa
commit 6019c9307d
117 changed files with 1361 additions and 3845 deletions

View File

@@ -40,6 +40,7 @@ add_executable(${kernel_exe_name}
target_include_directories(${kernel_exe_name} PRIVATE target_include_directories(${kernel_exe_name} PRIVATE
include include
libc/include libc/include
libmango/include
arch/${kernel_arch}/include) arch/${kernel_arch}/include)
target_compile_options(${kernel_exe_name} PRIVATE target_compile_options(${kernel_exe_name} PRIVATE
-nostdlib -ffreestanding -nostdlib -ffreestanding

View File

@@ -1,5 +1,5 @@
#include <unistd.h> #include <unistd.h>
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
int ml_init_bootcpu(void) int ml_init_bootcpu(void)
{ {

View File

@@ -1,5 +1,5 @@
#include <mango/machine/hwlock.h> #include <kernel/machine/hwlock.h>
#include <mango/compiler.h> #include <kernel/compiler.h>
void ml_hwlock_lock(ml_hwlock_t *lck) void ml_hwlock_lock(ml_hwlock_t *lck)
{ {

View File

@@ -1,11 +1,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <mango/init.h> #include <kernel/init.h>
#include <mango/memblock.h> #include <kernel/memblock.h>
#include <mango/vm.h> #include <kernel/vm.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <arch/stdcon.h> #include <arch/stdcon.h>
#include <sys/mman.h> #include <sys/mman.h>

View File

@@ -1,4 +1,4 @@
#include <mango/init.h> #include <kernel/init.h>
#ifdef __APPLE__ #ifdef __APPLE__
extern char __start_initcall0[] __asm("section$start$__DATA$__initcall0.init"); extern char __start_initcall0[] __asm("section$start$__DATA$__initcall0.init");

View File

@@ -1,10 +1,10 @@
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#include <mango/libc/ctype.h> #include <kernel/libc/ctype.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <mango/console.h> #include <kernel/console.h>
#include <mango/vm.h> #include <kernel/vm.h>
#include <mango/printk.h> #include <kernel/printk.h>
static void stdcon_write(struct console *con, const char *s, unsigned int len) static void stdcon_write(struct console *con, const char *s, unsigned int len)
{ {

View File

@@ -1,5 +1,5 @@
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/compiler.h> #include <kernel/compiler.h>
//size_t THREAD_sp = offsetof(struct thread, tr_sp); //size_t THREAD_sp = offsetof(struct thread, tr_sp);

View File

@@ -1,5 +1,5 @@
#include <arch/msr.h> #include <arch/msr.h>
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
int ml_cpu_block_init(ml_cpu_block *p) int ml_cpu_block_init(ml_cpu_block *p)
{ {

View File

@@ -1,8 +1,8 @@
#include "mango/types.h"
#include <mango/memblock.h>
#include <mango/printk.h>
#include <mango/util.h>
#include <arch/e820.h> #include <arch/e820.h>
#include <kernel/memblock.h>
#include <kernel/printk.h>
#include <kernel/types.h>
#include <kernel/util.h>
void e820_scan(multiboot_memory_map_t *mmap, size_t len) void e820_scan(multiboot_memory_map_t *mmap, size_t len)
{ {

View File

@@ -1,7 +1,7 @@
#include <arch/gdt.h> #include <arch/gdt.h>
#include <arch/tss.h> #include <arch/tss.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#include <mango/types.h> #include <kernel/types.h>
#include <stddef.h> #include <stddef.h>
static void init_entry(struct gdt_entry *entry, int access, int flags) static void init_entry(struct gdt_entry *entry, int access, int flags)

View File

@@ -2,7 +2,7 @@
#define ARCH_GDT_H_ #define ARCH_GDT_H_
#include <arch/tss.h> #include <arch/tss.h>
#include <mango/compiler.h> #include <kernel/compiler.h>
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_IRQ_H_ #ifndef ARCH_IRQ_H_
#define ARCH_IRQ_H_ #define ARCH_IRQ_H_
#include <mango/compiler.h> #include <kernel/compiler.h>
#include <mango/queue.h> #include <kernel/queue.h>
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_PAGING_H_ #ifndef ARCH_PAGING_H_
#define ARCH_PAGING_H_ #define ARCH_PAGING_H_
#include <mango/types.h> #include <kernel/types.h>
#include <mango/compiler.h> #include <kernel/compiler.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -1,8 +1,8 @@
#ifndef ARCH_TSS_H_ #ifndef ARCH_TSS_H_
#define ARCH_TSS_H_ #define ARCH_TSS_H_
#include <mango/compiler.h> #include <kernel/compiler.h>
#include <mango/types.h> #include <kernel/types.h>
#include <stdint.h> #include <stdint.h>
#define TSS_GDT_INDEX 5 #define TSS_GDT_INDEX 5

View File

@@ -1,73 +0,0 @@
#ifndef MANGO_X86_64_CPU_H_
#define MANGO_X86_64_CPU_H_
#include <arch/gdt.h>
#include <arch/irq.h>
#include <arch/tss.h>
#include <mango/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ML_BIG_ENDIAN 0
#define ml_cpu_block_get_id(p) ((p)->c_cpu_id)
#define ml_cpu_block_get_data(p) ((p)->c_data)
#if 0
#define ml_read_sp(sp, bp) \
asm volatile("mov %%rsp, %0" : "=r"(sp)); \
asm volatile("mov %%rbp, %0" : "=r"(bp));
#endif
struct cpu_data;
typedef struct ml_cpu_block {
struct ml_cpu_block *c_this;
struct gdt c_gdt;
struct gdt_ptr c_gdt_ptr;
struct tss c_tss;
struct tss_ptr c_tss_ptr;
struct idt_ptr c_idt_ptr;
unsigned int c_cpu_id;
struct cpu_data *c_data;
} ml_cpu_block;
struct ml_cpu_context {
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rdi, rsi, rbp, unused_rsp, rbx, rdx, rcx, rax;
uint64_t int_no, err_no;
uint64_t rip, cs, rflags, rsp, ss;
} __packed;
#define ml_cpu_pause() __asm__ __volatile__("hlt")
#define ml_cpu_relax() __asm__ __volatile__("pause")
#define ml_int_disable() __asm__ __volatile__("cli")
#define ml_int_enable() __asm__ __volatile__("sti")
extern int ml_init_bootcpu(void);
extern int ml_cpu_block_init(ml_cpu_block *p);
extern int ml_cpu_block_use(ml_cpu_block *p);
extern virt_addr_t ml_cpu_block_get_ustack(ml_cpu_block *p);
extern virt_addr_t ml_cpu_block_get_kstack(ml_cpu_block *p);
extern void ml_cpu_block_set_ustack(ml_cpu_block *p, virt_addr_t sp);
extern void ml_cpu_block_set_kstack(ml_cpu_block *p, virt_addr_t sp);
/* defined in cpu_ctrl.S */
extern void ml_halt_cpu(void);
extern ml_cpu_block *ml_this_cpu(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,22 +0,0 @@
#ifndef MANGO_X86_64_HWLOCK_H_
#define MANGO_X86_64_HWLOCK_H_
#define ML_HWLOCK_INIT (0)
#ifdef __cplusplus
extern "C" {
#endif
typedef int ml_hwlock_t;
extern void ml_hwlock_lock(ml_hwlock_t *lck);
extern void ml_hwlock_unlock(ml_hwlock_t *lck);
extern void ml_hwlock_lock_irqsave(ml_hwlock_t *lck, unsigned long *flags);
extern void ml_hwlock_unlock_irqrestore(ml_hwlock_t *lck, unsigned long flags);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,28 +0,0 @@
#ifndef MANGO_X86_64_INIT_H_
#define MANGO_X86_64_INIT_H_
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define __X2(x) #x
#define __X(x) __X2(x)
#define __define_initcall(fn, id) \
static initcall_t __initcall_##fn##id __used __section( \
".initcall" __X(id) ".init") \
= (fn)
extern int ml_init(uintptr_t arg);
extern const struct framebuffer_varinfo *bootfb_varinfo(void);
extern const struct framebuffer_fixedinfo *bootfb_fixedinfo(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,5 +0,0 @@
#ifndef MANGO_X86_64_IRQ_H_
#define MANGO_X86_64_IRQ_H_
#endif

View File

@@ -1,12 +0,0 @@
#ifndef MANGO_X86_64_PANIC_H_
#define MANGO_X86_64_PANIC_H_
#include <stdint.h>
struct ml_cpu_context;
extern void ml_print_cpu_state(struct ml_cpu_context *ctx);
extern void ml_print_stack_trace(uintptr_t ip);
extern void ml_print_stack_trace_irq(struct ml_cpu_context *ctx);
#endif

View File

@@ -1,11 +0,0 @@
#ifndef MANGO_X86_64_PMAP_H_
#define MANGO_X86_64_PMAP_H_
#include <arch/paging.h>
#define ML_PMAP_INVALID ((uintptr_t)-1)
typedef pml4t_ptr_t ml_pmap_t;
typedef uint64_t ml_pfn_t;
#endif

View File

@@ -1,29 +0,0 @@
#ifndef MANGO_X86_64_THREAD_H_
#define MANGO_X86_64_THREAD_H_
#include <mango/sched.h>
struct ml_cpu_context;
/* switch from one thread to another. the stack of the `to` thread must have
* been prepared in one of two ways:
* 1) a previous call to ml_thread_switch where it was the `from` thread.
* 2) a call to ml_thread_prepare_kernel_context
* the switch occurs entirely with kernel mode. a further return from an
* interrupt context is then used to return to usermode if necessary.
*/
extern void ml_thread_switch(struct thread *from, struct thread *to);
/* perform the initial transition to userspace. the stack must be prepared using
* ml_thread_prepare_user_context before this function can be used */
extern void ml_thread_switch_user(void);
/* prepare the stack so that ml_thread_switch can jump to the specified IP/SP */
extern void ml_thread_prepare_kernel_context(uintptr_t ip, uintptr_t *sp);
/* prepare the stack so that ml_thread_switch_user can jump to usermode
* with the specified IP/user SP */
extern void ml_thread_prepare_user_context(
virt_addr_t ip,
virt_addr_t user_sp,
virt_addr_t *kernel_sp);
#endif

View File

@@ -1,30 +0,0 @@
#ifndef MANGO_X86_64_VM_H_
#define MANGO_X86_64_VM_H_
/* kernel higher-half base virtual address. */
#define VM_KERNEL_VOFFSET 0xFFFFFFFF80000000
/* direct page-mapping region.
NOTE that these are the maximum bounds of this region.
the actual size depends on the amount of physical
memory present. */
#define VM_PAGEMAP_BASE 0xFFFF888000000000
#define VM_PAGEMAP_LIMIT 0xFFFFC87FFFFFFFFF
#define VM_PAGE_SIZE 0x1000
#define VM_PAGE_MASK (VM_PAGE_SIZE - 1)
#define VM_PAGE_SHIFT 12
#define VM_PAGE_MIN_ORDER VM_PAGE_4K
#define VM_PAGE_MAX_ORDER VM_PAGE_8M
#define VM_ZONE_MIN VM_ZONE_DMA
#define VM_ZONE_MAX VM_ZONE_NORMAL
#define VM_USER_BASE 0x0000000000100000
#define VM_USER_LIMIT 0x00007fffffffffff
#define VM_KERNEL_BASE 0XFFFF800000000000
#define VM_KERNEL_LIMIT 0XFFFFFFFFFFFFFFFF
#endif

View File

@@ -2,21 +2,21 @@
#include <arch/pit.h> #include <arch/pit.h>
#include <arch/serial.h> #include <arch/serial.h>
#include <arch/vgacon.h> #include <arch/vgacon.h>
#include <mango/arg.h> #include <kernel/arg.h>
#include <mango/bsp.h> #include <kernel/bsp.h>
#include <mango/clock.h> #include <kernel/clock.h>
#include <mango/console.h> #include <kernel/console.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/init.h> #include <kernel/init.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
#include <mango/memblock.h> #include <kernel/memblock.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/percpu.h> #include <kernel/percpu.h>
#include <mango/pmap.h> #include <kernel/pmap.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/types.h> #include <kernel/types.h>
#include <mango/vm.h> #include <kernel/vm.h>
#define PTR32(x) ((void *)((uintptr_t)(x))) #define PTR32(x) ((void *)((uintptr_t)(x)))

View File

@@ -1,4 +1,4 @@
#include <mango/init.h> #include <kernel/init.h>
extern char __initcall0_start[]; extern char __initcall0_start[];
extern char __initcall1_start[]; extern char __initcall1_start[];

View File

@@ -1,13 +1,13 @@
#include <arch/irq.h> #include <arch/irq.h>
#include <arch/msr.h> #include <arch/msr.h>
#include <arch/ports.h> #include <arch/ports.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
#include <mango/machine/irq.h> #include <kernel/machine/irq.h>
#include <mango/panic.h> #include <kernel/panic.h>
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/syscall.h> #include <kernel/syscall.h>
#include <stddef.h> #include <stddef.h>
#define MAX_ISR_HANDLERS 16 #define MAX_ISR_HANDLERS 16
@@ -31,7 +31,7 @@ static uintptr_t int_entry_points[NR_IDT_ENTRIES];
static void set_syscall_gate(uintptr_t rip) static void set_syscall_gate(uintptr_t rip)
{ {
uint64_t user_cs = 0x13; uint64_t user_cs = 0x13;
uint64_t kernel_cs = 0x8; uint64_t kernel_cs = 0x08;
uintptr_t star_reg = 0xC0000081; uintptr_t star_reg = 0xC0000081;
uintptr_t lstar_reg = 0xC0000082; uintptr_t lstar_reg = 0xC0000082;
@@ -97,11 +97,7 @@ static void pf_handler(struct ml_cpu_context *regs)
virt_addr_t fault_ptr = pf_faultptr(); virt_addr_t fault_ptr = pf_faultptr();
kern_status_t status = KERN_FATAL_ERROR; kern_status_t status = pmap_handle_fault(fault_ptr, fault_flags);
if (regs->err_no & PF_USER) {
status = pmap_handle_fault(fault_ptr, fault_flags);
}
if (status == KERN_OK) { if (status == KERN_OK) {
return; return;

View File

@@ -1,9 +1,9 @@
#include <arch/irq.h> #include <arch/irq.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
#include <mango/machine/panic.h> #include <kernel/machine/panic.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/vm.h> #include <kernel/vm.h>
#define R_CF 0 #define R_CF 0
#define R_PF 2 #define R_PF 2

View File

@@ -1,8 +1,8 @@
#include <arch/irq.h> #include <arch/irq.h>
#include <arch/ports.h> #include <arch/ports.h>
#include <mango/clock.h> #include <kernel/clock.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/printk.h> #include <kernel/printk.h>
#define PIT_COUNTER0 0x40 #define PIT_COUNTER0 0x40
#define PIT_CMD 0x43 #define PIT_CMD 0x43

View File

@@ -1,14 +1,14 @@
#include <mango/compiler.h> #include <kernel/compiler.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/memblock.h> #include <kernel/memblock.h>
#include <mango/pmap.h> #include <kernel/pmap.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/sched.h> #include <kernel/sched.h>
#include <kernel/types.h>
#include <kernel/vm-object.h>
#include <kernel/vm-region.h>
#include <kernel/vm.h>
#include <mango/status.h> #include <mango/status.h>
#include <mango/types.h>
#include <mango/vm-object.h>
#include <mango/vm-region.h>
#include <mango/vm.h>
/* some helpful datasize constants */ /* some helpful datasize constants */
#define C_1GiB 0x40000000ULL #define C_1GiB 0x40000000ULL
@@ -43,7 +43,7 @@ static pmap_t alloc_pmap(void)
return vm_virt_to_phys(p); return vm_virt_to_phys(p);
} }
static pte_t make_pte(pfn_t pfn, enum vm_prot prot, enum page_size size) static pte_t make_pte(pfn_t pfn, vm_prot_t prot, enum page_size size)
{ {
pte_t v = pfn; pte_t v = pfn;
@@ -139,7 +139,7 @@ static kern_status_t do_pmap_add(
pmap_t pmap, pmap_t pmap,
virt_addr_t pv, virt_addr_t pv,
pfn_t pfn, pfn_t pfn,
enum vm_prot prot, vm_prot_t prot,
enum page_size size) enum page_size size)
{ {
unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX, unsigned int pml4t_index = BAD_INDEX, pdpt_index = BAD_INDEX,
@@ -371,7 +371,7 @@ kern_status_t pmap_add(
pmap_t pmap, pmap_t pmap,
virt_addr_t p, virt_addr_t p,
pfn_t pfn, pfn_t pfn,
enum vm_prot prot, vm_prot_t prot,
enum pmap_flags flags) enum pmap_flags flags)
{ {
enum page_size ps = PS_4K; enum page_size ps = PS_4K;
@@ -387,7 +387,7 @@ kern_status_t pmap_add_block(
virt_addr_t p, virt_addr_t p,
pfn_t pfn, pfn_t pfn,
size_t len, size_t len,
enum vm_prot prot, vm_prot_t prot,
enum pmap_flags flags) enum pmap_flags flags)
{ {
return KERN_OK; return KERN_OK;

View File

@@ -1,8 +1,8 @@
#include <arch/irq.h> #include <arch/irq.h>
#include <arch/ports.h> #include <arch/ports.h>
#include <arch/serial.h> #include <arch/serial.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/printk.h> #include <kernel/printk.h>
#define COM1 0x3F8 #define COM1 0x3F8
#define COM2 0x2F8 #define COM2 0x2F8

View File

@@ -1,5 +1,5 @@
#include <mango/machine/cpu.h> #include <kernel/machine/cpu.h>
#include <mango/machine/thread.h> #include <kernel/machine/thread.h>
/* this is the context information restored by ml_thread_switch. /* this is the context information restored by ml_thread_switch.
* since ml_thread_switch only jumps to kernel-mode, IRETQ isn't used, * since ml_thread_switch only jumps to kernel-mode, IRETQ isn't used,

View File

@@ -2,7 +2,7 @@
#include <arch/gdt.h> #include <arch/gdt.h>
#include <arch/tss.h> #include <arch/tss.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
static void tss_flush(int index) static void tss_flush(int index)
{ {

View File

@@ -1,9 +1,9 @@
#include <arch/irq.h> #include <arch/irq.h>
#include <arch/ports.h> #include <arch/ports.h>
#include <arch/serial.h> #include <arch/serial.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/machine/vm.h> #include <kernel/machine/vm.h>
#include <mango/printk.h> #include <kernel/printk.h>
struct vga_console { struct vga_console {
uint16_t *vga_framebuffer; uint16_t *vga_framebuffer;

View File

@@ -1,5 +1,5 @@
#include <mango/bitmap.h> #include <kernel/bitmap.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
void bitmap_zero(unsigned long *map, unsigned long nbits) void bitmap_zero(unsigned long *map, unsigned long nbits)
{ {

View File

@@ -57,7 +57,7 @@
provide a comparator function. provide a comparator function.
*/ */
#include <mango/btree.h> #include <kernel/btree.h>
#include <stddef.h> #include <stddef.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))

View File

@@ -1,4 +1,4 @@
#include <mango/queue.h> #include <kernel/queue.h>
size_t queue_length(struct queue *q) size_t queue_length(struct queue *q)
{ {

View File

@@ -1,5 +1,5 @@
#include <mango/ringbuffer.h> #include <kernel/ringbuffer.h>
#include <mango/sched.h> #include <kernel/sched.h>
size_t ringbuffer_unread(struct ringbuffer *ring_buffer) size_t ringbuffer_unread(struct ringbuffer *ring_buffer)
{ {

View File

@@ -1,14 +0,0 @@
#ifndef MANGO_ARG_H_
#define MANGO_ARG_H_
#include <stdbool.h>
#include <mango/status.h>
#define CMDLINE_MAX 4096
extern kern_status_t parse_cmdline(const char *cmdline);
extern const char *arg_value(const char *arg_name);
extern bool arg_is_set(const char *arg_name);
#endif

View File

@@ -1,35 +0,0 @@
#ifndef MANGO_BITMAP_H_
#define MANGO_BITMAP_H_
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BITS_PER_WORD (8 * sizeof(unsigned long))
#define __DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define BITMAP_WORDS(nbits) __DIV_ROUND_UP(nbits, BITS_PER_WORD)
#define BITMAP_NPOS ((unsigned int)-1)
#define DECLARE_BITMAP(name, nbits) unsigned long name[BITMAP_WORDS(nbits)]
extern void bitmap_zero(unsigned long *map, unsigned long nbits);
extern void bitmap_fill(unsigned long *map, unsigned long nbits);
extern void bitmap_set(unsigned long *map, unsigned long bit);
extern void bitmap_clear(unsigned long *map, unsigned long bit);
extern bool bitmap_check(unsigned long *map, unsigned long bit);
extern unsigned int bitmap_count_set(unsigned long *map, unsigned long nbits);
extern unsigned int bitmap_count_clear(unsigned long *map, unsigned long nbits);
extern unsigned int bitmap_highest_set(unsigned long *map, unsigned long nbits);
extern unsigned int bitmap_highest_clear(unsigned long *map, unsigned long nbits);
extern unsigned int bitmap_lowest_set(unsigned long *map, unsigned long nbits);
extern unsigned int bitmap_lowest_clear(unsigned long *map, unsigned long nbits);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,38 +0,0 @@
#ifndef MANGO_BSP_H_
#define MANGO_BSP_H_
#include <mango/compiler.h>
#include <mango/status.h>
#include <mango/types.h>
#include <stddef.h>
#include <stdint.h>
#define BSP_MAGIC 0xcafebabe
struct task;
struct bsp_trailer {
/* these fields are stored in big endian in the package itself */
uint32_t bsp_magic;
uint64_t bsp_fs_offset;
uint32_t bsp_fs_len;
uint64_t bsp_exec_offset;
uint32_t bsp_exec_len;
uint64_t bsp_text_faddr, bsp_text_vaddr, bsp_text_size;
uint64_t bsp_data_faddr, bsp_data_vaddr, bsp_data_size;
uint64_t bsp_exec_entry;
} __packed;
struct bsp {
/* the values in this struct are stored in host byte order */
struct bsp_trailer bsp_trailer;
struct vm_object *bsp_vmo;
};
extern void bsp_set_location(const struct boot_module *mod);
extern void bsp_get_location(struct boot_module *out);
extern kern_status_t bsp_load(struct bsp *bsp, const struct boot_module *mod);
extern kern_status_t bsp_launch_async(struct bsp *bsp, struct task *task);
#endif

View File

@@ -1,381 +0,0 @@
/*
The Clear BSD License
Copyright (c) 2023 Max Wash
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the disclaimer
below) provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
*/
#ifndef MANGO_BTREE_H_
#define MANGO_BTREE_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* if your custom structure contains a struct btree_node (i.e. it can be part of a btree),
you can use this macro to convert a struct btree_node* to a your_type*
@param t the name of your custom type (something that can be passed to offsetof)
@param m the name of the struct btree_node member variable within your custom type.
@param v the struct btree_node pointer that you wish to convert. if this is NULL, NULL will be returned.
*/
#define BTREE_CONTAINER(t, m, v) ((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
/* defines a simple node insertion function.
this function assumes that your nodes have simple integer keys that can be compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
struct btree_node base;
}
You would use the following call to generate an insert function for a tree with this node type:
BTREE_DEFINE_SIMPLE_INSERT(struct my_tree_node, base, key, my_tree_node_insert);
Which would emit a function defined like:
static void my_tree_node_insert(struct btree *tree, struct my_tree_node *node);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param function_name the name of the function to generate.
*/
#define BTREE_DEFINE_SIMPLE_INSERT(node_type, container_node_member, container_key_member, function_name) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
struct btree_node *next = NULL; \
\
if (node->container_key_member > cur_node->container_key_member) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right(cur, &node->container_node_member); \
break; \
} \
} else if (node->container_key_member < cur_node->container_key_member) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left(cur, &node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a node insertion function.
this function should be used for trees with complex node keys that cannot be directly compared.
a comparator for your keys must be supplied.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
complex_key_t key;
struct btree_node base;
}
You would need to define a comparator function or macro with the following signature:
int my_comparator(struct my_tree_node *a, struct my_tree_node *b);
Which implements the following:
return -1 if a < b
return 0 if a == b
return 1 if a > b
You would use the following call to generate an insert function for a tree with this node type:
BTREE_DEFINE_INSERT(struct my_tree_node, base, key, my_tree_node_insert, my_comparator);
Which would emit a function defined like:
static void my_tree_node_insert(struct btree *tree, struct my_tree_node *node);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param function_name the name of the function to generate.
@param comparator the name of a comparator function or functional-macro that conforms to the
requirements listed above.
*/
#define BTREE_DEFINE_INSERT(node_type, container_node_member, container_key_member, function_name, comparator) \
void function_name(struct btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
struct btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
struct btree_node *next = NULL; \
int cmp = comparator(node, cur_node); \
\
if (cmp == 1) { \
next = btree_right(cur); \
\
if (!next) { \
btree_put_right(cur, &node->container_node_member); \
break; \
} \
} else if (cmp == -1) { \
next = btree_left(cur); \
\
if (!next) { \
btree_put_left(cur, &node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a simple tree search function.
this function assumes that your nodes have simple integer keys that can be compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
struct btree_node base;
}
You would use the following call to generate a search function for a tree with this node type:
BTREE_DEFINE_SIMPLE_GET(struct my_tree_node, int, base, key, my_tree_node_get);
Which would emit a function defined like:
static struct my_tree_node *my_tree_node_get(struct btree *tree, int key);
@param node_type your custom tree node type. usually a structure that contains a struct btree_node member.
@param key_type the type name of the key embedded in your custom tree node type. this type must be
compatible with the builtin comparison operators.
@param container_node_member the name of the struct btree_node member variable within your custom type.
@param container_key_member the name of the key member variable within your custom type.
@param function_name the name of the function to generate.
*/
#define BTREE_DEFINE_SIMPLE_GET(node_type, key_type, container_node_member, container_key_member, function_name) \
node_type *function_name(struct btree *tree, key_type key) \
{ \
struct btree_node *cur = tree->b_root; \
while (cur) { \
node_type *cur_node = BTREE_CONTAINER(node_type, container_node_member, cur); \
if (key > cur_node->container_key_member) { \
cur = btree_right(cur); \
} else if (key < cur_node->container_key_member) { \
cur = btree_left(cur); \
} else { \
return cur_node; \
} \
} \
\
return NULL; \
}
/* perform an in-order traversal of a binary tree
If you have a tree defined like:
struct btree my_tree;
with nodes defined like:
struct my_tree_node {
int key;
struct btree_node base;
}
and you want to do something like:
foreach (struct my_tree_node *node : my_tree) { ... }
you should use this:
btree_foreach (struct my_tree_node, node, &my_tree, base) { ... }
@param iter_type the type name of the iterator variable. this should be the tree's node type, and shouldn't be a pointer.
@param iter_name the name of the iterator variable.
@param tree_name a pointer to the tree to traverse.
@param node_member the name of the struct btree_node member variable within the tree node type.
*/
#define btree_foreach(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name = BTREE_CONTAINER(iter_type, node_member, btree_first(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER(iter_type, node_member, btree_next(&((iter_name)->node_member))))
/* perform an reverse in-order traversal of a binary tree
If you have a tree defined like:
struct btree my_tree;
with nodes defined like:
struct my_tree_node {
int key;
struct btree_node base;
}
and you want to do something like:
foreach (struct my_tree_node *node : reverse(my_tree)) { ... }
you should use this:
btree_foreach_r (struct my_tree_node, node, &my_tree, base) { ... }
@param iter_type the type name of the iterator variable. this should be the tree's node type, and shouldn't be a pointer.
@param iter_name the name of the iterator variable.
@param tree_name a pointer to the tree to traverse.
@param node_member the name of the struct btree_node member variable within the tree node type.
*/
#define btree_foreach_r(iter_type, iter_name, tree_name, node_member) \
for (iter_type *iter_name = BTREE_CONTAINER(iter_type, node_member, btree_last(tree_name)); \
iter_name; \
iter_name = BTREE_CONTAINER(iter_type, node_member, btree_prev(&((iter_name)->node_member))))
/* binary tree nodes. this *cannot* be used directly. you need to define a custom node type
that contains a member variable of type struct btree_node.
you would then use the supplied macros to define functions to manipulate your custom binary tree.
*/
struct btree_node {
struct btree_node *b_parent, *b_left, *b_right;
unsigned short b_height;
};
/* binary tree. unlike struct btree_node, you can define variables of type struct btree. */
struct btree {
struct btree_node *b_root;
};
/* re-balance a binary tree after an insertion operation.
NOTE that, if you define an insertion function using BTREE_DEFINE_INSERT or similar,
this function will automatically called for you.
@param tree the tree to re-balance.
@param node the node that was just inserted into the tree.
*/
extern void btree_insert_fixup(struct btree *tree, struct btree_node *node);
/* delete a node from a binary tree and re-balance the tree afterwards.
@param tree the tree to delete from
@param node the node to delete.
*/
extern void btree_delete(struct btree *tree, struct btree_node *node);
/* get the first node in a binary tree.
this will be the node with the smallest key (i.e. the node that is furthest-left from the root)
*/
extern struct btree_node *btree_first(struct btree *tree);
/* get the last node in a binary tree.
this will be the node with the largest key (i.e. the node that is furthest-right from the root)
*/
extern struct btree_node *btree_last(struct btree *tree);
/* for any binary tree node, this function returns the node with the next-largest key value */
extern struct btree_node *btree_next(struct btree_node *node);
/* for any binary tree node, this function returns the node with the next-smallest key value */
extern struct btree_node *btree_prev(struct btree_node *node);
/* sets `child` as the immediate left-child of `parent` */
static inline void btree_put_left(struct btree_node *parent, struct btree_node *child)
{
parent->b_left = child;
child->b_parent = parent;
}
/* sets `child` as the immediate right-child of `parent` */
static inline void btree_put_right(struct btree_node *parent, struct btree_node *child)
{
parent->b_right = child;
child->b_parent = parent;
}
/* get the immediate left-child of `node` */
static inline struct btree_node *btree_left(struct btree_node *node)
{
return node->b_left;
}
/* get the immediate right-child of `node` */
static inline struct btree_node *btree_right(struct btree_node *node)
{
return node->b_right;
}
/* get the immediate parent of `node` */
static inline struct btree_node *btree_parent(struct btree_node *node)
{
return node->b_parent;
}
/* get the height of `node`.
the height of a node is defined as the length of the longest path
between the node and a leaf node.
this count includes the node itself, so the height of a leaf node will be 1.
*/
static inline unsigned short btree_height(struct btree_node *node)
{
return node->b_height;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,27 +0,0 @@
#ifndef MANGO_CLOCK_H_
#define MANGO_CLOCK_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HZ (clock_hz())
typedef uint64_t clock_ticks_t;
extern volatile clock_ticks_t clock_ticks;
extern clock_ticks_t clock_hz(void);
extern void clock_calibrate(clock_ticks_t hz);
extern void clock_advance(clock_ticks_t ticks);
extern void clock_wait(clock_ticks_t ticks);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,41 +0,0 @@
#ifndef MANGO_COMPILER_H_
#define MANGO_COMPILER_H_
#ifdef __cplusplus
template <typename T>
T read_once(const volatile T *ptr)
{
return *ptr;
}
template <typename T>
void write_once(volatile T *ptr, T value)
{
*ptr = value;
}
#else
#define READ_ONCE(p) (*((const volatile typeof(p) *)&(p)))
#define WRITE_ONCE(p, v) *(volatile typeof(p) *)&(p) = (v)
#endif
#undef __used
#define __used __attribute__((__used__))
#undef __noreturn
#define __noreturn __attribute__((__noreturn__))
#undef __packed
#define __packed __attribute__((__packed__))
#undef __section
#define __section(name) __attribute__((__section__(name)))
#undef __aligned
#define __aligned(x) __attribute__((__aligned__(x)))
#undef __weak
#define __weak __attribute__((__weak__))
#endif

View File

@@ -1,56 +0,0 @@
#ifndef MANGO_CONSOLE_H_
#define MANGO_CONSOLE_H_
/* The console system
Consoles are like simplified TTYs. Their purpose is to serve as an output
sink for messages printed using printk.
a struct console could be used to represent a serial port, UART port, or even
a text-based framebuffer display. Anything where the job of displaying
or sending text can be abstracted to a simple write() call.
A secondary purpose of consoles is to allow input. For example, a console
representing a serial port may allow both sending AND receiving over the
port.
*/
#include <mango/queue.h>
#include <mango/locks.h>
#include <mango/status.h>
#ifdef __cplusplus
extern "C" {
#endif
enum console_flags {
/* console is only used during the boot process. the console
will be automatically de-registered when the first
non-boot console is registered */
CON_BOOT = 0x01u,
};
struct console {
char c_name[16];
enum console_flags c_flags;
spin_lock_t c_lock;
void (*c_write)(struct console *, const char *, unsigned int);
int (*c_read)(struct console *, char *, unsigned int);
struct queue_entry c_list;
};
extern kern_status_t console_register(struct console *con);
extern kern_status_t console_unregister(struct console *con);
extern struct queue *get_consoles(unsigned long *flags);
extern void put_consoles(struct queue *consoles, unsigned long flags);
extern void console_write(struct console *con, const char *s, unsigned int len);
extern int console_read(struct console *con, char *s, unsigned int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,65 +0,0 @@
#ifndef MANGO_CPU_H_
#define MANGO_CPU_H_
#include <mango/types.h>
#include <mango/machine/cpu.h>
#include <stdint.h>
#include <mango/sched.h>
#ifdef __cplusplus
extern "C" {
#endif
enum cpu_flags {
CPU_ONLINE = 0x01u,
};
struct cpu_data {
enum cpu_flags c_flags;
unsigned int c_id;
int c_preempt_count;
struct runqueue c_rq;
struct workqueue c_wq;
struct queue c_timers;
};
/* maximum number of processor cores that the kernel can support.
TODO move to build config option */
#define CPU_MAX 128
#define this_cpu() (ml_cpu_block_get_id(ml_this_cpu()))
extern struct cpu_data *get_this_cpu(void);
extern struct cpu_data *get_cpu(unsigned int id);
extern void put_cpu(struct cpu_data *cpu);
extern bool cpu_is_available(unsigned int cpu_id);
extern bool cpu_is_online(unsigned int cpu_id);
extern void cpu_set_available(unsigned int cpu_id);
extern void cpu_set_online(unsigned int cpu_id);
extern unsigned int cpu_nr_available(void);
extern unsigned int cpu_nr_online(void);
extern cycles_t get_cycles(void);
static inline cycles_t cycles_diff(cycles_t then, cycles_t now)
{
return now >= then ? now - then : (CYCLES_MAX - then) + now;
}
#define irq_enable() ml_int_enable()
#define irq_disable() ml_int_disable()
extern void preempt_disable(void);
extern void preempt_enable(void);
extern int preempt_count(void);
extern unsigned int cpu_get_highest_available(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,49 +0,0 @@
#ifndef MANGO_FB_H_
#define MANGO_FB_H_
#include <stdint.h>
enum framebuffer_flags {
FB_MODE_RGB = 0x01u,
FB_MODE_VGATEXT = 0x02u,
FB_MODE_PALETTE = 0x04u,
};
struct framebuffer_bitfield {
uint32_t b_offset;
uint16_t b_length;
};
struct framebuffer_varinfo {
enum framebuffer_flags fb_flags;
uint32_t fb_xres;
uint32_t fb_yres;
uint32_t fb_bpp;
uint32_t fb_stride;
union {
struct {
uint32_t fb_xcells;
uint32_t fb_ycells;
};
struct {
struct framebuffer_bitfield fb_red;
struct framebuffer_bitfield fb_green;
struct framebuffer_bitfield fb_blue;
struct framebuffer_bitfield fb_alpha;
};
struct {
uintptr_t fb_palette_addr;
uint16_t fb_palette_nr_colours;
};
};
};
struct framebuffer_fixedinfo {
uint64_t fb_baseptr;
};
#endif

View File

@@ -1,11 +0,0 @@
#ifndef MANGO_FLAGS_H_
#define MANGO_FLAGS_H_
#include <stdint.h>
typedef enum {
S_NORMAL = 0x00u,
S_NOBLOCK = 0x01u,
} mango_flags_t;
#endif

View File

@@ -1,56 +0,0 @@
#ifndef MANGO_HANDLE_H_
#define MANGO_HANDLE_H_
#include <mango/bitmap.h>
#include <mango/status.h>
#include <stdint.h>
/* subtract 32 bytes to account for the handle bitmap */
#define HANDLES_PER_TABLE ((4096 - 32) / sizeof(struct handle))
#define REFS_PER_TABLE ((4096 - 64) / sizeof(struct handle_table *))
typedef uint32_t kern_handle_t;
struct object;
struct handle {
union {
struct object *h_object;
uint64_t __x;
};
uint64_t h_flags;
};
struct handle_table {
union {
struct {
/* bitmap tracks which bits in t_handle_list are
* allocated */
DECLARE_BITMAP(t_handle_map, HANDLES_PER_TABLE);
struct handle t_handle_list[HANDLES_PER_TABLE];
} t_handles;
struct {
/* bitmap tracks which sub-tables are fully-allocated */
DECLARE_BITMAP(t_subtable_map, REFS_PER_TABLE);
struct handle_table *t_subtable_list[REFS_PER_TABLE];
} t_subtables;
};
};
extern struct handle_table *handle_table_create(void);
extern void handle_table_destroy(struct handle_table *tab);
extern kern_status_t handle_table_alloc_handle(
struct handle_table *tab,
struct handle **out_slot,
kern_handle_t *out_handle);
extern void handle_table_free_handle(
struct handle_table *tab,
kern_handle_t handle);
extern struct handle *handle_table_get_handle(
struct handle_table *tab,
kern_handle_t handle);
#endif

View File

@@ -1,41 +0,0 @@
#ifndef MANGO_INIT_H_
#define MANGO_INIT_H_
#include <mango/compiler.h>
#include <mango/machine/init.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*initcall_t)(void);
#define INITLEVEL_EARLY 0
#define INITLEVEL_CORE 1
#define INITLEVEL_POSTCORE 2
#define INITLEVEL_ARCH 3
#define INITLEVEL_SUBSYS 4
#define INITLEVEL_ROOTFS 5
#define INITLEVEL_DEVICE 6
#define INITLEVEL_LATE 7
#define INITLEVEL_TESTS 8
#define early_initcall(fn) __define_initcall(fn, INITLEVEL_EARLY)
#define core_initcall(fn) __define_initcall(fn, INITLEVEL_CORE)
#define postcore_initcall(fn) __define_initcall(fn, INITLEVEL_POSTCORE)
#define arch_initcall(fn) __define_initcall(fn, INITLEVEL_ARCH)
#define subsys_initcall(fn) __define_initcall(fn, INITLEVEL_SUBSYS)
#define rootfs_initcall(fn) __define_initcall(fn, INITLEVEL_ROOTFS)
#define device_initcall(fn) __define_initcall(fn, INITLEVEL_DEVICE)
#define late_initcall(fn) __define_initcall(fn, INITLEVEL_LATE)
#define test_initcall(fn) __define_initcall(fn, INITLEVEL_TESTS)
extern void print_kernel_banner(void);
extern int do_initcalls(void);
extern int start_initlevel(int level);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,184 +0,0 @@
#ifndef MANGO_INPUT_H_
#define MANGO_INPUT_H_
#include <stdint.h>
#include <mango/queue.h>
#include <mango/status.h>
enum input_event_hook_flags {
INPUT_HOOK_SQUASH_EVENT = 0x01u,
};
struct device;
enum input_event_type {
INPUT_TYPE_UNKNOWN = 0x00u,
INPUT_TYPE_KEY = 0x01u,
INPUT_TYPE_MOTION = 0x02u,
};
enum input_event_motion_type {
INPUT_MOTION_TYPE_MOUSE = 0x01u,
INPUT_MOTION_TYPE_SCROLL = 0x02u,
};
enum input_keycode {
KEY_UNKNOWN = 0x00u,
KEY_A = 0x01u,
KEY_B = 0x02u,
KEY_C = 0x03u,
KEY_D = 0x04u,
KEY_E = 0x05u,
KEY_F = 0x06u,
KEY_G = 0x07u,
KEY_H = 0x08u,
KEY_I = 0x09u,
KEY_J = 0x0Au,
KEY_K = 0x0Bu,
KEY_L = 0x0Cu,
KEY_M = 0x0Du,
KEY_N = 0x0Eu,
KEY_O = 0x0Fu,
KEY_P = 0x10u,
KEY_Q = 0x11u,
KEY_R = 0x12u,
KEY_S = 0x13u,
KEY_T = 0x14u,
KEY_U = 0x15u,
KEY_V = 0x16u,
KEY_W = 0x17u,
KEY_X = 0x18u,
KEY_Y = 0x19u,
KEY_Z = 0x1Au,
KEY_KEY_1 = 0x1Bu,
KEY_KEY_2 = 0x1Cu,
KEY_KEY_3 = 0x1Du,
KEY_KEY_4 = 0x1Eu,
KEY_KEY_5 = 0x1Fu,
KEY_KEY_6 = 0x20u,
KEY_KEY_7 = 0x21u,
KEY_KEY_8 = 0x22u,
KEY_KEY_9 = 0x23u,
KEY_KEY_0 = 0x24u,
KEY_ENTER = 0x25u,
KEY_ESCAPE = 0x26u,
KEY_BACKSPACE = 0x27u,
KEY_TAB = 0x28u,
KEY_SPACE = 0x29u,
KEY_MINUS = 0x2Au,
KEY_EQUALS = 0x2Bu,
KEY_LEFT_BRACE = 0x2Cu,
KEY_RIGHT_BRACE = 0x2Du,
KEY_BACKSLASH = 0x2Eu,
KEY_NON_US_HASH = 0x2Fu,
KEY_SEMICOLON = 0x30u,
KEY_APOSTROPHE = 0x31u,
KEY_GRAVE_ACCENT = 0x32u,
KEY_COMMA = 0x33u,
KEY_DOT = 0x34u,
KEY_SLASH = 0x35u,
KEY_CAPS_LOCK = 0x36u,
KEY_F1 = 0x37u,
KEY_F2 = 0x38u,
KEY_F3 = 0x39u,
KEY_F4 = 0x3Au,
KEY_F5 = 0x3Bu,
KEY_F6 = 0x3Cu,
KEY_F7 = 0x3Du,
KEY_F8 = 0x3Eu,
KEY_F9 = 0x3Fu,
KEY_F10 = 0x40u,
KEY_F11 = 0x41u,
KEY_F12 = 0x42u,
KEY_PRINT_SCREEN = 0x43u,
KEY_SCROLL_LOCK = 0x44u,
KEY_PAUSE = 0x45u,
KEY_INSERT = 0x46u,
KEY_HOME = 0x47u,
KEY_PAGE_UP = 0x48u,
KEY_DELETE = 0x49u,
KEY_END = 0x4Au,
KEY_PAGE_DOWN = 0x4Bu,
KEY_RIGHT = 0x4Cu,
KEY_LEFT = 0x4Du,
KEY_DOWN = 0x4Eu,
KEY_UP = 0x4Fu,
KEY_NUM_LOCK = 0x50u,
KEY_KEYPAD_SLASH = 0x51u,
KEY_KEYPAD_ASTERISK = 0x52u,
KEY_KEYPAD_MINUS = 0x53u,
KEY_KEYPAD_PLUS = 0x54u,
KEY_KEYPAD_ENTER = 0x55u,
KEY_KEYPAD_1 = 0x56u,
KEY_KEYPAD_2 = 0x57u,
KEY_KEYPAD_3 = 0x58u,
KEY_KEYPAD_4 = 0x59u,
KEY_KEYPAD_5 = 0x5Au,
KEY_KEYPAD_6 = 0x5Bu,
KEY_KEYPAD_7 = 0x5Cu,
KEY_KEYPAD_8 = 0x5Du,
KEY_KEYPAD_9 = 0x5Eu,
KEY_KEYPAD_0 = 0x5Fu,
KEY_KEYPAD_DOT = 0x60u,
KEY_NON_US_BACKSLASH = 0x61u,
KEY_KEYPAD_EQUALS = 0x62u,
KEY_MENU = 0x63u,
KEY_LEFT_CTRL = 0x64u,
KEY_LEFT_SHIFT = 0x65u,
KEY_LEFT_ALT = 0x66u,
KEY_LEFT_META = 0x67u,
KEY_RIGHT_CTRL = 0x68u,
KEY_RIGHT_SHIFT = 0x69u,
KEY_RIGHT_ALT = 0x6Au,
KEY_RIGHT_META = 0x6Bu,
KEY_MEDIA_MUTE = 0x6Cu,
KEY_MEDIA_VOLUME_INCREMENT = 0x6Du,
KEY_MEDIA_VOLUME_DECREMENT = 0x6Eu,
};
enum input_key_state {
INPUT_KEYSTATE_DOWN = 0x00u,
INPUT_KEYSTATE_UP = 0x01u,
};
enum input_button {
INPUT_BUTTON_MOUSE_LEFT = 0x00u,
INPUT_BUTTON_MOUSE_MIDDLE = 0x01u,
INPUT_BUTTON_MOUSE_RIGHT = 0x02u,
INPUT_BUTTON_MOUSE_BACK = 0x03u,
INPUT_BUTTON_MOUSE_FORWARD = 0x04u,
};
enum input_button_state {
INPUT_BUTTON_DOWN = 0x00u,
INPUT_BUTTON_UP = 0x01u,
};
struct input_event {
enum input_event_type ev_type;
union {
struct {
enum input_event_motion_type type;
int16_t movement_x;
int16_t movement_y;
} ev_motion;
struct {
enum input_button button;
enum input_button_state state;
} ev_button;
struct {
enum input_keycode key;
enum input_key_state state;
} ev_key;
};
};
struct input_event_hook {
void(*hook_callback)(struct device *, struct input_event *, enum input_event_hook_flags *, void *);
void *hook_arg;
struct queue_entry hook_head;
};
#endif

View File

@@ -1,25 +0,0 @@
#ifndef MANGO_LOCKS_H_
#define MANGO_LOCKS_H_
#include <mango/compiler.h>
#include <mango/machine/hwlock.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef __aligned(8) ml_hwlock_t spin_lock_t;
#define SPIN_LOCK_INIT ML_HWLOCK_INIT
#define spin_lock(lck) ml_hwlock_lock(lck);
#define spin_unlock(lck) ml_hwlock_unlock(lck);
#define spin_lock_irqsave(lck, flags) ml_hwlock_lock_irqsave(lck, flags);
#define spin_unlock_irqrestore(lck, flags) ml_hwlock_unlock_irqrestore(lck, flags);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,345 +0,0 @@
/*
The Clear BSD License
Copyright (c) 2023 Max Wash
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the disclaimer
below) provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
*/
#ifndef MANGO_MEMBLOCK_H_
#define MANGO_MEMBLOCK_H_
#include <limits.h>
#include <mango/types.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MEMBLOCK_INIT_MEMORY_REGION_COUNT 128
#define MEMBLOCK_INIT_RESERVED_REGION_COUNT 128
#define __for_each_mem_range(i, type_a, type_b, p_start, p_end) \
for ((i)->__idx = 0, \
__next_memory_region(i, type_a, type_b, p_start, p_end); \
(i)->__idx != ULLONG_MAX; \
__next_memory_region(i, type_a, type_b, p_start, p_end))
/* iterate through all memory regions known to memblock.
this consists of all regions that have been registered
with memblock using memblock_add().
this iteration can be optionally constrained to a given region.
@param i the iterator. this should be a pointer of type struct memblock_iter.
for each iteration, this structure will be filled with details about
the current memory region.
@param p_start the lower bound of the memory region to iterate through.
if you don't want to use a lower bound, pass 0.
@param p_end the upper bound of the memory region to iterate through.
if you don't want to use an upper bound, pass UINTPTR_MAX.
EXAMPLE: to iterate through all memory regions (with no bounds):
struct memblock_iter it;
for_each_mem_region (&it, 0x0, UINTPTR_MAX) { ... }
EXAMPLE: to iterate through all memory regions between physical
addresses 0x40000 and 0x80000:
struct memblock_iter it;
for_each_mem_region (&it, 0x40000, 0x80000) { ... }
*/
#define for_each_mem_range(i, p_start, p_end) \
__for_each_mem_range(i, &memblock.memory, NULL, p_start, p_end)
/* iterate through all memory regions reserved using memblock.
this consists of all regions that have been registered
with memblock using memblock_reserve().
this iteration can be optionally constrained to a given region.
@param i the iterator. this should be a pointer of type struct memblock_iter.
for each iteration, this structure will be filled with details about
the current memory region.
@param p_start the lower bound of the memory region to iterate through.
if you don't want to use a lower bound, pass 0.
@param p_end the upper bound of the memory region to iterate through.
if you don't want to use an upper bound, pass UINTPTR_MAX.
EXAMPLE: to iterate through all reserved memory regions (with no bounds):
struct memblock_iter it;
for_each_reserved_mem_region (&it, 0x0, UINTPTR_MAX) { ... }
EXAMPLE: to iterate through all reserved memory regions between physical
addresses 0x40000 and 0x80000:
struct memblock_iter it;
for_each_reserved_mem_region (&it, 0x40000, 0x80000) { ... }
*/
#define for_each_reserved_mem_range(i, p_start, p_end) \
__for_each_mem_range(i, &memblock.reserved, NULL, p_start, p_end)
/* iterate through all memory regions known by memblock to be free.
this consists of all regions BETWEEN those regions that have been
registered using memblock_reserve(), bounded within the memory
regions added using memblock_add().
this iteration can be optionally constrained to a given region.
@param i the iterator. this should be a pointer of type struct memblock_iter.
for each iteration, this structure will be filled with details about
the current memory region.
@param p_start the lower bound of the memory region to iterate through.
if you don't want to use a lower bound, pass 0.
@param p_end the upper bound of the memory region to iterate through.
if you don't want to use an upper bound, pass UINTPTR_MAX.
EXAMPLE: if you have added the following memory regions to
memblock using memblock_add():
- 0x00000 -> 0x05fff
- 0x08000 -> 0x1ffff
...and you have reserved the following memory regions using
memblock_reserve():
- 0x01000 -> 0x04fff
- 0x09000 -> 0x0ffff
the following call:
struct memblock_iter it;
for_each_free_mem_range (&it, 0x0, UINTPTR_MAX) { ... }
would iterate through the following sequence of free memory ranges:
- 0x00000 -> 0x00fff
- 0x05000 -> 0x05fff
- 0x08000 -> 0x08fff
- 0x10000 -> 0x1ffff
*/
#define for_each_free_mem_range(i, p_start, p_end) \
__for_each_mem_range( \
i, \
&memblock.memory, \
&memblock.reserved, \
p_start, \
p_end)
typedef uint64_t memblock_index_t;
enum memblock_region_status {
/* Used in memblock.memory regions, indicates that the memory region
* exists */
MEMBLOCK_MEMORY = 0,
/* Used in memblock.reserved regions, indicates that the memory region
* was reserved by a call to memblock_alloc() */
MEMBLOCK_ALLOC,
/* Used in memblock.reserved regions, indicates that the memory region
* was reserved by a call to memblock_reserve() */
MEMBLOCK_RESERVED,
};
struct memblock_region {
/* the status of the memory region (free, reserved, allocated, etc) */
enum memblock_region_status status;
/* the address of the first byte that makes up the region */
phys_addr_t base;
/* the address of the last byte that makes up the region */
phys_addr_t limit;
};
/* buffer of memblock regions, all of which are the same type
(memory, reserved, etc) */
struct memblock_type {
struct memblock_region *regions;
unsigned int count;
unsigned int max;
const char *name;
};
struct memblock {
/* bounds of the memory region that can be used by memblock_alloc()
both of these are virtual addresses */
uintptr_t m_alloc_start, m_alloc_end;
/* memblock assumes that all memory in the alloc zone is contiguously
mapped (if paging is enabled). m_voffset is the offset that needs to
be added to a given physical address to get the corresponding virtual
address */
uintptr_t m_voffset;
struct memblock_type memory;
struct memblock_type reserved;
};
struct memblock_iter {
memblock_index_t __idx;
phys_addr_t it_base;
phys_addr_t it_limit;
enum memblock_region_status it_status;
};
/* global memblock state. */
extern struct memblock memblock;
extern int __next_mem_range(struct memblock_iter *it);
/* initialise the global memblock state.
this function must be called before any other memblock functions can be used.
this function sets the bounds of the heap area. memory allocation requests
using memblock_alloc() will be constrained to this zone.
memblock assumes that all physical memory in the system is mapped to
an area in virtual memory, such that converting a physical address to
a valid virtual address can be done by simply applying an offset.
@param alloc_start the virtual address of the start of the heap area.
@param alloc_end the virtual address of the end of the heap area.
@param voffset the offset between the physical address of a given page and
its corresponding virtual address.
*/
extern int memblock_init(
uintptr_t alloc_start,
uintptr_t alloc_end,
uintptr_t voffset);
/* add a region of memory to memblock.
this function is used to define regions of memory that are accessible, but
says nothing about the STATE of the given memory.
all memory is free by default. once a region of memory is added,
memblock_reserve() can be used to mark the memory as reserved.
@param base the physical address of the start of the memory region to add.
@oaram size the size of the memory region to add in bytes.
*/
extern int memblock_add(phys_addr_t base, size_t size);
/* mark a region of memory as reserved.
this function can only operate on regions of memory that have been previously
registered with memblock using memblock_add().
reserved memory will not be used by memblock_alloc(), and will remain
reserved when the vm_page memory map is initialised.
@param base the physical address of the start of the memory region to
reserve.
@oaram size the size of the memory region to reserve in bytes.
*/
extern int memblock_reserve(phys_addr_t base, size_t size);
/* allocate a block of memory, returning a virtual address.
this function selects the first available region of memory that satisfies
the requested allocation size, marks `size` bytes of this region as reserved,
and returns the virtual address of the region.
when looking for a suitable region of memory, this function searches the
intersection of the following memory zones:
- the regions of memory added with memblock_alloc().
- the region of memory specified as the heap bounds during the call
to memblock_init().
and excludes the following regions:
- the regions of memory marked as reserved by memblock_reserve() and
previous calls to memblock_alloc()
@param size the size of the buffer to allocate in bytes.
@param align the alignment to use. for example, an alignment of 4096
will result in the returned pointer being a multiple
of 4096. this must be a power of 2.
*/
extern void *memblock_alloc(size_t size, phys_addr_t align);
/* allocate a block of memory, returning a physical address.
this function selects the first available region of memory that satisfies
the requested allocation size, marks `size` bytes of this region as reserved,
and returns the virtual address of the region.
when looking for a suitable region of memory, this function searches the
intersection of the following memory zones:
- the regions of memory added with memblock_alloc().
- the region of memory specified as the heap bounds during the call
to memblock_init().
and excludes the following regions:
- the regions of memory marked as reserved by memblock_reserve() and
previous calls to memblock_alloc()
@param size the size of the buffer to allocate in bytes.
@param align the alignment to use. for example, an alignment of 4096
will result in the returned pointer being a multiple
of 4096. this must be a power of 2.
*/
extern phys_addr_t memblock_alloc_phys(size_t size, phys_addr_t align);
/* free a block of memory using its virtual address.
due to limitations in memblock (as it is meant to be a simple,
early-boot allocator), you must specify the size of the memory
region you intend to free.
@param addr the virtual address of the region to free.
@param size the size of the region to free in bytes.
*/
extern int memblock_free(void *addr, size_t size);
/* free a block of memory using its physical address.
due to limitations in memblock (as it is meant to be a simple,
early-boot allocator), you must specify the size of the memory
region you intend to free.
@param addr the physical address of the region to free.
@param size the size of the region to free in bytes.
*/
extern int memblock_free_phys(phys_addr_t addr, size_t size);
/* convert a virtual pointer returned by memblock
to a physical address.
@param p the pointer to convert.
*/
extern phys_addr_t memblock_virt_to_phys(const void *p);
/* convert a physical address returned by memblock
to a virtual pointer.
@param p the address to convert.
*/
extern void *memblock_phys_to_virt(phys_addr_t p);
extern void __next_memory_region(
struct memblock_iter *it,
struct memblock_type *type_a,
struct memblock_type *type_b,
phys_addr_t start,
phys_addr_t end);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,95 +0,0 @@
#ifndef MANGO_OBJECT_H_
#define MANGO_OBJECT_H_
#include <mango/flags.h>
#include <mango/locks.h>
#include <mango/status.h>
#include <mango/vm.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DEFINE_OBJECT_LOCK_FUNCTION(object_name, base) \
static inline void object_name##_lock(struct object_name *p) \
{ \
object_lock(&p->base); \
} \
static inline void object_name##_unlock(struct object_name *p) \
{ \
object_unlock(&p->base); \
} \
static inline void object_name##_lock_irqsave( \
struct object_name *p, \
unsigned long *flags) \
{ \
object_lock_irqsave(&p->base, flags); \
} \
static inline void object_name##_unlock_irqrestore( \
struct object_name *p, \
unsigned long flags) \
{ \
object_unlock_irqrestore(&p->base, flags); \
}
#define OBJECT_MAGIC 0xBADDCAFE
#define OBJECT_NAME_MAX 64
#define OBJECT_PATH_MAX 256
#define OBJECT_CAST(to_type, to_type_member, p) \
((to_type *)((uintptr_t)p) - offsetof(to_type, to_type_member))
#define OBJECT_C_CAST(c_type, c_type_member, obj_type, objp) \
OBJECT_IS_TYPE(objp, obj_type) \
? OBJECT_CAST(c_type, c_type_member, (objp)) : NULL
#define OBJECT_IS_TYPE(obj, type_ptr) ((obj)->ob_type == (type_ptr))
struct object;
struct object_attrib;
enum object_type_flags {
OBJTYPE_INIT = 0x01u,
};
struct object_ops {
kern_status_t (*destroy)(struct object *obj);
};
struct object_type {
enum object_type_flags ob_flags;
char ob_name[32];
unsigned int ob_size;
unsigned int ob_header_offset;
struct vm_cache ob_cache;
struct queue_entry ob_list;
struct object_ops ob_ops;
};
struct object {
uint32_t ob_magic;
struct object_type *ob_type;
spin_lock_t ob_lock;
unsigned int ob_refcount;
unsigned int ob_handles;
struct queue_entry ob_list;
} __aligned(sizeof(long));
extern kern_status_t object_bootstrap(void);
extern kern_status_t object_type_register(struct object_type *p);
extern kern_status_t object_type_unregister(struct object_type *p);
extern struct object *object_create(struct object_type *type);
extern struct object *object_ref(struct object *obj);
extern void object_unref(struct object *obj);
extern void object_add_handle(struct object *obj);
extern void object_remove_handle(struct object *obj);
extern void object_lock(struct object *obj);
extern void object_unlock(struct object *obj);
extern void object_lock_irqsave(struct object *obj, unsigned long *flags);
extern void object_unlock_irqrestore(struct object *obj, unsigned long flags);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,13 +0,0 @@
#ifndef MANGO_PANIC_H_
#define MANGO_PANIC_H_
#include <mango/compiler.h>
struct ml_cpu_context;
#define panic(...) panic_irq(NULL, __VA_ARGS__)
extern void __noreturn
panic_irq(struct ml_cpu_context *ctx, const char *fmt, ...);
#endif

View File

@@ -1,36 +0,0 @@
#ifndef MANGO_PERCPU_H_
#define MANGO_PERCPU_H_
#include <mango/status.h>
#include <mango/compiler.h>
#include <mango/sched.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DEFINE_PERCPU_VAR(type, name) \
__section(".data.percpu") type name
#define percpu_get(var) \
__extension__({ \
preempt_disable(); \
__percpu_get(this_cpu(), var); \
})
#define percpu_get_from(cpu, var) \
__extension__({ \
preempt_disable(); \
__percpu_get(cpu, var); \
})
#define percpu_put(var) preempt_enable();
extern kern_status_t init_per_cpu_areas(void);
extern void *__percpu_get(unsigned int cpu, void *var);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,81 +0,0 @@
#ifndef MANGO_PMAP_H_
#define MANGO_PMAP_H_
/* all the functions declared in this file are defined in arch/xyz/pmap.c */
#include <mango/machine/pmap.h>
#include <mango/status.h>
#include <mango/vm.h>
#include <stddef.h>
#define PMAP_INVALID ML_PMAP_INVALID
#define PFN(x) ((x) >> VM_PAGE_SHIFT)
#ifdef __cplusplus
extern "C" {
#endif
typedef ml_pmap_t pmap_t;
typedef ml_pfn_t pfn_t;
enum pmap_fault_flags {
/* if set, the faulting page is present, and the fault is
* protection-related.
* if clear, the faulting page is missing, and the
* fault is due to the missing page.
*/
PMAP_FAULT_PRESENT = 0x01u,
/* if set, the faulting page was accessed from user mode.
* if clear, the faulting page was accessed from kernel mode.
*/
PMAP_FAULT_USER = 0x02u,
/* if set, the fault was caused by a write operation.
* if clear, the faulting page was caused by a read operation.
*/
PMAP_FAULT_WRITE = 0x04u,
/* if set, the fault was caused while fetching an instruction from the
* faulting page.
*/
PMAP_FAULT_IFETCH = 0x08u,
/* if set, the fault was caused by misconfigured page tables */
PMAP_FAULT_BADCFG = 0x10u,
};
enum pmap_flags {
PMAP_NORMAL = 0x00u,
PMAP_HUGEPAGE = 0x01u,
};
extern void pmap_bootstrap(void);
extern pmap_t get_kernel_pmap(void);
extern pmap_t pmap_create(void);
extern void pmap_destroy(pmap_t pmap);
extern void pmap_switch(pmap_t pmap);
extern kern_status_t pmap_handle_fault(
virt_addr_t fault_addr,
enum pmap_fault_flags flags);
extern kern_status_t pmap_add(
pmap_t pmap,
virt_addr_t p,
pfn_t pfn,
enum vm_prot prot,
enum pmap_flags flags);
extern kern_status_t pmap_add_block(
pmap_t pmap,
virt_addr_t p,
pfn_t pfn,
size_t len,
enum vm_prot prot,
enum pmap_flags flags);
extern kern_status_t pmap_remove(pmap_t pmap, void *p);
extern kern_status_t pmap_remove_range(pmap_t pmap, void *p, size_t len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,23 +0,0 @@
#ifndef MANGO_PRINTK_H_
#define MANGO_PRINTK_H_
#include <mango/console.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef TRACE
#define tracek(...) printk(__VA_ARGS__)
#else
#define tracek(...)
#endif
extern void early_printk_init(struct console *con);
extern int printk(const char *format, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,62 +0,0 @@
#ifndef MANGO_QUEUE_H_
#define MANGO_QUEUE_H_
#include <mango/libc/string.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define QUEUE_CONTAINER(t, m, v) ((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
#define QUEUE_INIT ((struct queue){ .q_first = NULL, .q_last = NULL })
#define QUEUE_ENTRY_INIT ((struct queue_entry){ .qe_next = NULL, .qe_prev = NULL })
#define queue_foreach(iter_type, iter_name, queue_name, node_member) \
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER(iter_type, node_member, queue_first(queue_name)); \
iter_name; \
iter_name = (iter_type *)QUEUE_CONTAINER(iter_type, node_member, queue_next(&((iter_name)->node_member))))
#define queue_foreach_r(iter_type, iter_name, queue_name, node_member) \
for (iter_type *iter_name = (iter_type *)QUEUE_CONTAINER(iter_type, node_member, queue_last(queue_name)); \
iter_name; \
iter_name = (iter_type *)QUEUE_CONTAINER(iter_type, node_member, queue_prev(&((iter_name)->node_member))))
struct queue_entry {
struct queue_entry *qe_next;
struct queue_entry *qe_prev;
};
struct queue {
struct queue_entry *q_first;
struct queue_entry *q_last;
};
static inline void queue_init(struct queue *q) { memset(q, 0x00, sizeof *q); }
static inline bool queue_empty(struct queue *q) { return q->q_first == NULL; }
static inline struct queue_entry *queue_first(struct queue *q) { return q->q_first; }
static inline struct queue_entry *queue_last(struct queue *q) { return q->q_last; }
static inline struct queue_entry *queue_next(struct queue_entry *entry) { return entry->qe_next; }
static inline struct queue_entry *queue_prev(struct queue_entry *entry) { return entry->qe_prev; }
extern size_t queue_length(struct queue *q);
extern void queue_insert_before(struct queue *q, struct queue_entry *entry, struct queue_entry *before);
extern void queue_insert_after(struct queue *q, struct queue_entry *entry, struct queue_entry *after);
extern void queue_push_front(struct queue *q, struct queue_entry *entry);
extern void queue_push_back(struct queue *q, struct queue_entry *entry);
extern struct queue_entry *queue_pop_front(struct queue *q);
extern struct queue_entry *queue_pop_back(struct queue *q);
extern void queue_delete(struct queue *q, struct queue_entry *entry);
extern void queue_delete_all(struct queue *q);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,34 +0,0 @@
#ifndef MANGO_RINGBUFFER_H_
#define MANGO_RINGBUFFER_H_
#include <mango/locks.h>
#include <mango/sched.h>
struct ringbuffer {
unsigned char *r_buffer;
size_t r_write_ptr;
size_t r_read_ptr;
size_t r_size;
spin_lock_t r_lock;
struct waitqueue r_wait_readers;
struct waitqueue r_wait_writers;
};
extern struct ringbuffer *ringbuffer_create(size_t size);
extern void ringbuffer_destroy(struct ringbuffer *buf);
extern kern_status_t ringbuffer_init(struct ringbuffer *buf, size_t size);
extern kern_status_t ringbuffer_deinit(struct ringbuffer *buf);
extern size_t ringbuffer_unread(struct ringbuffer *buf);
extern size_t ringbuffer_avail(struct ringbuffer *buf);
extern size_t ringbuffer_read(struct ringbuffer *buf, size_t size, void *buffer, mango_flags_t flags);
extern size_t ringbuffer_write(struct ringbuffer *buf, size_t size, const void *buffer, mango_flags_t flags);
/* TODO */
//extern size_t ringbuffer_peek(struct ringbuffer *buf, size_t at, size_t size, void *buffer);
//extern size_t ringbuffer_skip(struct ringbuffer *buf, size_t count);
extern int ringbuffer_write_would_block(struct ringbuffer *buf);
#endif

View File

@@ -1,250 +0,0 @@
#ifndef MANGO_SCHED_H_
#define MANGO_SCHED_H_
#include <mango/btree.h>
#include <mango/locks.h>
#include <mango/object.h>
#include <mango/pmap.h>
#include <mango/queue.h>
#include <mango/status.h>
#define TASK_NAME_MAX 64
#define PRIO_MAX 32
#define PID_MAX 99999
#define THREAD_KSTACK_ORDER VM_PAGE_4K
#define THREAD_MAX 65536
#define wait_event(wq, cond) \
({ \
struct thread *self = current_thread(); \
struct wait_item waiter; \
wait_item_init(&waiter, self); \
for (;;) { \
thread_wait_begin(&waiter, wq); \
if (cond) { \
break; \
} \
schedule(SCHED_NORMAL); \
} \
thread_wait_end(&waiter, wq); \
})
#ifdef __cplusplus
extern "C" {
#endif
struct runqueue;
struct work_item;
enum task_state {
TASK_RUNNING,
TASK_STOPPED,
};
enum thread_state {
THREAD_READY = 1,
THREAD_SLEEPING = 2,
THREAD_STOPPED = 3,
};
enum thread_flags {
THREAD_F_NEED_RESCHED = 0x01u,
THREAD_F_NO_PREEMPT = 0x02u,
};
enum sched_priority {
PRIO_IDLE = 4,
PRIO_SUBNORMAL = 6,
PRIO_NORMAL = 10,
PRIO_SUPERNORMAL = 14,
PRIO_HIGH = 18,
PRIO_REALTIME = 24,
};
enum sched_mode {
/* used when calling from non-interrupt context.
threads that aren't in state THREAD_READY are
removed from the runqueue. */
SCHED_NORMAL = 0,
/* used when calling from interrupt context.
threads that aren't in state THREAD_READY are
still added to the runqueue. */
SCHED_IRQ = 1,
};
struct task {
struct object t_base;
struct task *t_parent;
long t_id;
enum task_state t_state;
char t_name[TASK_NAME_MAX];
pmap_t t_pmap;
struct vm_region *t_address_space;
struct handle_table *t_handles;
struct btree_node t_tasklist;
struct queue_entry t_child_entry;
size_t t_next_thread_id;
struct queue t_threads;
struct queue t_children;
};
struct thread {
struct object thr_base;
enum thread_state tr_state;
enum thread_flags tr_flags;
struct task *tr_parent;
unsigned int tr_id;
unsigned int tr_prio;
cycles_t tr_charge_period_start;
cycles_t tr_quantum_cycles, tr_quantum_target;
cycles_t tr_total_cycles;
virt_addr_t tr_ip, tr_sp, tr_bp;
virt_addr_t tr_cpu_user_sp, tr_cpu_kernel_sp;
struct runqueue *tr_rq;
struct queue_entry tr_parent_entry;
struct queue_entry tr_rqentry;
struct vm_page *tr_kstack;
struct vm_object *tr_ustack;
};
struct runqueue {
struct queue rq_queues[PRIO_MAX];
uint32_t rq_readybits;
spin_lock_t rq_lock;
unsigned int rq_nthreads;
struct thread *rq_cur, *rq_idle;
};
struct timer {
struct queue_entry t_entry;
struct cpu_data *t_cpu;
struct thread *t_owner;
unsigned long t_expiry;
void (*t_callback)(struct timer *);
};
struct wait_item {
struct thread *w_thread;
struct queue_entry w_entry;
};
struct waitqueue {
struct queue wq_waiters;
spin_lock_t wq_lock;
};
typedef void (*work_func_t)(struct work_item *);
struct work_item {
void *w_data;
work_func_t w_func;
struct queue_entry w_head;
};
struct worker_pool {
struct thread **wp_workers;
size_t wp_nworkers;
};
struct workqueue {
spin_lock_t wq_lock;
struct queue wq_queue; /* list of struct work_item */
};
extern kern_status_t sched_init(void);
extern void schedule(enum sched_mode mode);
extern void preempt_disable(void);
extern void preempt_enable(void);
extern void rq_init(struct runqueue *rq);
extern struct thread *rq_dequeue(struct runqueue *rq);
extern void rq_enqueue(struct runqueue *rq, struct thread *thr);
static inline void rq_lock(struct runqueue *rq, unsigned long *flags)
{
spin_lock_irqsave(&rq->rq_lock, flags);
}
static inline void rq_unlock(struct runqueue *rq, unsigned long flags)
{
spin_unlock_irqrestore(&rq->rq_lock, flags);
}
extern void rq_remove_thread(struct runqueue *rq, struct thread *thr);
extern struct runqueue *cpu_rq(unsigned int cpu);
extern struct task *task_alloc(void);
extern struct task *task_create(struct task *parent, const char *name);
static inline struct task *task_ref(struct task *task)
{
return OBJECT_CAST(struct task, t_base, object_ref(&task->t_base));
}
static inline void task_unref(struct task *task)
{
object_unref(&task->t_base);
}
extern struct task *task_from_pid(unsigned int pid);
extern struct thread *task_create_thread(struct task *parent);
extern struct task *kernel_task(void);
extern struct task *idle_task(void);
extern cycles_t default_quantum(void);
extern bool need_resched(void);
extern struct task *current_task(void);
extern struct thread *current_thread(void);
extern struct runqueue *select_rq_for_thread(struct thread *thr);
extern void schedule_thread_on_cpu(struct thread *thr);
extern void start_charge_period(void);
extern void end_charge_period(void);
DEFINE_OBJECT_LOCK_FUNCTION(task, t_base)
extern struct thread *thread_alloc(void);
extern kern_status_t thread_init_kernel(struct thread *thr, virt_addr_t ip);
extern kern_status_t thread_init_user(
struct thread *thr,
virt_addr_t ip,
virt_addr_t sp);
extern int thread_priority(struct thread *thr);
extern void idle(void);
extern struct thread *create_kernel_thread(void (*fn)(void));
extern struct thread *create_idle_thread(void);
extern void add_timer(struct timer *timer);
extern void remove_timer(struct timer *timer);
extern unsigned long schedule_timeout(unsigned long clock_ticks);
extern unsigned long milli_sleep(unsigned long ms);
extern void sleep_forever(void);
extern void wait_item_init(struct wait_item *item, struct thread *thr);
extern void thread_wait_begin(struct wait_item *waiter, struct waitqueue *q);
extern void thread_wait_end(struct wait_item *waiter, struct waitqueue *q);
extern void wait_on_queue(struct waitqueue *q);
extern void wakeup_queue(struct waitqueue *q);
extern void wakeup_one(struct waitqueue *q);
extern void work_item_init(work_func_t func, void *data, struct work_item *out);
extern void workqueue_init(struct workqueue *wq);
extern struct worker_pool *worker_pool_create(size_t nworkers);
extern struct worker_pool *global_worker_pool(void);
extern bool schedule_work_on(struct workqueue *wq, struct work_item *work);
extern bool schedule_work(struct work_item *work);
extern void wake_workers(struct workqueue *wq, struct worker_pool *pool);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,20 +0,0 @@
#ifndef MANGO_SYSCALL_H_
#define MANGO_SYSCALL_H_
#include <mango/handle.h>
#include <mango/status.h>
#include <mango/vm.h>
#define SYS_EXIT 1
#define SYS_VM_OBJECT_CREATE 2
extern kern_status_t sys_exit(int status);
extern kern_status_t sys_vm_object_create(
const char *name,
size_t len,
enum vm_prot prot,
kern_handle_t *out_handle);
extern virt_addr_t syscall_get_function(unsigned int sysid);
#endif

View File

@@ -1,14 +0,0 @@
#ifndef MANGO_TEST_H_
#define MANGO_TEST_H_
#ifdef __cplusplus
extern "C" {
#endif
extern int run_all_tests(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,22 +0,0 @@
#ifndef MANGO_TYPES_H_
#define MANGO_TYPES_H_
#include <stddef.h>
#include <stdint.h>
#define CYCLES_MAX UINT64_MAX
typedef uintptr_t phys_addr_t;
typedef uintptr_t virt_addr_t;
typedef uint64_t cycles_t;
typedef uint64_t sectors_t;
typedef uint64_t off_t;
typedef unsigned int umode_t;
struct boot_module {
phys_addr_t mod_base;
size_t mod_size;
};
#endif

View File

@@ -1,69 +0,0 @@
#ifndef MANGO_UTIL_H_
#define MANGO_UTIL_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define CLAMP(x, lo, hi) (MIN(MAX(x, lo), hi))
extern uint64_t hash_string(const char *s);
extern void data_size_to_string(size_t value, char *out, size_t outsz);
static inline bool power_of_2(size_t x)
{
return (x > 0 && (x & (x - 1)) == 0);
}
static inline unsigned long long div64_pow2(
unsigned long long x,
unsigned long long y)
{
return x >> (__builtin_ctz(y));
}
static inline unsigned long long absdiff64(
unsigned long long x,
unsigned long long y)
{
return x < y ? y - x : x - y;
}
extern int16_t host_to_big_i16(int16_t v);
extern int16_t host_to_little_i16(int16_t v);
extern int16_t big_to_host_i16(int16_t v);
extern int16_t little_to_host_i16(int16_t v);
extern uint16_t host_to_big_u16(uint16_t v);
extern uint16_t host_to_little_u16(uint16_t v);
extern uint16_t big_to_host_u16(uint16_t v);
extern uint16_t little_to_host_u16(uint16_t v);
extern int32_t host_to_big_i32(int32_t v);
extern int32_t host_to_little_i32(int32_t v);
extern int32_t big_to_host_i32(int32_t v);
extern int32_t little_to_host_i32(int32_t v);
extern uint32_t host_to_big_u32(uint32_t v);
extern uint32_t host_to_little_u32(uint32_t v);
extern uint32_t big_to_host_u32(uint32_t v);
extern uint32_t little_to_host_u32(uint32_t v);
extern int64_t host_to_big_i64(int64_t v);
extern int64_t host_to_little_i64(int64_t v);
extern int64_t big_to_host_i64(int64_t v);
extern int64_t little_to_host_i64(int64_t v);
extern uint64_t host_to_big_u64(uint64_t v);
extern uint64_t host_to_little_u64(uint64_t v);
extern uint64_t big_to_host_u64(uint64_t v);
extern uint64_t little_to_host_u64(uint64_t v);
extern bool fill_random(void *buffer, unsigned int size);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,68 +0,0 @@
#ifndef MANGO_VM_OBJECT_H_
#define MANGO_VM_OBJECT_H_
#include <mango/locks.h>
#include <mango/object.h>
#define VM_OBJECT_NAME_MAX 64
enum vm_object_flags {
/* the memory behind this vm-object wasn't allocated by us, and
* therefore shouldn't be freed by us */
VMO_IN_PLACE = 0x01u,
};
struct vm_object {
struct object vo_base;
char vo_name[VM_OBJECT_NAME_MAX];
enum vm_object_flags vo_flags;
/* queue of struct vm_region_mapping */
struct queue vo_mappings;
/* memory protection flags. mappings of this vm_object can only use
* a subset of the flags set in this mask. */
enum vm_prot vo_prot;
/* btree of vm_pages that have been allocated to this vm_object.
* vm_page->p_vmo_offset and the size of each page is the bst key. */
struct btree vo_pages;
/* total length of the vm_object in bytes. */
size_t vo_size;
};
extern kern_status_t vm_object_type_init(void);
/* create a vm_object with the specified length in bytes and protection flags.
* the length will be automatically rounded up to the nearest vm_object page
* order size. the actual page frames themselves won't be allocated until
* they are mapped and accessed. */
extern struct vm_object *vm_object_create(
const char *name,
size_t len,
enum vm_prot prot);
/* create a vm_object that represents the specified range of physical memory.
* the length will be automatically rounded up to the nearest vm_object page
* order size.
* NOTE this function assumes that the physical memory has already been
* reserved, and is not in use by any other kernel component. */
extern struct vm_object *vm_object_create_in_place(
const char *name,
phys_addr_t base,
size_t len,
enum vm_prot prot);
extern struct vm_page *vm_object_get_page(
const struct vm_object *vo,
off_t offset);
extern struct vm_page *vm_object_alloc_page(
struct vm_object *vo,
off_t offset,
enum vm_page_order size);
DEFINE_OBJECT_LOCK_FUNCTION(vm_object, vo_base)
#endif

View File

@@ -1,115 +0,0 @@
#ifndef MANGO_VM_REGION_H_
#define MANGO_VM_REGION_H_
#include <mango/object.h>
#include <mango/pmap.h>
#include <mango/vm.h>
#define VM_REGION_NAME_MAX 64
#define VM_REGION_ANY_OFFSET ((off_t) - 1)
struct vm_region;
struct vm_object;
enum vm_region_entry_type {
VM_REGION_ENTRY_NONE = 0,
VM_REGION_ENTRY_REGION,
VM_REGION_ENTRY_MAPPING,
};
struct vm_region_entry {
struct btree_node e_node;
struct vm_region_entry *e_parent;
enum vm_region_entry_type e_type;
/* offset in bytes of this entry within its immediate parent. */
off_t e_offset;
/* size of the entry in bytes */
size_t e_size;
};
struct vm_region_mapping {
struct vm_region_entry m_entry;
struct vm_object *m_object;
/* used to link to vm_object->vo_mappings */
struct queue_entry m_object_entry;
enum vm_prot m_prot;
/* offset in bytes to the start of the object data that was mapped */
off_t m_object_offset;
};
struct vm_region {
struct object vr_base;
struct vm_region_entry vr_entry;
char vr_name[VM_REGION_NAME_MAX];
/* btree of struct vm_region_entry.
* sibling entries cannot overlap each other, and child entries must
* be entirely contained within their immediate parent entry. */
struct btree vr_entries;
/* memory protection restriction mask.
* any mapping in this region, or any of its children, cannot use
* protection flags that are not set in this mask.
* for example, if VM_PROT_EXEC is /not/ set here, no mapping
* can be created in this region or any child region with VM_PROT_EXEC
* set. */
enum vm_prot vr_prot;
/* the physical address space in which mappings in this region (and
* its children) are created */
pmap_t vr_pmap;
};
extern kern_status_t vm_region_type_init(void);
/* create a new vm-region, optionally within a parent region.
* `offset` is the byte offset within the parent region where the new region
* should start.
* if no parent is specified, `offset` is the absolute virtual address of the
* start of the region.
* in both cases, `len` is the length of the new region in bytes. */
extern kern_status_t vm_region_create(
struct vm_region *parent,
const char *name,
off_t offset,
size_t len,
enum vm_prot prot,
struct vm_region **out);
/* map a vm-object into a vm-region.
* [region_offset,length] must fall within exactly one region, and cannot span
* multiple sibling regions.
* if [region_offset,length] falls within a child region, the map operation
* will be transparently redirected to the relevant region.
* `prot` must be allowed both by the region into which the mapping is being
* created AND the vm-object being mapped. */
extern kern_status_t vm_region_map_object(
struct vm_region *region,
off_t region_offset,
struct vm_object *object,
off_t object_offset,
size_t length,
enum vm_prot prot,
virt_addr_t *out);
/* find the mapping corresponding to the given virtual address, and page-in the
* necessary vm_page to allow the memory access to succeed. if the relevant
* vm-object page hasn't been allocated yet, it will be allocated here. */
extern kern_status_t vm_region_demand_map(
struct vm_region *region,
virt_addr_t addr,
enum pmap_fault_flags flags);
/* get the absolute base virtual address of a region within its
* parent/ancestors. */
extern virt_addr_t vm_region_get_base_address(const struct vm_region *region);
extern void vm_region_dump(struct vm_region *region, int depth);
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
#endif

View File

@@ -1,367 +0,0 @@
#ifndef MANGO_VM_H_
#define MANGO_VM_H_
#include <mango/bitmap.h>
#include <mango/btree.h>
#include <mango/locks.h>
#include <mango/machine/vm.h>
#include <mango/queue.h>
#include <mango/status.h>
#include <mango/types.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
struct bcache;
/* maximum number of NUMA nodes */
#define VM_MAX_NODES 64
/* maximum number of memory zones per node */
#define VM_MAX_ZONES (VM_ZONE_MAX + 1)
/* maximum number of supported page orders */
#define VM_MAX_PAGE_ORDERS (VM_PAGE_MAX_ORDER + 1)
/* maximum number of sparse memory sectors */
#define VM_MAX_SECTORS 8192
/* maximum number of disk sectors that can be stored in a single
page. AKA the number of bits in the sector bitmap.
used by the block cache */
#define VM_MAX_SECTORS_PER_PAGE 32
#define VM_CHECK_ALIGN(p, mask) ((((p) & (mask)) == (p)) ? 1 : 0)
#define VM_CACHE_INITIALISED(c) ((c)->c_obj_count != 0)
#define VM_PAGE_IS_FREE(pg) \
(((pg)->p_flags & (VM_PAGE_RESERVED | VM_PAGE_ALLOC)) == 0)
#define vm_page_foreach(pg, i) \
for (struct vm_page *i = (pg); i; i = vm_page_get_next_tail(i))
typedef phys_addr_t vm_alignment_t;
typedef unsigned int vm_node_id_t;
enum vm_model {
VM_MODEL_FLAT = 1,
VM_MODEL_SPARSE,
};
enum vm_prot {
VM_PROT_READ = 0x01u,
VM_PROT_WRITE = 0x02u,
VM_PROT_EXEC = 0x04u,
VM_PROT_USER = 0x08u,
VM_PROT_SVR = 0x10u,
VM_PROT_NOCACHE = 0x20u,
};
enum vm_flags {
VM_NORMAL = 0x00u,
VM_GET_DMA = 0x01u,
};
enum vm_zone_id {
/* NOTE that these are used as indices into the node_zones array in
vm/zone.c they need to be continuous, and must start at 0!
not all of these zones are implemented for every architecture. */
VM_ZONE_DMA = 0u,
VM_ZONE_NORMAL = 1u,
VM_ZONE_HIGHMEM = 2u,
};
enum vm_page_order {
VM_PAGE_4K = 0u,
VM_PAGE_8K,
VM_PAGE_16K,
VM_PAGE_32K,
VM_PAGE_64K,
VM_PAGE_128K,
VM_PAGE_256K,
VM_PAGE_512K,
VM_PAGE_1M,
VM_PAGE_2M,
VM_PAGE_4M,
VM_PAGE_8M,
VM_PAGE_16M,
VM_PAGE_32M,
VM_PAGE_64M,
VM_PAGE_128M,
/* struct vm_page only has 4 bits to store the page order with.
the maximum order that can be stored in 4 bits is 15 (VM_PAGE_128M)
to use any of the page orders listed here, this field
will have to be expanded. */
VM_PAGE_256M,
VM_PAGE_512M,
VM_PAGE_1G,
VM_PAGE_2G,
VM_PAGE_4G,
VM_PAGE_8G,
VM_PAGE_16G,
VM_PAGE_32G,
VM_PAGE_64G,
};
enum vm_page_flags {
/* page is reserved (probably by a call to memblock_reserve()) and
cannot be returned by any allocation function */
VM_PAGE_RESERVED = 0x01u,
/* page has been allocated by a zone's buddy allocator, and is in-use */
VM_PAGE_ALLOC = 0x02u,
/* page is the first page of a huge-page */
VM_PAGE_HEAD = 0x04u,
/* page is part of a huge-page */
VM_PAGE_HUGE = 0x08u,
/* page is holding cached data from secondary storage, and can be freed
* if necessary (and not dirty). */
VM_PAGE_CACHE = 0x10u,
};
enum vm_memory_region_status {
VM_REGION_FREE = 0x01u,
VM_REGION_RESERVED = 0x02u,
};
enum vm_cache_flags {
VM_CACHE_OFFSLAB = 0x01u,
VM_CACHE_DMA = 0x02u
};
struct vm_zone_descriptor {
enum vm_zone_id zd_id;
vm_node_id_t zd_node;
const char zd_name[32];
phys_addr_t zd_base;
phys_addr_t zd_limit;
};
struct vm_zone {
struct vm_zone_descriptor z_info;
spin_lock_t z_lock;
struct queue z_free_pages[VM_MAX_PAGE_ORDERS];
unsigned long z_size;
};
struct vm_pg_data {
struct vm_zone pg_zones[VM_MAX_ZONES];
};
struct vm_cache {
const char *c_name;
enum vm_cache_flags c_flags;
struct queue_entry c_list;
struct queue c_slabs_full;
struct queue c_slabs_partial;
struct queue c_slabs_empty;
spin_lock_t c_lock;
/* number of objects that can be stored in a single slab */
unsigned int c_obj_count;
/* the size of object kept in the cache */
unsigned int c_obj_size;
/* combined size of struct vm_slab and the freelist */
unsigned int c_hdr_size;
/* power of 2 alignment for objects returned from the cache */
unsigned int c_align;
/* offset from one object to the next in a slab.
this may be different from c_obj_size depending
on the alignment settings for this cache. */
unsigned int c_stride;
/* size of page used for slabs */
unsigned int c_page_order;
};
struct vm_slab {
struct vm_cache *s_cache;
/* queue entry for struct vm_cache.c_slabs_* */
struct queue_entry s_list;
/* pointer to the first object slot. */
void *s_objects;
/* the number of objects allocated on the slab. */
unsigned int s_obj_allocated;
/* the index of the next free object.
if s_free is equal to FREELIST_END (defined in vm/cache.c)
there are no free slots left in the slab. */
unsigned int s_free;
/* list of free object slots.
when allocating:
- s_free should be set to the value of s_freelist[s_free]
when freeing:
- s_free should be set to the index of the object being freed.
- s_freelist[s_free] should be set to the previous value of s_free.
this is commented as it as flexible arrays are not supported in c++.
*/
// unsigned int s_freelist[];
};
struct vm_page {
/* order of the page block that this page belongs too */
uint32_t p_order : 4;
/* the id of the NUMA node that this page belongs to */
uint32_t p_node : 6;
/* the id of the memory zone that this page belongs to */
uint32_t p_zone : 3;
/* vm_page_flags_t bitfields. */
uint32_t p_sector : 11;
/* some unused bits */
uint32_t p_reserved : 8;
uint32_t p_flags;
/* owner-specific pointer */
union {
struct vm_slab *p_slab;
struct bcache *p_bcache;
void *p_priv0;
};
/* multi-purpose list/tree entry.
the owner of the page can decide what to do with this.
some examples:
- the buddy allocator uses this to maintain its per-zone free-page
lists.
- vm_object uses it to maintain a btree of allocated pages keyed
by offset/size.
- the block cache uses this to maintain a tree of pages keyed by
block number.
*/
union {
struct queue_entry p_list;
struct btree_node p_bnode;
/* btree_node contains three pointers, so provide three
pointer-sized integers for use if p_bnode isn't needed. */
uintptr_t priv1[3];
};
union {
/* used by bcache when sector size is < page size. bitmap of
* present/missing sectors */
DECLARE_BITMAP(p_blockbits, VM_MAX_SECTORS_PER_PAGE);
uint32_t p_priv2;
};
union {
/* sector address, used by bcache */
sectors_t p_blockid;
/* offset of this page within the vm_object it is a part of */
off_t p_vmo_offset;
uint32_t p_priv3[2];
};
} __aligned(2 * sizeof(unsigned long));
/* represents a sector of memory, containing its own array of vm_pages.
this struct is used under the sparse memory model, instead of the
global vm_page array */
struct vm_sector {
/* sector size. this must be a power of 2.
all sectors in the system have the same size. */
enum vm_page_order s_size;
/* PFN of the first page contained in s_pages.
to find the PFN of any page contained within s_pages,
simply add its offset within the array to s_first_pfn */
size_t s_first_pfn;
/* array of pages contained in this sector */
struct vm_page *s_pages;
};
extern kern_status_t vm_bootstrap(
const struct vm_zone_descriptor *zones,
size_t nr_zones);
extern enum vm_model vm_memory_model(void);
extern void vm_set_memory_model(enum vm_model model);
extern struct vm_pg_data *vm_pg_data_get(vm_node_id_t node);
extern phys_addr_t vm_virt_to_phys(const void *p);
extern void *vm_phys_to_virt(phys_addr_t p);
extern size_t vm_page_order_to_bytes(enum vm_page_order order);
extern size_t vm_page_order_to_pages(enum vm_page_order order);
extern vm_alignment_t vm_page_order_to_alignment(enum vm_page_order order);
extern void vm_page_init_array(void);
extern struct vm_page *vm_page_get(phys_addr_t addr);
extern phys_addr_t vm_page_get_paddr(struct vm_page *pg);
extern struct vm_zone *vm_page_get_zone(struct vm_page *pg);
extern void *vm_page_get_vaddr(struct vm_page *pg);
extern size_t vm_page_get_pfn(struct vm_page *pg);
static inline size_t vm_page_get_size_bytes(const struct vm_page *pg)
{
return vm_page_order_to_bytes(pg->p_order);
}
extern struct vm_page *vm_page_alloc(
enum vm_page_order order,
enum vm_flags flags);
extern void vm_page_free(struct vm_page *pg);
extern int vm_page_split(
struct vm_page *pg,
struct vm_page **a,
struct vm_page **b);
extern struct vm_page *vm_page_merge(struct vm_page *a, struct vm_page *b);
extern struct vm_page *vm_page_get_buddy(struct vm_page *pg);
extern struct vm_page *vm_page_get_next_tail(struct vm_page *pg);
extern size_t vm_bytes_to_pages(size_t bytes);
extern void vm_zone_init(
struct vm_zone *z,
const struct vm_zone_descriptor *zone_info);
extern struct vm_page *vm_zone_alloc_page(
struct vm_zone *z,
enum vm_page_order order,
enum vm_flags flags);
extern void vm_zone_free_page(struct vm_zone *z, struct vm_page *pg);
extern struct vm_cache *vm_cache_create(
const char *name,
size_t objsz,
enum vm_cache_flags flags);
extern void vm_cache_init(struct vm_cache *cache);
extern void vm_cache_destroy(struct vm_cache *cache);
extern void *vm_cache_alloc(struct vm_cache *cache, enum vm_flags flags);
extern void vm_cache_free(struct vm_cache *cache, void *p);
extern void kmalloc_init(void);
extern void *kmalloc(size_t count, enum vm_flags flags);
extern void *kzalloc(size_t count, enum vm_flags flags);
extern void kfree(void *p);
/* Flat memory model functions */
extern void vm_flat_init(void);
extern struct vm_page *vm_page_get_flat(phys_addr_t addr);
extern size_t vm_page_get_pfn_flat(struct vm_page *pg);
/* Sparse memory model functions */
extern void vm_sparse_init(void);
extern struct vm_page *vm_page_get_sparse(phys_addr_t addr);
extern size_t vm_page_get_pfn_sparse(struct vm_page *pg);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
inline void *operator new(size_t count, void *p)
{
return p;
}
#define kmalloc_object(objtype, flags, ...) \
__extension__({ \
void *p = kmalloc(sizeof(objtype), flags); \
if (p) { \
new (p) objtype(__VA_ARGS__); \
} \
(objtype *)p; \
})
#endif
#endif

View File

@@ -1,5 +1,4 @@
#include <mango/init.h> #include <kernel/init.h>
int do_initcalls(void) int do_initcalls(void)
{ {

View File

@@ -1,18 +1,20 @@
#include <mango/arg.h> #include <kernel/arg.h>
#include <mango/bsp.h> #include <kernel/bsp.h>
#include <mango/clock.h> #include <kernel/channel.h>
#include <mango/cpu.h> #include <kernel/clock.h>
#include <mango/handle.h> #include <kernel/cpu.h>
#include <mango/init.h> #include <kernel/handle.h>
#include <mango/input.h> #include <kernel/init.h>
#include <mango/libc/stdio.h> #include <kernel/input.h>
#include <mango/machine/init.h> #include <kernel/libc/stdio.h>
#include <mango/object.h> #include <kernel/machine/init.h>
#include <mango/panic.h> #include <kernel/object.h>
#include <mango/printk.h> #include <kernel/panic.h>
#include <mango/sched.h> #include <kernel/port.h>
#include <mango/test.h> #include <kernel/printk.h>
#include <mango/vm-object.h> #include <kernel/sched.h>
#include <kernel/test.h>
#include <kernel/vm-object.h>
#include <stdint.h> #include <stdint.h>
extern unsigned long get_rflags(void); extern unsigned long get_rflags(void);

View File

@@ -1,6 +1,6 @@
#include <mango/arg.h> #include <kernel/arg.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#include <mango/libc/ctype.h> #include <kernel/libc/ctype.h>
static char g_cmdline[CMDLINE_MAX + 1] = {0}; static char g_cmdline[CMDLINE_MAX + 1] = {0};

View File

@@ -1,9 +1,10 @@
#include <mango/bsp.h> #include <kernel/bsp.h>
#include <mango/printk.h> #include <kernel/handle.h>
#include <mango/sched.h> #include <kernel/printk.h>
#include <mango/util.h> #include <kernel/sched.h>
#include <mango/vm-object.h> #include <kernel/util.h>
#include <mango/vm-region.h> #include <kernel/vm-object.h>
#include <kernel/vm-region.h>
#define BOOTSTRAP_STACK_SIZE 0x10000 #define BOOTSTRAP_STACK_SIZE 0x10000

View File

@@ -1,6 +1,6 @@
#include <mango/clock.h> #include <kernel/clock.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/compiler.h> #include <kernel/compiler.h>
static clock_ticks_t ticks_per_sec = 0; static clock_ticks_t ticks_per_sec = 0;
volatile clock_ticks_t clock_ticks = 0; volatile clock_ticks_t clock_ticks = 0;

View File

@@ -1,7 +1,7 @@
#include <mango/console.h> #include <kernel/console.h>
#include <mango/queue.h> #include <kernel/queue.h>
#include <mango/locks.h> #include <kernel/locks.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
static struct queue consoles; static struct queue consoles;
static spin_lock_t consoles_lock = SPIN_LOCK_INIT; static spin_lock_t consoles_lock = SPIN_LOCK_INIT;

View File

@@ -1,6 +1,6 @@
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/percpu.h> #include <kernel/percpu.h>
#include <mango/bitmap.h> #include <kernel/bitmap.h>
DECLARE_BITMAP(cpu_available, CPU_MAX); DECLARE_BITMAP(cpu_available, CPU_MAX);
DECLARE_BITMAP(cpu_online, CPU_MAX); DECLARE_BITMAP(cpu_online, CPU_MAX);

View File

@@ -1,7 +1,9 @@
#include <mango/handle.h> #include <kernel/handle.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/vm.h> #include <kernel/sched.h>
#include <kernel/util.h>
#include <kernel/vm.h>
/* depth=3 gives a maximum of ~66.6 million handles */ /* depth=3 gives a maximum of ~66.6 million handles */
#define MAX_TABLE_DEPTH 3 #define MAX_TABLE_DEPTH 3

View File

@@ -1,6 +1,6 @@
#include <mango/locks.h> #include <kernel/locks.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/queue.h> #include <kernel/queue.h>
#define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops.opname) #define HAS_OP(obj, opname) ((obj)->ob_type->ob_ops.opname)

View File

@@ -1,8 +1,8 @@
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <mango/machine/panic.h> #include <kernel/machine/panic.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/sched.h> #include <kernel/sched.h>
#include <stdarg.h> #include <stdarg.h>
static int has_panicked = 0; static int has_panicked = 0;

View File

@@ -1,6 +1,6 @@
#include <mango/percpu.h> #include <kernel/percpu.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/vm.h> #include <kernel/vm.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>

View File

@@ -1,7 +1,7 @@
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/locks.h> #include <kernel/locks.h>
#include <mango/console.h> #include <kernel/console.h>
#include <mango/libc/stdio.h> #include <kernel/libc/stdio.h>
#include <stdarg.h> #include <stdarg.h>
#define LOG_BUFFER_SIZE 0x40000 #define LOG_BUFFER_SIZE 0x40000

View File

@@ -1,26 +0,0 @@
#ifndef MANGO_LIBC_TYPES_H_
#define MANGO_LIBC_TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
extern int isalnum(int c);
extern int isalpha(int c);
extern int iscntrl(int c);
extern int isdigit(int c);
extern int isgraph(int c);
extern int islower(int c);
extern int isprint(int c);
extern int ispunct(int c);
extern int isspace(int c);
extern int isupper(int c);
extern int isxdigit(int c);
extern int tolower(int c);
extern int toupper(int c);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,21 +0,0 @@
#ifndef MANGO_STDIO_H_
#define MANGO_STDIO_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
int snprintf(char *buffer, size_t count, const char *format, ...);
int vsnprintf(char *buffer, size_t count, const char *format, va_list va);
int fctprintf(void (*out)(char character, void *arg), void *arg, const char*format, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,36 +0,0 @@
#ifndef MANGO_LIBC_STRING_H_
#define MANGO_LIBC_STRING_H_
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char *strcpy(char *output, const char *input);
extern char *strncpy(char *output, const char *input, unsigned long count);
extern char *strchrnul(const char *s, int c);
extern char *strchr(const char *s, int c);
extern size_t lfind(const char *str, const char accept);
extern size_t strspn(const char *s, const char *c);
extern size_t strcspn(const char *s, const char *c);
extern char *strpbrk(const char *s, const char *b);
extern size_t strlen(const char *str);
extern char *strrchr(const char *str, int c);
extern int strcmp(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, unsigned long n);
extern void *memcpy(void *str1, const void *str2, size_t n);
extern int memcmp(const void *str1, const void *str2, size_t n);
extern void *memset(void *str, int c, size_t n);
extern void *memmove(void *dst, const void *src, size_t n);
extern char *strdup(const char *src);
extern char *strtok_r(char *str, const char *delim, char **saveptr);
extern char *strcat(char *dest, const char *src);
extern char *strncat(char *dest, const char *src, size_t num);
extern void *memchr(const void *ptr, int value, unsigned long num);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
static void *memcpy_r(void *dest, const void *src, size_t sz) static void *memcpy_r(void *dest, const void *src, size_t sz)
{ {

View File

@@ -2,12 +2,12 @@
void *memset(void *str, int c, size_t n) void *memset(void *str, int c, size_t n)
{ {
unsigned char val = (unsigned char)c; unsigned char val = (unsigned char)c;
unsigned char *buf = str; unsigned char *buf = str;
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
buf[i] = val; buf[i] = val;
} }
return str; return str;
} }

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h> #include <kernel/libc/string.h>
char *strcat(char *dest, const char *src) { char *strcat(char *dest, const char *src) {
size_t start = strlen(dest), i = 0; size_t start = strlen(dest), i = 0;

View File

@@ -1,19 +1,21 @@
int strcmp(const char *s1, const char *s2) int strcmp(const char *s1, const char *s2)
{ {
int i; int i;
for (i = 0; s1[i] == s2[i]; i++) for (i = 0; s1[i] == s2[i]; i++)
if (s1[i] == '\0') if (s1[i] == '\0')
return 0; return 0;
return s1[i] - s2[i]; return s1[i] - s2[i];
} }
int strncmp(const char *s1, const char *s2, unsigned long n) int strncmp(const char *s1, const char *s2, unsigned long n)
{ {
for (; n > 0; s1++, s2++, --n) for (; n > 0; s1++, s2++, --n)
if (*s1 != *s2) if (*s1 != *s2)
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : 1); return ((*(unsigned char *)s1 < *(unsigned char *)s2)
else if (*s1 == '\0') ? -1
return 0; : 1);
return 0; else if (*s1 == '\0')
return 0;
return 0;
} }

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h> #include <kernel/libc/string.h>
char *strcpy(char *output, const char *input) char *strcpy(char *output, const char *input)
{ {

View File

@@ -1,10 +1,11 @@
#include <mango/libc/string.h> #include <kernel/libc/string.h>
size_t strlen(const char *str) { size_t strlen(const char *str)
{
size_t res = 0; size_t res = 0;
while (str[res]) { while (str[res]) {
res++; res++;
} }
return res; return res;
} }

View File

@@ -1,4 +1,4 @@
#include <mango/libc/string.h> #include <kernel/libc/string.h>
char *strrchr(const char *str, int c) { char *strrchr(const char *str, int c) {
size_t len = strlen(str); size_t len = strlen(str);

View File

@@ -1,5 +1,5 @@
#include <limits.h> #include <limits.h>
#include <mango/libc/string.h> #include <kernel/libc/string.h>
#define ALIGN (sizeof(size_t)) #define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1 / UCHAR_MAX) #define ONES ((size_t)-1 / UCHAR_MAX)

View File

@@ -16,7 +16,8 @@ typedef unsigned int kern_status_t;
#define KERN_DEVICE_STUCK (10) #define KERN_DEVICE_STUCK (10)
#define KERN_IO_ERROR (11) #define KERN_IO_ERROR (11)
#define KERN_FATAL_ERROR (12) #define KERN_FATAL_ERROR (12)
#define KERN_BAD_STATE (13)
extern const char *kern_status_string(kern_status_t status); #define KERN_MEMORY_FAULT (14)
#define KERN_ACCESS_DENIED (15)
#endif #endif

View File

@@ -0,0 +1,35 @@
#ifndef MANGO_SYSCALL_H_
#define MANGO_SYSCALL_H_
#define SYS_TASK_EXIT 1
#define SYS_TASK_CREATE 2
#define SYS_TASK_CREATE_THREAD 3
#define SYS_THREAD_START 30
#define SYS_VM_OBJECT_CREATE 4
#define SYS_VM_OBJECT_READ 5
#define SYS_VM_OBJECT_WRITE 6
#define SYS_VM_OBJECT_COPY 29
#define SYS_VM_REGION_CREATE 7
#define SYS_VM_REGION_READ 8
#define SYS_VM_REGION_WRITE 9
#define SYS_VM_REGION_MAP_ABSOLUTE 10
#define SYS_VM_REGION_MAP_RELATIVE 11
#define SYS_VM_REGION_UNMAP_ABSOLUTE 12
#define SYS_VM_REGION_UNMAP_RELATIVE 13
#define SYS_KERN_LOG 14
#define SYS_KERN_HANDLE_CLOSE 15
#define SYS_KERN_CONFIG_GET 16
#define SYS_KERN_CONFIG_SET 17
#define SYS_MSG_SEND 18
#define SYS_MSG_RECV 19
#define SYS_MSG_REPLY 20
#define SYS_MSG_READ 21
#define SYS_MSG_READ_HANDLES 22
#define SYS_MSG_WRITE 23
#define SYS_MSG_WRITE_HANDLES 24
#define SYS_CHANNEL_CREATE 25
#define SYS_PORT_CREATE 26
#define SYS_PORT_CONNECT 27
#define SYS_PORT_DISCONNECT 28
#endif

View File

@@ -0,0 +1,62 @@
#ifndef MANGO_TYPES_H_
#define MANGO_TYPES_H_
#include <stddef.h>
#include <stdint.h>
#define VM_PROT_READ 0x01u
#define VM_PROT_WRITE 0x02u
#define VM_PROT_EXEC 0x04u
#define VM_PROT_USER 0x08u
#define VM_PROT_SVR 0x10u
#define VM_PROT_NOCACHE 0x10u
#define VM_PROT_MAP_SPECIFIC 0x40u
/* if this flag is set, other tasks can connect to this channel using
* the port_connect_* syscalls.
* if this flag is NOT set, only threads in the task that owns the channel
* can create ports connecting to it. */
#define CHANNEL_F_ALLOW_DIRECT_CONNECTIONS 0x01u
/* msg_reply: once the reply has been sent, disconnect the port that sent the
* original message */
#define MSG_F_DISCONNECT_AFTER_REPLY 0x01u
#define VM_REGION_ANY_OFFSET ((off_t) - 1)
#define KERN_HANDLE_INVALID ((kern_handle_t)0xFFFFFFFF)
#define KERN_CFG_INVALID 0x00u
#define KERN_CFG_PAGE_SIZE 0x01u
typedef uintptr_t phys_addr_t;
typedef uintptr_t virt_addr_t;
typedef uint64_t msgid_t;
typedef uint64_t off_t;
typedef unsigned int tid_t;
typedef uint32_t kern_handle_t;
typedef uint32_t kern_config_key_t;
typedef uint32_t vm_prot_t;
typedef uint32_t channel_flags_t;
typedef uint32_t msg_flags_t;
typedef unsigned int umode_t;
struct iovec {
virt_addr_t io_base;
size_t io_len;
};
struct handle_list {
kern_handle_t *l_handles;
size_t l_nr_handles;
};
struct msg {
struct iovec *msg_data;
size_t msg_data_count;
struct handle_list *msg_handles;
size_t msg_handles_count;
};
#endif

View File

@@ -1,10 +1,10 @@
#include <mango/clock.h> #include <kernel/clock.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/machine/thread.h> #include <kernel/machine/thread.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/vm-region.h> #include <kernel/vm-region.h>
extern kern_status_t setup_kernel_task(void); extern kern_status_t setup_kernel_task(void);
extern kern_status_t setup_idle_task(void); extern kern_status_t setup_idle_task(void);

View File

@@ -1,6 +1,6 @@
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/percpu.h> #include <kernel/percpu.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#define PRIO_MASK(p) (((uint32_t)1) << (p)) #define PRIO_MASK(p) (((uint32_t)1) << (p))
#define FIRST_PRIO(m) (m > 0 ? (PRIO_MAX - __builtin_clz(m) - 1) : -1) #define FIRST_PRIO(m) (m > 0 ? (PRIO_MAX - __builtin_clz(m) - 1) : -1)

View File

@@ -1,12 +1,14 @@
#include <mango/clock.h> #include <kernel/channel.h>
#include <mango/cpu.h> #include <kernel/clock.h>
#include <mango/handle.h> #include <kernel/cpu.h>
#include <mango/libc/stdio.h> #include <kernel/handle.h>
#include <mango/locks.h> #include <kernel/libc/stdio.h>
#include <mango/object.h> #include <kernel/locks.h>
#include <mango/printk.h> #include <kernel/object.h>
#include <mango/sched.h> #include <kernel/printk.h>
#include <mango/vm-region.h> #include <kernel/sched.h>
#include <kernel/util.h>
#include <kernel/vm-region.h>
#define TASK_CAST(p) OBJECT_C_CAST(struct task, t_base, &task_type, p) #define TASK_CAST(p) OBJECT_C_CAST(struct task, t_base, &task_type, p)

View File

@@ -1,8 +1,8 @@
#include <mango/bitmap.h> #include <kernel/bitmap.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/machine/thread.h> #include <kernel/machine/thread.h>
#include <mango/object.h> #include <kernel/object.h>
#include <mango/sched.h> #include <kernel/sched.h>
#define THREAD_CAST(p) OBJECT_C_CAST(struct thread, thr_base, &thread_type, p) #define THREAD_CAST(p) OBJECT_C_CAST(struct thread, thr_base, &thread_type, p)

View File

@@ -1,7 +1,7 @@
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/printk.h> #include <kernel/printk.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
#include <mango/clock.h> #include <kernel/clock.h>
static void timeout_expiry(struct timer *timer) static void timeout_expiry(struct timer *timer)
{ {

View File

@@ -1,5 +1,5 @@
#include <mango/sched.h> #include <kernel/cpu.h>
#include <mango/cpu.h> #include <kernel/sched.h>
void wait_item_init(struct wait_item *item, struct thread *thr) void wait_item_init(struct wait_item *item, struct thread *thr)
{ {

View File

@@ -1,7 +1,7 @@
#include <mango/sched.h> #include <kernel/sched.h>
#include <mango/vm.h> #include <kernel/vm.h>
#include <mango/util.h> #include <kernel/util.h>
#include <mango/cpu.h> #include <kernel/cpu.h>
static struct worker_pool *__global_worker_pool = NULL; static struct worker_pool *__global_worker_pool = NULL;

Some files were not shown because too many files have changed in this diff Show More