Massive backlog of changes

This commit is contained in:
2022-06-15 15:59:31 -05:00
parent c962a83ff0
commit a52f06f81e
49 changed files with 1855 additions and 1083 deletions

View File

@@ -1,9 +0,0 @@
#pragma once
#include <stddef.h>
void initialize_allocator(void *bottom, void *top);
void *allocate_from_bottom(size_t size);
void *allocate_from_top(size_t size);

41
include/avltree.h Normal file
View File

@@ -0,0 +1,41 @@
#pragma once
/**
* @brief An AVL tree.
*
*/
struct avltree_t {
int height;
int key;
void *value;
struct avltree_t *left, *right;
};
/**
* @brief Inserts a new node into an AVL tree.
*
* A new node will be allocated and assigned the provided key and value.
*
* @param tree A pointer to the tree to insert into.
* @param key The key to associate the new node with.
* @param value A pointer to store into the new node.
*/
struct avltree_t *avl_insert(struct avltree_t *tree, int key, void *value);
/**
* @brief Removes the node associated with `key` from `tree`.
*
* @param tree A pointer to the tree to remove from.
* @param key The key of the node to remove.
* @return struct avltree_t* The pointer stored in the node that was just removed.
*/
struct avltree_t *avl_remove(struct avltree_t *tree, int key);
/**
* @brief Searches for a node in `tree` with a matching key, and returns the
*
* @param tree
* @param key
* @return void*
*/
void *avl_get(struct avltree_t *tree, int key);

View File

@@ -1,6 +1,6 @@
#pragma once
#include "pageallocator.h"
#include "mmgr.h"
#include "types/physaddr.h"
#include <stdint.h>
@@ -115,4 +115,4 @@ struct elf_section_header_t
static const enum elf_isa_t HOST_ISA = ELF_ISA_AARCH64;
#endif
int load_program(struct elf_file_header_t *elf, struct page_stack_t *page_stack);
int load_program(struct elf_file_header_t *elf);

33
include/heap.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include "mmgr.h"
#include <stddef.h>
/**
* @brief Initializes the system's heap.
*
* This function contructs the heap's internal tables, allocating pages as needed
* to do so.
*
* @param page_stack Pointer to the page stack descriptor
* @param base Base location of the heap to contruct
* @param heap_size Total size in bytes of the heap
* @param block_size Size in bytes of a single unit of allocation
* @return a status code
*/
int kminit(void *base, size_t heap_size, size_t block_size);
/**
* @brief Allocates a block of memory containing at least `size` bytes.
*
* @param size The size of the block to allocate
* @return void* A pointer to the allocated block, or NULL upon failure.
*/
void *kmalloc(size_t size);
/**
* @brief Frees a block of memory previously allocated by `kmalloc`.
*
* @param ptr Pointer to the block to free
*/
void kfree(void *ptr);

View File

@@ -1,14 +1,14 @@
#pragma once
#include "pageallocator.h"
#include "avltree.h"
#include "memmap.h"
#include "priorityqueue.h"
#include "resource.h"
#include "module.h"
#include "memorymap.h"
#include "syscallid.h"
#include "mmgr.h"
#include "syscalls.h"
#include <stddef.h>
typedef size_t (*syscall_t)(struct kernel_t*, size_t, size_t, size_t);
#define MAX_SYSCALL_ID 256
#define module_limit 8
enum process_state_t
{
@@ -18,6 +18,22 @@ enum process_state_t
struct process_context_t;
struct module_t
{
physaddr_t start;
physaddr_t end;
char str[64 - 2 * sizeof(physaddr_t)];
};
struct boot_info_t
{
char *bootloader;
char *parameters;
size_t module_count;
struct memory_map_t map;
struct module_t modules[module_limit];
};
struct message_t
{
uint16_t sender, type;
@@ -35,30 +51,33 @@ struct process_t
struct kernel_t
{
struct page_stack_t *page_stack;
struct priority_queue_t *priority_queue;
struct resource_table_t *resource_table;
struct syscall_t syscall_table[MAX_SYSCALL_ID];
struct priority_queue_t priority_queue;
struct avltree_t *process_table;
struct process_t *active_process;
int next_pid;
};
extern syscall_t syscall_table[32];
void kernel_initialize(struct boot_info_t *boot_info);
extern struct kernel_t kernel_state;
int set_syscall(int id, int arg_count, int pid, void *func_ptr);
void construct_kernel_state(struct kernel_t *kernel, struct page_stack_t *page_stack,
struct priority_queue_t *priority_queue, struct resource_table_t *resource_table,
size_t module_count, struct module_t *module_list);
size_t do_syscall(enum syscall_id_t id, syscall_arg_t arg1, syscall_arg_t arg2, syscall_arg_t arg3);
size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, size_t arg2, size_t arg3);
int load_module(struct module_t *module);
int load_module(struct kernel_t *kernel, struct module_t *module);
int active_process();
struct process_context_t *next_process(struct kernel_t *kernel, struct process_context_t *prev_state);
int add_process(void *program_entry, int priority, physaddr_t address_space);
int terminate_process(struct kernel_t *kernel, size_t process_id);
struct process_context_t *next_process(struct process_context_t *prev_state);
int accept_message(struct kernel_t *kernel, size_t process_id, struct message_t *message);
int terminate_process(size_t process_id);
int send_message(struct kernel_t *kernel, size_t process_id, const struct message_t *message);
/*
int accept_message(size_t process_id, struct message_t *message);
int send_message(size_t process_id, const struct message_t *message);
*/
void panic(const char *message) __attribute__ ((noreturn));

View File

@@ -24,4 +24,4 @@ struct memory_map_t
size_t capacity;
};
void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, enum memory_type_t type);
void insert_region(struct memory_map_t *map, physaddr_t location, size_t size, enum memory_type_t type);

View File

@@ -1,24 +1,63 @@
#pragma once
#include "pageallocator.h"
#include "memmap.h"
#include "platform/paging.h"
#include "types/physaddr.h"
enum page_flag_t
{
PAGE_RW = 1,
PAGE_EXECUTABLE = 1 << 1,
PAGE_USERMODE = 1 << 2
};
enum page_type_t
{
PAGE_NOT_PRESENT = 0,
PAGE_ANON = 1,
PAGE_COPY_ON_WRITE = 2
};
#include <stddef.h>
extern const size_t page_size;
/**
* @brief Pop the topmost address from the stack and returns that value.
*
* If the stack is empty, this function will instead return a status code. This
* can be identified by testing the least signifigant bits of the return value.
*
* @param stack
* @return physaddr_t
*/
physaddr_t reserve_page();
/**
* @brief Pushes `location` onto the stack.
*
* If there is no room on the stack, the stack will be unaffected.
*
* @param stack
* @param location
*/
int free_page(physaddr_t location);
/**
* @brief Computes the number of available pages.
*
* @param stack
* @return size_t
*/
size_t free_page_count();
/**
* @brief Get the location of the bottom of the page stack.
*
* @return void*
*/
void *page_stack_bottom();
/**
* @brief Get the location of the top of the page stack.
*
* @return void*
*/
void *page_stack_top();
/**
* @brief Push all available pages in `map` onto the stack
*
* @param stack
* @param map
*/
int initialize_page_stack(struct memory_map_t *map, physaddr_t *stack_base);
/**
* @brief Create a new top-level page table and map the kernel in it.
*
@@ -26,14 +65,7 @@ extern const size_t page_size;
*
* @return physaddr_t
*/
physaddr_t create_address_space(struct page_stack_t *page_stack);
/**
* @brief Load an existing top-level page table
*
* @param table
*/
void load_address_space(physaddr_t table);
physaddr_t create_address_space();
/**
* @brief Returns the physical address of the top-level page table currently in
@@ -52,7 +84,7 @@ physaddr_t current_address_space();
* @param flags
* @return int
*/
int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags);
int map_page(void *page, physaddr_t frame, int flags);
/**
* @brief Unmaps a single page, returning the physical address of the frame it
@@ -69,7 +101,7 @@ physaddr_t unmap_page(void *page);
* @param page
* @return enum page_type_t
*/
enum page_type_t page_type(void *page);
int page_type(void *page);
/**
* @brief

View File

@@ -1,10 +0,0 @@
#pragma once
#include "types/physaddr.h"
struct module_t
{
physaddr_t start;
physaddr_t end;
char str[64 - 2 * sizeof(physaddr_t)];
};

View File

@@ -1,75 +0,0 @@
#pragma once
#include "memorymap.h"
#include "types/physaddr.h"
#include <stddef.h>
/**
* @brief Describes a stack containing the physical addresses of available page
* frames.
*
*/
struct page_stack_t
{
/**
* @brief The total number of physical pages managed by the system.
*
*/
size_t total_pages;
/**
* @brief Points to the topmost physical address on the stack.
*
*/
physaddr_t *stack_pointer;
/**
* @brief Points to the bottom of the stack.
*
*/
physaddr_t *base_pointer;
/**
* @brief Points to the limit of the stack. The stack cannot grow beyond
* this point.
*
*/
physaddr_t *limit_pointer;
};
/**
* @brief Pop the topmost address from the stack and returns that value.
*
* If the stack is empty, this function will instead return a status code. This
* can be identified by testing the least signifigant bits of the return value.
*
* @param stack
* @return physaddr_t
*/
physaddr_t reserve_page(struct page_stack_t *stack);
/**
* @brief Pushes `location` onto the stack.
*
* If there is no room on the stack, the stack will be unaffected.
*
* @param stack
* @param location
*/
int free_page(struct page_stack_t *stack, physaddr_t location);
/**
* @brief Computes the number of available pages.
*
* @param stack
* @return size_t
*/
size_t free_page_count(struct page_stack_t *stack);
/**
* @brief Push all available pages in `map` onto the stack
*
* @param stack
* @param map
*/
int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, physaddr_t *stack_base);

View File

@@ -1,9 +1,8 @@
#pragma once
#include "pageallocator.h"
#include "kernel.h"
void *initialize_context(void *task_entry);
void *initialize_context(void *task_entry, struct page_stack_t *page_stack);
void destroy_context(void *ctx);
void save_context(struct process_context_t *context, void *ptr);

View File

@@ -0,0 +1,20 @@
#pragma once
/**
* @brief
*
* @return int
*/
int initialize_interrupts();
/**
* @brief
*
*/
void irq_enable();
/**
* @brief
*
*/
void irq_disable();

96
include/platform/paging.h Normal file
View File

@@ -0,0 +1,96 @@
#pragma once
#include "types/physaddr.h"
#include <stddef.h>
enum page_flag_t
{
PAGE_RW = 1,
PAGE_EXECUTABLE = 1 << 1,
PAGE_USERMODE = 1 << 2,
PAGE_PRESENT = 1 << 16,
PAGE_ANON = 1 << 17,
PAGE_COPY_ON_WRITE = 1 << 18
};
const size_t page_table_levels;
/**
* @brief
*
* @param table
* @return int
*/
int paging_init_top_table(physaddr_t table);
/**
* @brief Returns the physical address of the top-level page table currently in
* use.
*
* @return physaddr_t
*/
physaddr_t paging_current_address_space();
/**
* @brief Load an existing top-level page table
*
* @param table
*/
void paging_load_address_space(physaddr_t table);
/**
* @brief Get the pte type object
*
* @param page
* @param level
* @return int
*/
int get_pte_type(void *page, int level);
/**
* @brief Set the pte type object
*
* @param page
* @param level
* @param flags
* @return int
*/
int set_pte_type(void *page, int level, int flags);
/**
* @brief Get the pte address object
*
* @param page
* @param level
* @return physaddr_t
*/
physaddr_t get_pte_address(void *page, int level);
/**
* @brief Set the pte address object
*
* @param page
* @param level
* @param addr
* @return int
*/
int set_pte_address(void *page, int level, physaddr_t addr);
/**
* @brief Set the pte object
*
* @param page
* @param level
* @param flags
* @param addr
* @return int
*/
int set_pte(void *page, int level, int flags, physaddr_t addr);
/**
* @brief Resets all entries in the same table as the specified entry
*
* @param page
* @param level
*/
void wipe_page_table(void *page, int level);

24
include/platform/putc.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
/**
* @brief Prepare to output characters to the screen.
*
* @return int
*/
int initialize_screen();
/**
* @brief Write a single character to the screen.
*
* @param c
* @return int
*/
int putchar(int c);
/**
* @brief Write a string to the screen.
*
* @param str
* @return int
*/
int puts(const char *str);

View File

@@ -1,11 +1,31 @@
#pragma once
#include "pageallocator.h"
#include "kernel.h"
#include <stddef.h>
/**
* @brief An pair consisting of a priority and a pointer to be stored in
* a priority queue.
*
*/
struct priority_queue_node_t
{
/**
* @brief A pointer to some user-defined object.
*
*/
void *value;
/**
* @brief The priority of the associated object. Only the object with the
* lowest priority is directly accessible from a priority queue.
*
*/
int priority;
};
/**
* @brief
* @brief A priority queue. Each object in the queue contains a priority and
* a pointer to some user-defined value, and a priority. Operations on the
* queue consist of insertion and deletion of objects, and extraction of the
* object with the lowest priority.
*
*/
struct priority_queue_t
@@ -14,45 +34,59 @@ struct priority_queue_t
* @brief A pointer to the heap described by this structure.
*
*/
struct process_t **heap;
struct priority_queue_node_t *heap;
/**
* @brief The current number of elements stored in the heap.
*
*/
size_t size;
int size;
/**
* @brief The maximum number of elements that the heap can currently hold.
*
*/
size_t capacity;
int capacity;
};
int construct_priority_queue(struct priority_queue_t *queue, struct page_stack_t *page_stack);
/**
* @brief
* @brief Initializes the given queue struct.
*
* The queue's underlying heap is allocated
*
* @param queue
* @return struct process_t*
*/
struct process_t *extract_min(struct priority_queue_t *queue);
/**
* @brief
*
* @param queue
* @param process
* @return int
*/
int queue_insert(struct priority_queue_t *queue, struct process_t *process);
int construct_priority_queue(struct priority_queue_t *queue, int capacity);
/**
* @brief
* @brief Extracts the object with the lowest priority off the given queue.
*
* The object is removed from the queue, and a pointer to its userdata is
* returned. If the queue is empty, this function returns NULL and the queue
* is unaffected. If multiple objects with the same priority are stored on the
* queue, this function will extract the object lest-recently inserted.
*
* @param queue
* @param process
* @return void*
*/
void *extract_min(struct priority_queue_t *queue);
/**
* @brief Inserts a new object onto the queue.
*
* @param queue
* @param value
* @param priority
* @return int
*/
int queue_remove(struct priority_queue_t *queue, struct process_t *process);
int queue_insert(struct priority_queue_t *queue, void *value, int priority);
/**
* @brief Removes the object with a matching value from the queue.
*
* @param queue
* @param value
* @return int
*/
int queue_remove(struct priority_queue_t *queue, void *value);

View File

@@ -1,30 +0,0 @@
#pragma once
#include "pageallocator.h"
#include "kernel.h"
#include <stddef.h>
enum resource_type_t
{
RESOURCE_UNAVAILABLE = 0,
RESOURCE_PROCESS
};
struct resource_t
{
size_t type;
union
{
struct process_t process;
};
};
struct resource_table_t
{
struct resource_t *array;
struct resource_t *limit;
};
int construct_resource_table(struct resource_table_t *table, struct page_stack_t *page_stack);
int get_free_resource_slot(struct resource_table_t *table, struct page_stack_t *page_stack);

View File

@@ -2,12 +2,6 @@
#include <stdarg.h>
int initialize_screen();
int putchar(int c);
int puts(const char *str);
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);

View File

@@ -1,10 +0,0 @@
#pragma once
enum syscall_id_t
{
SYSCALL_TEST = 1,
SYSCALL_YIELD,
SYSCALL_MMAP,
SYSCALL_MUNMAP,
SYSCALL_TERMINATE_SELF
};

View File

@@ -1,11 +1,50 @@
#pragma once
#include "kernel.h"
#include <stdbool.h>
#include <stddef.h>
size_t test_syscall(struct kernel_t *kernel, size_t arg1, size_t arg2, size_t arg3);
enum syscall_id_t
{
SYSCALL_TEST = 1,
SYSCALL_YIELD,
SYSCALL_MMAP,
SYSCALL_MUNMAP,
SYSCALL_TERMINATE_SELF
};
size_t mmap(struct kernel_t *kernel, size_t location, size_t length, size_t flags);
typedef union
{
long signed_int;
unsigned long unsigned_int;
void *ptr;
} syscall_arg_t;
size_t munmap(struct kernel_t *kernel, size_t location, size_t length, size_t arg3);
typedef size_t (*syscall_ptr_0_t)();
size_t terminate_self(struct kernel_t *kernel, size_t arg1, size_t arg2, size_t arg3)
typedef size_t (*syscall_ptr_1_t)(syscall_arg_t);
typedef size_t (*syscall_ptr_2_t)(syscall_arg_t, syscall_arg_t);
typedef size_t (*syscall_ptr_3_t)(syscall_arg_t, syscall_arg_t, syscall_arg_t);
struct syscall_t
{
bool defined;
int arg_count;
int process_id;
union
{
syscall_ptr_0_t func_ptr_0;
syscall_ptr_1_t func_ptr_1;
syscall_ptr_2_t func_ptr_2;
syscall_ptr_3_t func_ptr_3;
};
};
size_t test_syscall(syscall_arg_t str);
size_t mmap(syscall_arg_t location, syscall_arg_t length, syscall_arg_t flags);
size_t munmap(syscall_arg_t location, syscall_arg_t length);
size_t terminate_self();

View File

@@ -61,7 +61,7 @@ struct apic_register_t
{
uint32_t value;
uint32_t padding[3];
};
} __attribute__ ((packed));
struct apic_lapic_version_t
{
@@ -71,7 +71,7 @@ struct apic_lapic_version_t
uint32_t suppress_eoi_broadcast : 1;
uint32_t reserved_2 : 7;
uint32_t padding[3];
};
} __attribute__ ((packed));
struct apic_lvt_t
{
@@ -86,7 +86,7 @@ struct apic_lvt_t
uint32_t timer_mode : 2;
uint32_t reserved_2 : 13;
uint32_t padding[3];
};
} __attribute__ ((packed));
struct apic_icr_t
{
@@ -104,7 +104,7 @@ struct apic_icr_t
uint32_t reserved : 24;
uint32_t destination : 8;
uint32_t padding_2[3];
};
} __attribute__ ((packed));
struct apic_registers_t
{
@@ -138,9 +138,10 @@ struct apic_registers_t
struct apic_register_t reserved_4[4];
struct apic_register_t divide_config;
struct apic_register_t reserved_5;
};
struct apic_register_t reserved_76[16 * 12];
} __attribute__ ((packed));
extern struct apic_registers_t volatile *apic_registers;
extern struct apic_registers_t volatile apic_registers;
void apic_enable();

View File

@@ -8,6 +8,9 @@ void isr_generic(struct interrupt_frame_t *frame);
__attribute__ ((interrupt))
void isr_division_by_zero(struct interrupt_frame_t *frame);
__attribute__ ((interrupt))
void isr_segment_not_present(struct interrupt_frame_t *frame, unsigned int error);
__attribute__ ((interrupt))
void isr_gp_fault(struct interrupt_frame_t *frame, unsigned int error);

View File

@@ -1,84 +1,12 @@
#pragma once
#include "memorymap.h"
#include "module.h"
#include <stddef.h>
#include <stdint.h>
#define module_limit 8
enum multiboot2_tag_types
{
MB_END_TAG = 0,
MB_BOOT_COMMAND = 1,
MB_BOOTLOADER = 2,
MB_MODULE = 3,
MB_MEMORY_INFO = 4,
MB_BIOS_BOOT_DEVICE = 5,
MB_MEMORY_MAP = 6,
MB_VBE = 7,
MB_FRAMEBUFFER = 8,
MB_ELF_SYMBOLS = 9,
MB_APM = 10,
MB_EFI32_SYSTEM_TABLE = 11,
MB_EFI64_SYSTEM_TABLE = 12,
MB_SMBIOS = 13,
MB_ACPI10_RSDP = 14,
MB_ACPT20_RSDP = 15,
MB_NETOWRK = 16,
MB_EFI_MEMORY_MAP = 17,
MB_EFI_BOOT_SERVICES = 18,
MB_EFI32_IMAGE = 19,
MB_EFI64_IMAGE = 20,
MB_LOAD_ADDRESS = 21
};
enum multiboot2_memory_types
{
MB_AVAILABLE = 1,
MB_ACPI = 3,
MB_DEFECTIVE = 5
};
struct multiboot2_string_t
{
uint32_t type;
uint32_t size;
char str;
};
struct multiboot2_module_t
{
uint32_t type;
uint32_t size;
uint32_t start;
uint32_t end;
char str;
};
struct multiboot2_map_entry_t
{
uint64_t base;
uint64_t length;
uint32_t type;
};
struct multiboot2_memory_map_t
{
uint32_t type;
uint32_t size;
uint32_t entry_size;
uint32_t entry_version;
struct multiboot2_map_entry_t entries;
};
struct boot_info_t
{
char *bootloader;
char *parameters;
size_t module_count;
struct memory_map_t map;
struct module_t modules[module_limit];
};
#include "kernel.h"
/**
* @brief
*
* @param boot_info
* @param table
* @return void*
*/
void *read_multiboot_table(struct boot_info_t *boot_info, void *table);