diff options
Diffstat (limited to 'src/kernel/include')
l--------- | src/kernel/include/config.h | 1 | ||||
-rw-r--r-- | src/kernel/include/dbglog.h | 8 | ||||
-rw-r--r-- | src/kernel/include/frame.h | 14 | ||||
-rw-r--r-- | src/kernel/include/gdt.h | 17 | ||||
-rw-r--r-- | src/kernel/include/idt.h | 79 | ||||
-rw-r--r-- | src/kernel/include/kmalloc.h | 11 | ||||
-rw-r--r-- | src/kernel/include/multiboot.h | 63 | ||||
-rw-r--r-- | src/kernel/include/paging.h | 31 | ||||
-rw-r--r-- | src/kernel/include/process.h | 43 | ||||
-rw-r--r-- | src/kernel/include/region.h | 38 | ||||
-rw-r--r-- | src/kernel/include/sys.h | 53 | ||||
-rw-r--r-- | src/kernel/include/thread.h | 46 |
12 files changed, 404 insertions, 0 deletions
diff --git a/src/kernel/include/config.h b/src/kernel/include/config.h new file mode 120000 index 0000000..93307d9 --- /dev/null +++ b/src/kernel/include/config.h @@ -0,0 +1 @@ +../config.h
\ No newline at end of file diff --git a/src/kernel/include/dbglog.h b/src/kernel/include/dbglog.h new file mode 100644 index 0000000..8bf6962 --- /dev/null +++ b/src/kernel/include/dbglog.h @@ -0,0 +1,8 @@ +#pragma once + +#include <config.h> +#include <debug.h> + +void dbglog_setup(); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/frame.h b/src/kernel/include/frame.h new file mode 100644 index 0000000..9ffafb3 --- /dev/null +++ b/src/kernel/include/frame.h @@ -0,0 +1,14 @@ +#pragma once + +#include <sys.h> + +// frame.h : physical memory allocator + +void frame_init_allocator(size_t total_ram, void** kernel_data_end); + +uint32_t frame_alloc(size_t n); // allocate n consecutive frames (returns 0 on failure) +void frame_free(uint32_t base, size_t n); + +void dbg_print_frame_stats(); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/gdt.h b/src/kernel/include/gdt.h new file mode 100644 index 0000000..a62d0db --- /dev/null +++ b/src/kernel/include/gdt.h @@ -0,0 +1,17 @@ +#pragma once + +#include <stddef.h> +#include <stdint.h> + +/* The GDT is one of the x86's descriptor tables. It is used for memory segmentation. + Here, we don't use segmentation to separate processes from one another (this is done with paging). + We only use segmentation to make the difference between kernel mode (ring 3) and user mode (ring 0) */ + +void gdt_init(); + +#define K_CODE_SEGMENT 0x08 +#define K_DATA_SEGMENT 0x10 +#define U_CODE_SEGMENT 0x18 +#define U_DATA_SEGMENT 0x20 + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/idt.h b/src/kernel/include/idt.h new file mode 100644 index 0000000..8e84cea --- /dev/null +++ b/src/kernel/include/idt.h @@ -0,0 +1,79 @@ +#pragma once + +/* The IDT is the system descriptor table that tells the CPU what to do when an interrupt fires. + There are three categories of interrupts : + - Exceptions ; eg page fault, divide by 0 + - IRQ : interrupts caused by hardware + - System calls : when an applications asks the system to do something */ + +#include <config.h> + +#define IRQ0 0 +#define IRQ1 1 +#define IRQ2 2 +#define IRQ3 3 +#define IRQ4 4 +#define IRQ5 5 +#define IRQ6 6 +#define IRQ7 7 +#define IRQ8 8 +#define IRQ9 9 +#define IRQ10 10 +#define IRQ11 11 +#define IRQ12 12 +#define IRQ13 13 +#define IRQ14 14 +#define IRQ15 15 + +#define EX_DIVIDE_ERROR 0 // No error code +#define EX_DEBUG 1 // No error code +#define EX_NMI_INTERRUPT 2 // No error code +#define EX_BREAKPOINT 3 // No error code +#define EX_OVERFLOW 4 // No error code +#define EX_BOUND_RANGE_EXCEDEED 5 // No error code +#define EX_INVALID_OPCODE 6 // No error code +#define EX_DEVICE_NOT_AVAILABLE 7 // No error code +#define EX_DOUBLE_FAULT 8 // Yes (Zero) +#define EX_COPROCESSOR_SEGMENT_OVERRUN 9 // No error code +#define EX_INVALID_TSS 10 // Yes +#define EX_SEGMENT_NOT_PRESENT 11 // Yes +#define EX_STACK_SEGMENT_FAULT 12 // Yes +#define EX_GENERAL_PROTECTION 13 // Yes +#define EX_PAGE_FAULT 14 // Yes +#define EX_INTEL_RESERVED_1 15 // No +#define EX_FLOATING_POINT_ERROR 16 // No +#define EX_ALIGNEMENT_CHECK 17 // Yes (Zero) +#define EX_MACHINE_CHECK 18 // No +#define EX_INTEL_RESERVED_2 19 // No +#define EX_INTEL_RESERVED_3 20 // No +#define EX_INTEL_RESERVED_4 21 // No +#define EX_INTEL_RESERVED_5 22 // No +#define EX_INTEL_RESERVED_6 23 // No +#define EX_INTEL_RESERVED_7 24 // No +#define EX_INTEL_RESERVED_8 25 // No +#define EX_INTEL_RESERVED_9 26 // No +#define EX_INTEL_RESERVED_10 27 // No +#define EX_INTEL_RESERVED_11 28 // No +#define EX_INTEL_RESERVED_12 29 // No +#define EX_INTEL_RESERVED_13 30 // No +#define EX_INTEL_RESERVED_14 31 // No + +#define EFLAGS_IF (0x1 << 9) + +typedef struct registers { + uint32_t ds; // Data segment selector + uint32_t edi, esi, ebp, useless_esp, ebx, edx, ecx, eax; // Pushed by pusha. + uint32_t int_no, err_code; // Interrupt number and error code (if applicable) + uint32_t eip, cs, eflags, esp, ss; // Pushed by the processor automatically. +} registers_t; + +typedef void (*isr_handler_t)(registers_t*); + +void idt_init(); + +void idt_set_ex_handler(int number, isr_handler_t func); //Set exception handler +void idt_set_irq_handler(int number, isr_handler_t func); //Set IRQ handler + +void dbg_dump_registers(registers_t*); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/kmalloc.h b/src/kernel/include/kmalloc.h new file mode 100644 index 0000000..d4a9272 --- /dev/null +++ b/src/kernel/include/kmalloc.h @@ -0,0 +1,11 @@ +#pragma once + +#include <stdint.h> +#include <stddef.h> + +// Kernel memory allocator : one slab allocator for shared memory +// Thread-safe. + +void kmalloc_setup(); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/multiboot.h b/src/kernel/include/multiboot.h new file mode 100644 index 0000000..581337a --- /dev/null +++ b/src/kernel/include/multiboot.h @@ -0,0 +1,63 @@ +#pragma once + +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +struct multiboot_header_t{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +}; + +struct aout_symbol_table_t { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +}; + +struct elf_section_header_table_t { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +}; + +struct multiboot_info_t { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + struct aout_symbol_table_t aout_sym; + struct elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +}; + +struct module_t { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +}; + +struct memory_map_t { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +}; + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/paging.h b/src/kernel/include/paging.h new file mode 100644 index 0000000..44014a2 --- /dev/null +++ b/src/kernel/include/paging.h @@ -0,0 +1,31 @@ +#pragma once + +#include <sys.h> +#include <stdbool.h> + +struct page_directory; +typedef struct page_directory pagedir_t; + + +void paging_setup(void* kernel_data_end); + +pagedir_t *get_current_pagedir(); +pagedir_t *get_kernel_pagedir(); + +void switch_pagedir(pagedir_t *pd); + +// these functions are always relative to the currently mapped page directory +uint32_t pd_get_frame(void* vaddr); // get physical frame for virtual address +int pd_map_page(void* vaddr, uint32_t frame_id, bool rw); // returns nonzero on error +void pd_unmap_page(void* vaddr); // does nothing if page not mapped + +// Note on concurrency : we expect that multiple threads will not try to map/unmap +// pages in the same region at the same time. It can nevertheless happen that +// several threads try to map pages that belong to the same 4M-section, and in that +// case both might require the allocation of a new PT at the same location. These +// cases are well-handled (the pagedir_t type contains a mutex used for this) + +pagedir_t *create_pagedir(); // returns zero on error +void delete_pagedir(pagedir_t *pd); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h new file mode 100644 index 0000000..00ed1d7 --- /dev/null +++ b/src/kernel/include/process.h @@ -0,0 +1,43 @@ +#pragma once + +// Things described in this file are essentially a public interface +// All implementation details are hidden in process.c + +#include <thread.h> + +#include <hashtbl.h> +#include <buffer.h> + +#define PW_NOT_WAITING 0 +#define PW_WAIT_ANY_MSG 1 +#define PW_WAIT_MSG_ON_CHAN 2 + +#define PROCESS_MAILBOX_SIZE 42 + +typedef int chan_id_t; + +typedef struct chan_pair { + chan_id_t fst, snd; +} chan_pair_t; + +typedef struct message { + buffer_t *data; + chan_id_t chan_id; +} message_t; + +struct process; +typedef struct process process_t; + +process_t *new_process(entry_t entry, void* data, chan_pair_t *give_chans); + +chan_pair_t new_chan(); // not used very often, but still usefull +chan_id_t unbox_chan(chan_id_t chan, chan_id_t subchan); +void detach_chan(chan_id_t chan); // chan ID is freed + +int send_message(chan_id_t chan, buffer_t *msg); // nonnull on error (recipient queue is full) + +size_t await_message(); // returns the size of the first message to come +size_t await_message_on_chan(chan_id_t chan); // returns the size of the first message to come +message_t get_message(); // gets the first message in the queue (or nothing when queue is empty) + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/region.h b/src/kernel/include/region.h new file mode 100644 index 0000000..1fef582 --- /dev/null +++ b/src/kernel/include/region.h @@ -0,0 +1,38 @@ +#pragma once + +// Kernel virtual memory region allocator + +// This is entirely thread-safe + +#include <sys.h> +#include <paging.h> + +struct region_info; +typedef void (*page_fault_handler_t)(pagedir_t *pd, struct region_info *r, void* addr); + +typedef struct region_info { + void* addr; + size_t size; + char* type; + page_fault_handler_t pf; +} region_info_t; + +void region_allocator_init(void* kernel_data_end); + +void* region_alloc(size_t size, char* type, page_fault_handler_t pf); // returns 0 on error +region_info_t *find_region(void* addr); +void region_free(void* addr); + +// some usefull PF handlers +// default_allocator_pf_handler : just allocates new frames on page faults +void default_allocator_pf_handler(pagedir_t *pd, struct region_info *r, void* addr); + +// some functions for freeing regions and frames +// region_free_unmap_free : deletes a region and frees all frames that were mapped in it +void region_free_unmap_free(void* addr); +// region_free_unmap : deletes a region and unmaps all frames that were mapped in it, without freeing them +void region_free_unmap(void* addr); + +void dbg_print_region_info(); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/sys.h b/src/kernel/include/sys.h new file mode 100644 index 0000000..29735fa --- /dev/null +++ b/src/kernel/include/sys.h @@ -0,0 +1,53 @@ +#pragma once + +#include <debug.h> // common header +#include <config.h> + +static inline void outb(uint16_t port, uint8_t value) { + asm volatile("outb %1, %0" : : "dN"(port), "a"(value)); +} + +static inline void outw(uint16_t port, uint16_t value) { + asm volatile("outw %1, %0" : : "dN"(port), "a"(value)); +} + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile("inb %1, %0" : "=a"(ret) : "dN"(port)); + return ret; +} + +static inline uint16_t inw(uint16_t port) { + uint16_t ret; + asm volatile("inw %1, %0" : "=a"(ret) : "dN"(port)); + return ret; +} + +static inline void invlpg(void* addr) { + asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); +} + +#define BOCHS_BREAKPOINT asm volatile("xchg %bx, %bx") + + +// Utility functions for memory alignment + +#define PAGE_SIZE 0x1000 +#define PAGE_MASK 0xFFFFF000 +#define PAGE_ALIGN_DOWN(x) (((size_t)x) & PAGE_MASK) +#define PAGE_ALIGN_UP(x) ((((size_t)x)&(~PAGE_MASK)) == 0 ? ((size_t)x) : (((size_t)x) & PAGE_MASK) + PAGE_SIZE) +#define PAGE_ID(x) (((size_t)x) / PAGE_SIZE) +#define PAGE_SHIFT 12 +#define PT_SHIFT 10 +// PAGE_SHIFT + PT_SHIFT + PT_SHIFT = 32 +#define N_PAGES_IN_PT 1024 +#define PD_MIRROR_ADDR 0xFFC00000 // last 4MB used for PD mirroring +#define LAST_KERNEL_ADDR PD_MIRROR_ADDR +#define FIRST_KERNEL_PT (K_HIGHHALF_ADDR >> (PAGE_SHIFT+PT_SHIFT)) // must be 768 + +#define MASK4 0xFFFFFFFC +#define ALIGN4_UP(x) ((((size_t)x)&(~MASK4)) == 0 ? ((size_t)x) : (((size_t)x) & MASK4) + 4) +#define ALIGN4_DOWN(x) (((size_t)x)&MASK4) + + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/thread.h b/src/kernel/include/thread.h new file mode 100644 index 0000000..757ba00 --- /dev/null +++ b/src/kernel/include/thread.h @@ -0,0 +1,46 @@ +#pragma once + +#include <sys.h> +#include <paging.h> +#include <region.h> + +#define T_STATE_RUNNING 1 +#define T_STATE_PAUSED 2 +#define T_STATE_FINISHED 3 + +#define KPROC_STACK_SIZE 0x8000 // 8Kb + +#define TASK_SWITCH_FREQUENCY 100 // in herz + +typedef struct saved_context { + uint32_t *esp; + void (*eip)(); +} saved_context_t; + +struct process; +typedef struct thread { + saved_context_t ctx; + pagedir_t *current_pd_d; + + uint32_t state; + + region_info_t *stack_region; + + struct process *proc; // process : L1 data structure + + struct thread *next_in_queue; +} thread_t; + +typedef void (*entry_t)(void*); + +void threading_setup(entry_t cont, void* data); // never returns +thread_t *new_thread(entry_t entry, void* data); // thread is PAUSED, and must be resume_thread'ed + +extern thread_t *current_thread; + +void yield(); +void pause(); + +void resume_thread(thread_t *thread, bool run_at_once); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ |