aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/include')
l---------src/kernel/include/config.h1
-rw-r--r--src/kernel/include/dbglog.h8
-rw-r--r--src/kernel/include/frame.h14
-rw-r--r--src/kernel/include/gdt.h17
-rw-r--r--src/kernel/include/idt.h79
-rw-r--r--src/kernel/include/kmalloc.h11
-rw-r--r--src/kernel/include/multiboot.h63
-rw-r--r--src/kernel/include/paging.h31
-rw-r--r--src/kernel/include/process.h43
-rw-r--r--src/kernel/include/region.h38
-rw-r--r--src/kernel/include/sys.h53
-rw-r--r--src/kernel/include/thread.h46
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 :*/