From 7304e20731980078a7bfe138a20a8d13653fed7b Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Sat, 27 Feb 2021 18:24:38 +0100 Subject: Started basic paging port from skiftOS --- kernel/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/main.c') diff --git a/kernel/main.c b/kernel/main.c index 6be31bd..4d8165f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,7 +26,7 @@ void kernel_main(struct vid_info *vid_info) serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); serial_print("Serial connected.\n"); - heap_init(0x00f00000); + paging_install(); boot_passed = vid_info; -- cgit v1.2.3 From d50d3aeaaeaca4a75a807759a54d1d6ae8b5bce4 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Sun, 28 Feb 2021 13:40:45 +0100 Subject: Fixed memory mapping detection --- boot/entry.asm | 2 +- kernel/Makefile | 2 +- kernel/features/memory.c | 48 ++++++++++++++++++++++++++++++++---------------- kernel/inc/memory.h | 3 ++- kernel/link.ld | 3 +-- kernel/main.c | 6 +++--- 6 files changed, 40 insertions(+), 24 deletions(-) (limited to 'kernel/main.c') diff --git a/boot/entry.asm b/boot/entry.asm index 452de01..7285fb8 100644 --- a/boot/entry.asm +++ b/boot/entry.asm @@ -71,7 +71,7 @@ %define VESA_LFB_FLAG 0x4000 ; Enable LFB flag ; MMAP constants -%define MMAP_START 0x400 ; Starts at 0x400, ends at 0x500 +%define MMAP_START 0x500 ; Starts at 0x500, ends at 0x600 %define MMAP_SIZE 0x18 ; Struct size %define MMAP_SIG 0x0534d4150 ; Signature ("SMAP") %define MMAP_BIOS_MAGIC 0xe820 ; BIOS int 15h code to get address map diff --git a/kernel/Makefile b/kernel/Makefile index 8f090d1..6763185 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -35,5 +35,5 @@ all: compile compile: $(COBJS) @mkdir -p ../build/ - @$(LD) -N -ekernel_main -Ttext 0x00050000 -o ../build/kernel.elf -L../build/ $+ -lk + @$(LD) -N -z undefs -ekernel_main -Ttext 0x00050000 -o ../build/kernel.elf -L../build/ $+ -lk @$(LD) -N -Tlink.ld -o ../build/kernel.bin -L../build/ $+ -lk diff --git a/kernel/features/memory.c b/kernel/features/memory.c index aa861e1..f8e183a 100644 --- a/kernel/features/memory.c +++ b/kernel/features/memory.c @@ -104,8 +104,8 @@ void physical_free(u32 addr, u32 n) #define PDI(vaddr) ((vaddr) >> 22) #define PTI(vaddr) (((vaddr) >> 12) & 0x03ff) -struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; -struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; +static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; +static struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; u8 virtual_present(struct page_dir *dir, u32 vaddr) { @@ -217,11 +217,8 @@ void virtual_free(struct page_dir *dir, struct memory_range virtual_range) * Memory wrapper */ -/* extern u32 kernel_start; */ -/* extern u32 kernel_end; */ -// TODO! -u32 kernel_start = 0x50000; -u32 kernel_end = 0xa0000; +extern u32 kernel_start; +extern u32 kernel_end; struct memory_range memory_range_from_address(u32 base, u32 size) { @@ -353,12 +350,12 @@ struct page_dir *memory_dir_create(void) void memory_dir_destroy(struct page_dir *dir) { - for (u32 i = 256; i < 1024; i++) { + for (u32 i = 256; i < PAGE_COUNT; i++) { union page_dir_entry *dir_entry = &dir->entries[i]; if (dir_entry->bits.present) { struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - for (u32 j = 0; j < 1024; j++) { + for (u32 j = 0; j < PAGE_COUNT; j++) { union page_table_entry *table_entry = &table->entries[j]; if (table_entry->bits.present) physical_free(table_entry->bits.address * PAGE_SIZE, 1); @@ -375,9 +372,8 @@ void memory_dir_switch(struct page_dir *dir) paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); } -void memory_initialize(void) +void memory_initialize(struct mem_info *mem_info) { - memset(memory, 0xff, PAGE_COUNT * PAGE_COUNT / 8); for (u32 i = 0; i < 256; i++) { union page_dir_entry *entry = &kernel_dir.entries[i]; entry->bits.present = 1; @@ -386,23 +382,43 @@ void memory_initialize(void) entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; } - // TODO: Loop over mmap and set free + // Detect memory using E820 memory map + for (struct mmap_boot *p = mem_info->start; (u32)(p - mem_info->start) < mem_info->size; + p++) { + if (p->hbase || !p->acpi || !p->type) + continue; + + u32 size = p->lsize; + if (p->hsize) + size = U32_MAX; + + if (p->type == MEMORY_AVAILABLE) { + physical_set_free(p->lbase, size / PAGE_SIZE); + memory_total += size; + } else if (p->type == MEMORY_DEFECT) { + printf("Defect memory at 0x%x-0x%x!\n", p->lbase, p->lbase + size); + } + } memory_used = 0; - memory_total = 100 << 20; // 100Megs? + printf("Detected memory: %dKiB (%dMiB)\n", memory_total >> 10, memory_total >> 20); memory_map_identity(&kernel_dir, kernel_memory_range(), MEMORY_NONE); + + // Unmap NULL byte/page virtual_free(&kernel_dir, memory_range(0, PAGE_SIZE)); physical_set_used(0, 1); + memory_dir_switch(&kernel_dir); - printf("OK!\n"); + printf("Enabling...\n"); paging_enable(); + printf("Enabled!\n"); } #define HEAP_START 0x00f00000 -void paging_install(void) +void paging_install(struct mem_info *mem_info) { heap_init(HEAP_START); - memory_initialize(); + memory_initialize(mem_info); printf("OK!\n"); } diff --git a/kernel/inc/memory.h b/kernel/inc/memory.h index 4647c3e..812b052 100644 --- a/kernel/inc/memory.h +++ b/kernel/inc/memory.h @@ -3,6 +3,7 @@ #ifndef PAGING_H #define PAGING_H +#include #include /** @@ -60,7 +61,7 @@ struct page_dir { union page_dir_entry entries[PAGE_COUNT]; } PACKED; -void paging_install(void); +void paging_install(struct mem_info *mem_info); /** * Memory wrappers diff --git a/kernel/link.ld b/kernel/link.ld index e63bd71..5a63e33 100644 --- a/kernel/link.ld +++ b/kernel/link.ld @@ -5,9 +5,8 @@ phys = 0x00050000; SECTIONS { - kernel_start = .; - .text phys : AT(phys) { + kernel_start = .; code = .; *(.text) *(.rodata) diff --git a/kernel/main.c b/kernel/main.c index 4d8165f..16ae619 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -18,15 +18,15 @@ struct vid_info *boot_passed; -void kernel_main(struct vid_info *vid_info); // Decl -void kernel_main(struct vid_info *vid_info) +void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info); // Decl +void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) { // Serial connection serial_install(); serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); serial_print("Serial connected.\n"); - paging_install(); + paging_install(mem_info); boot_passed = vid_info; -- cgit v1.2.3 From acc4b7ccc133b64312e7ab1da3225b7945b1e13d Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Tue, 2 Mar 2021 19:04:53 +0100 Subject: very good this is --- kernel/Makefile | 2 +- kernel/features/load.c | 18 +- kernel/features/memory.c | 428 --------------------------------------------- kernel/features/mm.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/features/proc.c | 20 ++- kernel/features/syscall.c | 2 +- kernel/inc/memory.h | 80 --------- kernel/inc/mm.h | 87 +++++++++ kernel/inc/proc.h | 8 +- kernel/main.c | 2 +- 10 files changed, 557 insertions(+), 526 deletions(-) delete mode 100644 kernel/features/memory.c create mode 100644 kernel/features/mm.c delete mode 100644 kernel/inc/memory.h create mode 100644 kernel/inc/mm.h (limited to 'kernel/main.c') diff --git a/kernel/Makefile b/kernel/Makefile index 6763185..2db201b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -10,7 +10,7 @@ COBJS = main.o \ drivers/ide.o \ drivers/timer.o \ drivers/rtl8139.o \ - features/memory.o \ + features/mm.o \ features/fs.o \ features/load.o \ features/proc.o \ diff --git a/kernel/features/load.c b/kernel/features/load.c index 8a4aae3..610abf8 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -3,14 +3,19 @@ #include #include #include +#include #include +#define PROC_STACK_SIZE 0x4000 + void proc_load(struct proc *proc, void *data) { - u32 stack = (u32)malloc(0x2000) + 0x1000; + u32 stack; + memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_CLEAR, &stack); + u32 ptr = stack + PROC_STACK_SIZE - 1; - proc->regs.ebp = (u32)stack; - proc->regs.useresp = (u32)stack; + proc->regs.ebp = (u32)ptr; + proc->regs.useresp = (u32)ptr; proc->regs.eip = (u32)data; proc->entry = (u32)data; } @@ -19,12 +24,13 @@ int bin_load(const char *path, struct proc *proc) { struct stat s = { 0 }; vfs_stat(path, &s); - char *data = malloc(s.size); - if (!vfs_read(path, data, 0, s.size)) + u32 data; + memory_alloc(proc->page_dir, PAGE_ALIGN_UP(s.size), MEMORY_CLEAR, &data); + if (!vfs_read(path, (void *)data, 0, s.size)) return 1; strcpy(proc->name, path); - proc_load(proc, data); + proc_load(proc, (void *)data); return 0; } diff --git a/kernel/features/memory.c b/kernel/features/memory.c deleted file mode 100644 index 7813c56..0000000 --- a/kernel/features/memory.c +++ /dev/null @@ -1,428 +0,0 @@ -// Hugely inspired by the implementation in skiftOS: MIT License, Copyright (c) 2020 N. Van Bossuyt -// MIT License, Copyright (c) 2021 Marvin Borner - -#include -#include -#include -#include -#include - -#include - -/** - * Paging - */ - -void paging_disable(void) -{ - cr0_set(cr0_get() | 0x7fffffff); -} - -void paging_enable(void) -{ - cr0_set(cr0_get() | 0x80000000); -} - -void paging_switch_dir(u32 dir) -{ - cr3_set(dir); -} - -extern void paging_invalidate_tlb(void); - -/** - * Physical - */ - -static u32 memory_used = 0; -static u32 memory_total = 0; -static u8 memory[PAGE_COUNT * PAGE_COUNT / 8] = { 0 }; -#define PHYSICAL_IS_USED(addr) \ - (memory[(u32)(addr) / PAGE_SIZE / 8] & (1 << ((u32)(addr) / PAGE_SIZE % 8))) - -#define PHYSICAL_SET_USED(addr) \ - (memory[(u32)(addr) / PAGE_SIZE / 8] |= (1 << ((u32)(addr) / PAGE_SIZE % 8))) - -#define PHYSICAL_SET_FREE(addr) \ - (memory[(u32)(addr) / PAGE_SIZE / 8] &= ~(1 << ((u32)(addr) / PAGE_SIZE % 8))) - -u8 physical_is_used(u32 addr, u32 n) -{ - for (u32 i = 0; i < n; i++) { - if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) - return 1; - } - return 0; -} - -void physical_set_used(u32 addr, u32 n) -{ - for (u32 i = 0; i < n; i++) { - if (!PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { - memory_used += PAGE_SIZE; - PHYSICAL_SET_USED(addr + (i * PAGE_SIZE)); - } - } -} - -void physical_set_free(u32 addr, u32 n) -{ - for (u32 i = 0; i < n; i++) { - if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { - memory_used -= PAGE_SIZE; - PHYSICAL_SET_FREE(addr + (i * PAGE_SIZE)); - } - } -} - -u32 physical_alloc(u32 n) -{ - for (u32 i = 0; i < (memory_total / PAGE_SIZE); i++) { - u32 addr = i * PAGE_SIZE; - if (!physical_is_used(addr, n)) { - physical_set_used(addr, n); - return addr; - } - } - - panic("Out of physical memory!\n"); - return 0; -} - -void physical_free(u32 addr, u32 n) -{ - physical_set_free(addr, n); -} - -/** - * Virtual - */ - -#define PDI(vaddr) ((vaddr) >> 22) -#define PTI(vaddr) (((vaddr) >> 12) & 0x03ff) - -static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; -static struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; - -u8 virtual_present(struct page_dir *dir, u32 vaddr) -{ - u32 pdi = PDI(vaddr); - u32 pti = PTI(vaddr); - - union page_dir_entry *dir_entry = &dir->entries[pdi]; - if (!dir_entry->bits.present) - return 0; - - struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - union page_table_entry *table_entry = &table->entries[pti]; - if (!table_entry->bits.present) - return 0; - - return 1; -} - -u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) -{ - u32 pdi = PDI(vaddr); - u32 pti = PTI(vaddr); - - union page_dir_entry *dir_entry = &dir->entries[pdi]; - struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - union page_table_entry *table_entry = &table->entries[pti]; - - return (table_entry->bits.address * PAGE_SIZE) + (vaddr & (PAGE_SIZE - 1)); -} - -void memory_alloc_identity(struct page_dir *dir, u32 flags, u32 *out); -void virtual_map(struct page_dir *dir, u32 vaddr, u32 paddr, u32 n, u8 user) -{ - for (u32 i = 0; i < n; i++) { - u32 offset = i * PAGE_SIZE; - u32 pdi = PDI(vaddr + offset); - u32 pti = PTI(vaddr + offset); - - union page_dir_entry *dir_entry = &dir->entries[pdi]; - struct page_table *table = - (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - union page_table_entry *table_entry = &table->entries[pti]; - - if (!dir_entry->bits.present) { - memory_alloc_identity(dir, MEMORY_CLEAR, (u32 *)&table); - dir_entry->bits.present = 1; - dir_entry->bits.writable = 1; - dir_entry->bits.user = user; - dir_entry->bits.address = (u32)table >> 12; - } - - table_entry->bits.present = 1; - table_entry->bits.writable = 1; - table_entry->bits.user = user; - table_entry->bits.address = (paddr + offset) >> 12; - } - - paging_invalidate_tlb(); -} - -struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, - u32 flags) -{ - u8 is_user = flags & MEMORY_USER; - u32 vaddr = 0; - u32 size = 0; - for (u32 i = (is_user ? 256 : 1) * PAGE_COUNT; - i < (is_user ? PAGE_COUNT : 256) * PAGE_COUNT; i++) { - u32 addr = i * PAGE_SIZE; - if (!virtual_present(dir, addr)) { - if (size == 0) - vaddr = addr; - size += PAGE_SIZE; - if (size == physical_range.size) { - virtual_map(dir, vaddr, physical_range.base, - physical_range.size / PAGE_SIZE, is_user); - return memory_range(vaddr, size); - } - } else { - size = 0; - } - } - - panic("Out of virtual memory!\n"); - return memory_range(0, 0); -} - -void virtual_free(struct page_dir *dir, struct memory_range virtual_range) -{ - for (u32 i = 0; i < virtual_range.size / PAGE_SIZE; i++) { - u32 offset = i * PAGE_SIZE; - - u32 pdi = PDI(virtual_range.base + offset); - u32 pti = PTI(virtual_range.base + offset); - - union page_dir_entry *dir_entry = &dir->entries[pdi]; - struct page_table *table = - (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - union page_table_entry *table_entry = &table->entries[pti]; - - if (table_entry->bits.present) - table_entry->uint = 0; - } - - paging_invalidate_tlb(); -} - -/** - * Memory wrapper - */ - -extern u32 kernel_start; -extern u32 kernel_end; - -struct memory_range memory_range_from_address(u32 base, u32 size) -{ - u32 align = PAGE_SIZE - base % PAGE_SIZE; - - if (base % PAGE_SIZE == 0) { - align = 0; - } - - base += align; - size -= align; - - size -= size % PAGE_SIZE; - - return memory_range(base, size); -} - -struct memory_range memory_range_around_address(u32 base, u32 size) -{ - u32 align = base % PAGE_SIZE; - - base -= align; - size += align; - - size += PAGE_SIZE - size % PAGE_SIZE; - - return memory_range(base, size); -} - -static struct memory_range kernel_memory_range(void) -{ - return memory_range_around_address((u32)&kernel_start, - (u32)&kernel_end - (u32)&kernel_start); -} - -void memory_map_identity(struct page_dir *dir, struct memory_range range, u32 flags) -{ - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); - - u32 page_count = range.size / PAGE_SIZE; - physical_set_used(range.base, page_count); - virtual_map(dir, range.base, range.base, page_count, flags & MEMORY_USER); - - if (flags & MEMORY_CLEAR) - memset((void *)range.base, 0, range.size); -} - -void memory_map(struct page_dir *dir, struct memory_range range, u32 flags) -{ - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); - - for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { - u32 vaddr = range.base + i * PAGE_SIZE; - if (!virtual_present(dir, vaddr)) { - u32 paddr = physical_alloc(1); - virtual_map(dir, vaddr, paddr, 1, flags & MEMORY_USER); - } - } - - if (flags & MEMORY_CLEAR) - memset((void *)range.base, 0, range.size); -} - -void memory_alloc_identity(struct page_dir *dir, u32 flags, u32 *out) -{ - for (u32 i = 1; i < 256 * PAGE_COUNT; i++) { - u32 addr = i * PAGE_SIZE; - if (!virtual_present(dir, addr) && !physical_is_used(addr, 1)) { - physical_set_used(addr, 1); - virtual_map(dir, addr, addr, 1, flags & MEMORY_USER); - - if (flags & MEMORY_CLEAR) - memset((void *)addr, 0, PAGE_SIZE); - - *out = addr; - - return; - } - } - - *out = 0; - panic("Out of memory!\n"); -} - -void memory_alloc(struct page_dir *dir, u32 size, u32 flags, u32 *out) -{ - assert(size && PAGE_ALIGNED(size)); - *out = 0; - - u32 page_count = size / PAGE_SIZE; - u32 paddr = physical_alloc(page_count); - assert(paddr); - u32 vaddr = virtual_alloc(dir, memory_range(paddr, size), flags).base; - assert(vaddr); - if (flags & MEMORY_CLEAR) - memset((void *)vaddr, 0, page_count * PAGE_SIZE); - *out = vaddr; -} - -void memory_free(struct page_dir *dir, struct memory_range range) -{ - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); - - for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { - u32 vaddr = range.base + i * PAGE_SIZE; - if (virtual_present(dir, vaddr)) { - physical_free(virtual_to_physical(dir, vaddr), 1); - virtual_free(dir, memory_range(vaddr, PAGE_SIZE)); - } - } -} - -struct page_dir *memory_dir_create(void) -{ - struct page_dir *dir = NULL; - memory_alloc(&kernel_dir, sizeof(*dir), MEMORY_CLEAR, (u32 *)&dir); - memset(dir, 0, sizeof(*dir)); - - for (u32 i = 0; i < 256; i++) { - union page_dir_entry *entry = &dir->entries[i]; - entry->bits.present = 1; - entry->bits.writable = 1; - entry->bits.user = 0; - entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; - } - - return dir; -} - -void memory_dir_destroy(struct page_dir *dir) -{ - for (u32 i = 256; i < PAGE_COUNT; i++) { - union page_dir_entry *dir_entry = &dir->entries[i]; - if (dir_entry->bits.present) { - struct page_table *table = - (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); - for (u32 j = 0; j < PAGE_COUNT; j++) { - union page_table_entry *table_entry = &table->entries[j]; - if (table_entry->bits.present) - physical_free(table_entry->bits.address * PAGE_SIZE, 1); - } - - memory_free(&kernel_dir, memory_range((u32)table, sizeof(*table))); - } - } - memory_free(&kernel_dir, memory_range((u32)dir, sizeof(*dir))); -} - -void memory_dir_switch(struct page_dir *dir) -{ - paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); -} - -void memory_initialize(struct mem_info *mem_info) -{ - for (u32 i = 0; i < 256; i++) { - union page_dir_entry *entry = &kernel_dir.entries[i]; - entry->bits.present = 1; - entry->bits.writable = 1; - entry->bits.user = 0; - entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; - } - - // Detect memory using E820 memory map - for (struct mmap_boot *p = mem_info->start; (u32)(p - mem_info->start) < mem_info->size; - p++) { - if (p->hbase || !p->acpi || !p->type) - continue; - - u32 size = p->lsize; - if (p->hsize) - size = U32_MAX - p->lbase; - - /* printf("Memory region: %x-%x\n", p->lbase, p->lbase + size); */ - if (p->type == MEMORY_AVAILABLE) { - physical_set_free(p->lbase, size / PAGE_SIZE); - memory_total += size; - } else if (p->type == MEMORY_DEFECT) { - printf("Defect memory at 0x%x-0x%x!\n", p->lbase, p->lbase + size); - } - } - - memory_used = 0; - printf("Detected memory: %dKiB (%dMiB)\n", memory_total >> 10, memory_total >> 20); - - // Map kernel - memory_map_identity(&kernel_dir, kernel_memory_range(), MEMORY_NONE); - - // Map kernel stack - memory_map_identity(&kernel_dir, - memory_range_around_address(STACK_START - STACK_SIZE, STACK_SIZE), - MEMORY_NONE); - - // Map kernel heap - memory_map_identity(&kernel_dir, memory_range_around_address(HEAP_START, HEAP_INIT_SIZE), - MEMORY_NONE); - - // Unmap NULL byte/page - virtual_free(&kernel_dir, memory_range(0, PAGE_SIZE)); - physical_set_used(0, 1); - - memory_dir_switch(&kernel_dir); - paging_enable(); -} - -void paging_install(struct mem_info *mem_info) -{ - memory_initialize(mem_info); - heap_init(HEAP_START); -} diff --git a/kernel/features/mm.c b/kernel/features/mm.c new file mode 100644 index 0000000..ccc2727 --- /dev/null +++ b/kernel/features/mm.c @@ -0,0 +1,436 @@ +// Hugely inspired by the implementation in skiftOS: MIT License, Copyright (c) 2020 N. Van Bossuyt +// MIT License, Copyright (c) 2021 Marvin Borner + +#include +#include +#include +#include +#include + +#include + +/** + * Paging + */ + +void paging_disable(void) +{ + cr0_set(cr0_get() | 0x7fffffff); +} + +void paging_enable(void) +{ + cr0_set(cr0_get() | 0x80000000); +} + +void paging_switch_dir(u32 dir) +{ + cr3_set(dir); +} + +extern void paging_invalidate_tlb(void); + +/** + * Physical + */ + +static u32 memory_used = 0; +static u32 memory_total = 0; +static u8 memory[PAGE_COUNT * PAGE_COUNT / 8] = { 0 }; +#define PHYSICAL_IS_USED(addr) \ + (memory[(u32)(addr) / PAGE_SIZE / 8] & (1 << ((u32)(addr) / PAGE_SIZE % 8))) + +#define PHYSICAL_SET_USED(addr) \ + (memory[(u32)(addr) / PAGE_SIZE / 8] |= (1 << ((u32)(addr) / PAGE_SIZE % 8))) + +#define PHYSICAL_SET_FREE(addr) \ + (memory[(u32)(addr) / PAGE_SIZE / 8] &= ~(1 << ((u32)(addr) / PAGE_SIZE % 8))) + +u8 physical_is_used(u32 addr, u32 n) +{ + for (u32 i = 0; i < n; i++) { + if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) + return 1; + } + return 0; +} + +void physical_set_used(u32 addr, u32 n) +{ + for (u32 i = 0; i < n; i++) { + if (!PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { + memory_used += PAGE_SIZE; + PHYSICAL_SET_USED(addr + (i * PAGE_SIZE)); + } + } +} + +void physical_set_free(u32 addr, u32 n) +{ + for (u32 i = 0; i < n; i++) { + if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { + memory_used -= PAGE_SIZE; + PHYSICAL_SET_FREE(addr + (i * PAGE_SIZE)); + } + } +} + +u32 physical_alloc(u32 n) +{ + for (u32 i = 0; i < (memory_total / PAGE_SIZE); i++) { + u32 addr = i * PAGE_SIZE; + if (!physical_is_used(addr, n)) { + physical_set_used(addr, n); + return addr; + } + } + + panic("Out of physical memory!\n"); + return 0; +} + +void physical_free(u32 addr, u32 n) +{ + physical_set_free(addr, n); +} + +/** + * Virtual + */ + +#define PDI(vaddr) ((vaddr) >> 22) +#define PTI(vaddr) (((vaddr) >> 12) & 0x03ff) + +static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; +static struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; + +u8 virtual_present(struct page_dir *dir, u32 vaddr) +{ + u32 pdi = PDI(vaddr); + u32 pti = PTI(vaddr); + + union page_dir_entry *dir_entry = &dir->entries[pdi]; + if (!dir_entry->bits.present) + return 0; + + struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + union page_table_entry *table_entry = &table->entries[pti]; + if (!table_entry->bits.present) + return 0; + + return 1; +} + +u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) +{ + u32 pdi = PDI(vaddr); + u32 pti = PTI(vaddr); + + union page_dir_entry *dir_entry = &dir->entries[pdi]; + struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + union page_table_entry *table_entry = &table->entries[pti]; + + return (table_entry->bits.address * PAGE_SIZE) + (vaddr & (PAGE_SIZE - 1)); +} + +void memory_alloc_identity(struct page_dir *dir, u32 flags, u32 *out); +void virtual_map(struct page_dir *dir, u32 vaddr, u32 paddr, u32 n, u8 user) +{ + for (u32 i = 0; i < n; i++) { + u32 offset = i * PAGE_SIZE; + u32 pdi = PDI(vaddr + offset); + u32 pti = PTI(vaddr + offset); + + union page_dir_entry *dir_entry = &dir->entries[pdi]; + struct page_table *table = + (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + union page_table_entry *table_entry = &table->entries[pti]; + + if (!dir_entry->bits.present) { + memory_alloc_identity(dir, MEMORY_CLEAR, (u32 *)&table); + dir_entry->bits.present = 1; + dir_entry->bits.writable = 1; + dir_entry->bits.user = user; + dir_entry->bits.address = (u32)table >> 12; + } + + table_entry->bits.present = 1; + table_entry->bits.writable = 1; + table_entry->bits.user = user; + table_entry->bits.address = (paddr + offset) >> 12; + } + + paging_invalidate_tlb(); +} + +struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, + u32 flags) +{ + u8 is_user = flags & MEMORY_USER; + u32 vaddr = 0; + u32 size = 0; + for (u32 i = (is_user ? 256 : 1) * PAGE_COUNT; + i < (is_user ? PAGE_COUNT : 256) * PAGE_COUNT; i++) { + u32 addr = i * PAGE_SIZE; + if (!virtual_present(dir, addr)) { + if (size == 0) + vaddr = addr; + size += PAGE_SIZE; + if (size == physical_range.size) { + virtual_map(dir, vaddr, physical_range.base, + physical_range.size / PAGE_SIZE, is_user); + return memory_range(vaddr, size); + } + } else { + size = 0; + } + } + + panic("Out of virtual memory!\n"); + return memory_range(0, 0); +} + +void virtual_free(struct page_dir *dir, struct memory_range virtual_range) +{ + for (u32 i = 0; i < virtual_range.size / PAGE_SIZE; i++) { + u32 offset = i * PAGE_SIZE; + + u32 pdi = PDI(virtual_range.base + offset); + u32 pti = PTI(virtual_range.base + offset); + + union page_dir_entry *dir_entry = &dir->entries[pdi]; + struct page_table *table = + (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + union page_table_entry *table_entry = &table->entries[pti]; + + if (table_entry->bits.present) + table_entry->uint = 0; + } + + paging_invalidate_tlb(); +} + +/** + * Memory wrapper + */ + +extern u32 kernel_start; +extern u32 kernel_end; + +struct memory_range memory_range_from_address(u32 base, u32 size) +{ + u32 align = PAGE_SIZE - base % PAGE_SIZE; + + if (base % PAGE_SIZE == 0) { + align = 0; + } + + base += align; + size -= align; + + size -= size % PAGE_SIZE; + + return memory_range(base, size); +} + +struct memory_range memory_range_around_address(u32 base, u32 size) +{ + u32 align = base % PAGE_SIZE; + + base -= align; + size += align; + + size += PAGE_SIZE - size % PAGE_SIZE; + + return memory_range(base, size); +} + +static struct memory_range kernel_memory_range(void) +{ + return memory_range_around_address((u32)&kernel_start, + (u32)&kernel_end - (u32)&kernel_start); +} + +void memory_map_identity(struct page_dir *dir, struct memory_range range, u32 flags) +{ + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + u32 page_count = range.size / PAGE_SIZE; + physical_set_used(range.base, page_count); + virtual_map(dir, range.base, range.base, page_count, flags & MEMORY_USER); + + if (flags & MEMORY_CLEAR) + memset((void *)range.base, 0, range.size); +} + +void memory_map(struct page_dir *dir, struct memory_range range, u32 flags) +{ + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { + u32 vaddr = range.base + i * PAGE_SIZE; + if (!virtual_present(dir, vaddr)) { + u32 paddr = physical_alloc(1); + virtual_map(dir, vaddr, paddr, 1, flags & MEMORY_USER); + } + } + + if (flags & MEMORY_CLEAR) + memset((void *)range.base, 0, range.size); +} + +void memory_alloc_identity(struct page_dir *dir, u32 flags, u32 *out) +{ + for (u32 i = 1; i < 256 * PAGE_COUNT; i++) { + u32 addr = i * PAGE_SIZE; + if (!virtual_present(dir, addr) && !physical_is_used(addr, 1)) { + physical_set_used(addr, 1); + virtual_map(dir, addr, addr, 1, flags & MEMORY_USER); + + if (flags & MEMORY_CLEAR) + memset((void *)addr, 0, PAGE_SIZE); + + *out = addr; + + return; + } + } + + *out = 0; + panic("Out of memory!\n"); +} + +void memory_alloc(struct page_dir *dir, u32 size, u32 flags, u32 *out) +{ + assert(size && PAGE_ALIGNED(size)); + *out = 0; + + u32 page_count = size / PAGE_SIZE; + u32 paddr = physical_alloc(page_count); + assert(paddr); + u32 vaddr = virtual_alloc(dir, memory_range(paddr, size), flags).base; + assert(vaddr); + if (flags & MEMORY_CLEAR) + memset((void *)vaddr, 0, page_count * PAGE_SIZE); + *out = vaddr; +} + +void memory_free(struct page_dir *dir, struct memory_range range) +{ + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { + u32 vaddr = range.base + i * PAGE_SIZE; + if (virtual_present(dir, vaddr)) { + physical_free(virtual_to_physical(dir, vaddr), 1); + virtual_free(dir, memory_range(vaddr, PAGE_SIZE)); + } + } +} + +struct page_dir *memory_dir_create(void) +{ + struct page_dir *dir = NULL; + memory_alloc(&kernel_dir, sizeof(*dir), MEMORY_CLEAR, (u32 *)&dir); + memset(dir, 0, sizeof(*dir)); + + for (u32 i = 0; i < 256; i++) { + union page_dir_entry *entry = &dir->entries[i]; + entry->bits.present = 1; + entry->bits.writable = 1; + entry->bits.user = 0; + entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; + } + + return dir; +} + +void memory_dir_destroy(struct page_dir *dir) +{ + for (u32 i = 256; i < PAGE_COUNT; i++) { + union page_dir_entry *dir_entry = &dir->entries[i]; + if (dir_entry->bits.present) { + struct page_table *table = + (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + for (u32 j = 0; j < PAGE_COUNT; j++) { + union page_table_entry *table_entry = &table->entries[j]; + if (table_entry->bits.present) + physical_free(table_entry->bits.address * PAGE_SIZE, 1); + } + + memory_free(&kernel_dir, memory_range((u32)table, sizeof(*table))); + } + } + memory_free(&kernel_dir, memory_range((u32)dir, sizeof(*dir))); +} + +void memory_dir_switch(struct page_dir *dir) +{ + paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); +} + +struct page_dir *memory_kernel_dir(void) +{ + return &kernel_dir; +} + +void memory_initialize(struct mem_info *mem_info) +{ + for (u32 i = 0; i < 256; i++) { + union page_dir_entry *entry = &kernel_dir.entries[i]; + entry->bits.present = 1; + entry->bits.writable = 1; + entry->bits.user = 0; + entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; + } + + // Detect memory using E820 memory map + for (struct mmap_boot *p = mem_info->start; (u32)(p - mem_info->start) < mem_info->size; + p++) { + if (p->hbase || !p->acpi || !p->type) + continue; + + u32 size = p->lsize; + if (p->hsize) + size = U32_MAX - p->lbase; + + /* printf("Memory region: %x-%x\n", p->lbase, p->lbase + size); */ + if (p->type == MEMORY_AVAILABLE) { + physical_set_free(p->lbase, size / PAGE_SIZE); + memory_total += size; + } else if (p->type == MEMORY_DEFECT) { + printf("Defect memory at 0x%x-0x%x!\n", p->lbase, p->lbase + size); + } + } + + memory_used = 0; + printf("Detected memory: %dKiB (%dMiB)\n", memory_total >> 10, memory_total >> 20); + + // Map kernel + memory_map_identity(&kernel_dir, kernel_memory_range(), MEMORY_NONE); + + // Map kernel stack + memory_map_identity(&kernel_dir, + memory_range_around_address(STACK_START - STACK_SIZE, STACK_SIZE), + MEMORY_NONE); + + // Map kernel heap + memory_map_identity(&kernel_dir, memory_range_around_address(HEAP_START, HEAP_INIT_SIZE), + MEMORY_NONE); + + // TODO: Map something, idk? Triple fault prevention? + memory_map_identity(&kernel_dir, memory_range_around_address(0x7000, 0x1000), MEMORY_NONE); + + // Unmap NULL byte/page + virtual_free(&kernel_dir, memory_range(0, PAGE_SIZE)); + physical_set_used(0, 1); + + memory_dir_switch(&kernel_dir); + paging_enable(); +} + +void paging_install(struct mem_info *mem_info) +{ + memory_initialize(mem_info); + heap_init(HEAP_START); +} diff --git a/kernel/features/proc.c b/kernel/features/proc.c index cdbe8b1..bbe675e 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ void scheduler(struct regs *regs) } memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); + memory_dir_switch(((struct proc *)current->data)->page_dir); if (regs->cs != GDT_USER_CODE_OFFSET) { regs->gs = GDT_USER_DATA_OFFSET; @@ -103,7 +105,7 @@ u8 proc_super(void) { struct proc *proc = proc_current(); if (proc) - return proc->super; + return proc->priv == PROC_PRIV_ROOT || proc->priv == PROC_PRIV_KERNEL; else if (current_pid == 0) return 1; // Kernel has super permissions else @@ -237,14 +239,19 @@ end: p->state = PROC_SLEEPING; } -struct proc *proc_make(void) +struct proc *proc_make(enum proc_priv priv) { struct proc *proc = zalloc(sizeof(*proc)); proc->pid = current_pid++; - proc->super = 0; + proc->priv = priv; proc->messages = stack_new(); proc->state = PROC_RUNNING; + if (priv == PROC_PRIV_KERNEL) + proc->page_dir = memory_kernel_dir(); + else + proc->page_dir = memory_dir_create(); + if (current) list_add(proc_list, proc); @@ -465,20 +472,20 @@ void proc_init(void) vfs_mount(dev, "/proc/"); // Idle proc - struct proc *kernel_proc = proc_make(); + struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); void (*func)(void) = kernel_idle; proc_load(kernel_proc, *(void **)&func); strcpy(kernel_proc->name, "idle"); kernel_proc->state = PROC_SLEEPING; idle_proc = list_add(proc_list, kernel_proc); - struct node *new = list_add(proc_list, proc_make()); + // Init proc (root) + struct node *new = list_add(proc_list, proc_make(PROC_PRIV_ROOT)); bin_load("/bin/init", new->data); current = new; _eip = ((struct proc *)new->data)->regs.eip; _esp = ((struct proc *)new->data)->regs.useresp; - ((struct proc *)new->data)->super = 1; u32 argc = 2; char **argv = malloc(sizeof(*argv) * (argc + 1)); @@ -491,6 +498,7 @@ void proc_init(void) printf("Jumping to userspace!\n"); proc_jump_userspace(); + memory_dir_switch(((struct proc *)new->data)->page_dir); while (1) { }; } diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 61c7479..b3e69e0 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -62,7 +62,7 @@ static void syscall_handler(struct regs *r) } case SYS_EXEC: { char *path = (char *)r->ebx; - struct proc *proc = proc_make(); + struct proc *proc = proc_make(PROC_PRIV_NONE); r->eax = (u32)bin_load(path, proc); u32 argc = 3; // TODO: Add argc evaluator char **argv = malloc(sizeof(*argv) * (argc + 1)); diff --git a/kernel/inc/memory.h b/kernel/inc/memory.h deleted file mode 100644 index 812b052..0000000 --- a/kernel/inc/memory.h +++ /dev/null @@ -1,80 +0,0 @@ -// MIT License, Copyright (c) 2021 Marvin Borner - -#ifndef PAGING_H -#define PAGING_H - -#include -#include - -/** - * Physical - */ - -/** - * Virtual - */ - -#define PAGE_SIZE 0x1000 -#define PAGE_COUNT 1024 -#define PAGE_ALIGN(x) ((x) + PAGE_SIZE - ((x) % PAGE_SIZE)) -#define PAGE_ALIGNED(x) ((x) % PAGE_SIZE == 0) - -union page_table_entry { - struct PACKED { - u32 present : 1; - u32 writable : 1; - u32 user : 1; - u32 write_through : 1; - u32 cache_disable : 1; - u32 accessed : 1; - u32 dirty : 1; - u32 attribute : 1; - u32 global : 1; - u32 available : 3; - u32 address : 20; - } bits; - u32 uint; -} PACKED; - -struct page_table { - union page_table_entry entries[PAGE_COUNT]; -} PACKED; - -union page_dir_entry { - struct PACKED { - u32 present : 1; - u32 writable : 1; - u32 user : 1; - u32 write_through : 1; - u32 cache_disable : 1; - u32 accessed : 1; - u32 reserved : 1; - u32 page_size : 1; - u32 global : 1; - u32 available : 3; - u32 address : 20; - } bits; - u32 uint; -} PACKED; - -struct page_dir { - union page_dir_entry entries[PAGE_COUNT]; -} PACKED; - -void paging_install(struct mem_info *mem_info); - -/** - * Memory wrappers - */ - -#define MEMORY_NONE (0 << 0) -#define MEMORY_USER (1 << 0) -#define MEMORY_CLEAR (1 << 1) -#define memory_range(base, size) ((struct memory_range){ (base), (size) }) - -struct memory_range { - u32 base; - u32 size; -}; - -#endif diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h new file mode 100644 index 0000000..00d9e4b --- /dev/null +++ b/kernel/inc/mm.h @@ -0,0 +1,87 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef PAGING_H +#define PAGING_H + +#include +#include + +/** + * Physical + */ + +/** + * Virtual + */ + +#define PAGE_SIZE 0x1000 +#define PAGE_COUNT 1024 +#define PAGE_ALIGN(x) ((x) + PAGE_SIZE - ((x) % PAGE_SIZE)) +#define PAGE_ALIGNED(x) ((x) % PAGE_SIZE == 0) +#define PAGE_ALIGN_UP(x) (((x) % PAGE_SIZE == 0) ? (x) : (x) + PAGE_SIZE - ((x) % PAGE_SIZE)) +#define PAGE_ALIGN_DOWN(x) ((x) - ((x) % PAGE_SIZE)) + +union page_table_entry { + struct PACKED { + u32 present : 1; + u32 writable : 1; + u32 user : 1; + u32 write_through : 1; + u32 cache_disable : 1; + u32 accessed : 1; + u32 dirty : 1; + u32 attribute : 1; + u32 global : 1; + u32 available : 3; + u32 address : 20; + } bits; + u32 uint; +} PACKED; + +struct page_table { + union page_table_entry entries[PAGE_COUNT]; +} PACKED; + +union page_dir_entry { + struct PACKED { + u32 present : 1; + u32 writable : 1; + u32 user : 1; + u32 write_through : 1; + u32 cache_disable : 1; + u32 accessed : 1; + u32 reserved : 1; + u32 page_size : 1; + u32 global : 1; + u32 available : 3; + u32 address : 20; + } bits; + u32 uint; +} PACKED; + +struct page_dir { + union page_dir_entry entries[PAGE_COUNT]; +} PACKED; + +void paging_install(struct mem_info *mem_info); + +/** + * Memory wrappers + */ + +#define MEMORY_NONE (0 << 0) +#define MEMORY_USER (1 << 0) +#define MEMORY_CLEAR (1 << 1) +#define memory_range(base, size) ((struct memory_range){ (base), (size) }) + +struct memory_range { + u32 base; + u32 size; +}; + +struct page_dir *memory_dir_create(void); +void memory_dir_switch(struct page_dir *dir); +void memory_alloc(struct page_dir *dir, u32 size, u32 flags, u32 *out); +struct page_dir *memory_kernel_dir(void); + +#endif diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 272a3ac..de4eb84 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -9,7 +9,7 @@ #include #include -#define PROC_QUANTUM 10 // Milliseconds or something // TODO +#define PROC_QUANTUM 42 // Milliseconds or something // TODO #define EFLAGS_ALWAYS 0x2 // Always one #define EFLAGS_INTERRUPTS 0x200 // Enable interrupts @@ -23,6 +23,7 @@ #define STREAM_MAX_SIZE 4096 enum stream_defaults { STREAM_IN, STREAM_OUT, STREAM_ERR, STREAM_LOG, STREAM_UNKNOWN = -1 }; +enum proc_priv { PROC_PRIV_NONE, PROC_PRIV_ROOT, PROC_PRIV_KERNEL }; enum proc_state { PROC_RUNNING, PROC_SLEEPING }; enum proc_wait_type { PROC_WAIT_DEV, PROC_WAIT_MSG }; @@ -47,9 +48,10 @@ struct stream { struct proc { u32 pid; u32 entry; - u8 super; + u8 priv; char name[32]; struct stream streams[4]; + struct page_dir *page_dir; struct regs regs; struct proc_wait wait; // dev_id enum proc_state state; @@ -67,6 +69,6 @@ void proc_yield(struct regs *r); void proc_clear_quantum(void); void proc_enable_waiting(u32 id, enum proc_wait_type type); void proc_wait_for(u32 id, enum proc_wait_type type, u32 func_ptr); -struct proc *proc_make(void); +struct proc *proc_make(enum proc_priv priv); #endif diff --git a/kernel/main.c b/kernel/main.c index 16ae619..b46db0d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From d47e627d0006e038dcd1c34b9015c3370f7b4b0c Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Tue, 2 Mar 2021 23:34:39 +0100 Subject: Getting closer! --- kernel/drivers/interrupts.c | 38 +++++++++++++++++++++----------------- kernel/features/load.c | 13 ++++++------- kernel/features/mm.c | 32 +++++++++++++++++++++++++++++++- kernel/features/proc.c | 11 +++++------ kernel/inc/interrupts.h | 1 + kernel/inc/load.h | 2 +- kernel/main.c | 5 +++++ 7 files changed, 70 insertions(+), 32 deletions(-) (limited to 'kernel/main.c') diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index fa455d7..55926b7 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -169,26 +169,30 @@ void isr_uninstall_handler(int isr) isr_routines[isr] = 0; } -void isr_handler(struct regs *r); -void isr_handler(struct regs *r) +void isr_panic(struct regs *r) { - if (r->int_no <= 32) { - struct proc *proc = proc_current(); - printf("%s Exception at 0x%x, exiting!\n", isr_exceptions[r->int_no], r->eip); - if (proc) { - printf("\t-> Exception occurred in %s at addr 0x%x\n", proc->name, - r->eip - proc->entry); - proc_exit(proc, 1); - } else { - __asm__ volatile("cli\nhlt"); - } - proc_yield(r); + struct proc *proc = proc_current(); + printf("%s Exception (%x) at 0x%x, exiting!\n", isr_exceptions[r->int_no], r->err_code, + r->eip); + if (proc) { + printf("\t-> Exception occurred in %s at addr 0x%x\n", proc->name, + r->eip - proc->entry); + proc_exit(proc, 1); } else { - // Execute fault handler if exists - void (*handler)(struct regs * r) = isr_routines[r->int_no]; - if (handler) - handler(r); + __asm__ volatile("cli\nhlt"); } + proc_yield(r); +} + +void isr_handler(struct regs *r); +void isr_handler(struct regs *r) +{ + // Execute fault handler if exists + void (*handler)(struct regs * r) = isr_routines[r->int_no]; + if (handler) + handler(r); + else + isr_panic(r); } static void isr_install(void) diff --git a/kernel/features/load.c b/kernel/features/load.c index 610abf8..4b3f8ea 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -8,16 +8,15 @@ #define PROC_STACK_SIZE 0x4000 -void proc_load(struct proc *proc, void *data) +void proc_load(struct proc *proc, u32 entry) { u32 stack; memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_CLEAR, &stack); - u32 ptr = stack + PROC_STACK_SIZE - 1; - proc->regs.ebp = (u32)ptr; - proc->regs.useresp = (u32)ptr; - proc->regs.eip = (u32)data; - proc->entry = (u32)data; + proc->regs.ebp = stack; + proc->regs.useresp = stack; + proc->regs.eip = entry; + proc->entry = entry; } int bin_load(const char *path, struct proc *proc) @@ -30,7 +29,7 @@ int bin_load(const char *path, struct proc *proc) return 1; strcpy(proc->name, path); - proc_load(proc, (void *)data); + proc_load(proc, data); return 0; } diff --git a/kernel/features/mm.c b/kernel/features/mm.c index ccc2727..ad70685 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -25,6 +25,7 @@ void paging_enable(void) void paging_switch_dir(u32 dir) { + assert(dir); cr3_set(dir); } @@ -418,7 +419,7 @@ void memory_initialize(struct mem_info *mem_info) memory_map_identity(&kernel_dir, memory_range_around_address(HEAP_START, HEAP_INIT_SIZE), MEMORY_NONE); - // TODO: Map something, idk? Triple fault prevention? + // TODO: Triple fault prevention? Probably bootloader stuff or something memory_map_identity(&kernel_dir, memory_range_around_address(0x7000, 0x1000), MEMORY_NONE); // Unmap NULL byte/page @@ -429,8 +430,37 @@ void memory_initialize(struct mem_info *mem_info) paging_enable(); } +static void page_fault(struct regs *r) +{ + // Check error code + const char *type = (r->err_code & 4) ? "present" : "non-present"; + const char *operation = (r->err_code & 2) ? "write" : "read"; + const char *super = (r->err_code & 1) ? "User" : "Super"; + + // Check cr2 address + u32 vaddr; + __asm__ volatile("movl %%cr2, %%eax" : "=a"(vaddr)); + struct proc *proc = proc_current(); + struct page_dir *dir = NULL; + if (proc && proc->page_dir) { + dir = proc->page_dir; + printf("Stack is at %x, entry at %x\n", virtual_to_physical(dir, proc->regs.ebp), + virtual_to_physical(dir, proc->entry)); + } else { + dir = &kernel_dir; + } + u32 paddr = virtual_to_physical(dir, vaddr); + + // Print! + printf("%s process tried to %s a %s page at [vaddr=%x; paddr=%x]\n", super, operation, type, + vaddr, paddr); + + isr_panic(r); +} + void paging_install(struct mem_info *mem_info) { memory_initialize(mem_info); heap_init(HEAP_START); + isr_install_handler(14, page_fault); } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index bbe675e..43cedb6 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -20,7 +20,7 @@ struct list *proc_list = NULL; struct node *idle_proc = NULL; struct node *current = NULL; -// TODO: Use less memcpy and only copy relevant registers +// TODO: Use less memcpy and only copy relevant registers (rewrite for efficiency argh) // TODO: 20 priority queues (https://www.kernel.org/doc/html/latest/scheduler/sched-nice-design.html) void scheduler(struct regs *regs) { @@ -57,8 +57,8 @@ void scheduler(struct regs *regs) } } - memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); memory_dir_switch(((struct proc *)current->data)->page_dir); + memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); if (regs->cs != GDT_USER_CODE_OFFSET) { regs->gs = GDT_USER_DATA_OFFSET; @@ -473,8 +473,7 @@ void proc_init(void) // Idle proc struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); - void (*func)(void) = kernel_idle; - proc_load(kernel_proc, *(void **)&func); + proc_load(kernel_proc, (u32)kernel_idle); strcpy(kernel_proc->name, "idle"); kernel_proc->state = PROC_SLEEPING; idle_proc = list_add(proc_list, kernel_proc); @@ -494,11 +493,11 @@ void proc_init(void) argv[2] = NULL; ((u32 *)_esp)[0] = argc; // First argument (argc) - ((u32 *)_esp)[1] = (u32)argv; // Second argument (argv) + ((u32 *)_esp)[-1] = (u32)argv; // Second argument (argv) printf("Jumping to userspace!\n"); - proc_jump_userspace(); memory_dir_switch(((struct proc *)new->data)->page_dir); + proc_jump_userspace(); while (1) { }; } diff --git a/kernel/inc/interrupts.h b/kernel/inc/interrupts.h index 30c91c3..fc00402 100644 --- a/kernel/inc/interrupts.h +++ b/kernel/inc/interrupts.h @@ -32,6 +32,7 @@ void irq_uninstall_handler(int irq); void isr_install_handler(int isr, void (*handler)(struct regs *r)); void isr_uninstall_handler(int isr); +void isr_panic(struct regs *r); void interrupts_install(void); diff --git a/kernel/inc/load.h b/kernel/inc/load.h index 407fbeb..330caca 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -5,7 +5,7 @@ #include -void proc_load(struct proc *proc, void *data); +void proc_load(struct proc *proc, u32 entry); int bin_load(const char *path, struct proc *proc); #endif diff --git a/kernel/main.c b/kernel/main.c index b46db0d..2e2e030 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,10 @@ struct vid_info *boot_passed; void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info); // Decl void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) { + // Clear stack + for (u32 i = 0; i < STACK_SIZE; i++) + ((u8 *)STACK_START)[-i] = 0; + // Serial connection serial_install(); serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); -- cgit v1.2.3 From 38cfba2f71bfa9bdea562cb6465b9dc0155fc467 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Mon, 8 Mar 2021 19:30:48 +0100 Subject: Better randomization (soon: random memory locs) --- kernel/main.c | 1 + libc/cpu.c | 19 ++++++--- libc/inc/cpu.h | 116 ++++++++++++++++++++++++++++-------------------------- libc/inc/random.h | 2 + libc/random.c | 29 ++++++++++++++ 5 files changed, 106 insertions(+), 61 deletions(-) (limited to 'kernel/main.c') diff --git a/kernel/main.c b/kernel/main.c index 2e2e030..f0bfc3c 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -37,6 +37,7 @@ void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) cpu_enable_features(); cpu_print(); + srand(rdseed()); // Install drivers vfs_install(); diff --git a/libc/cpu.c b/libc/cpu.c index b74ed57..cb9aa49 100644 --- a/libc/cpu.c +++ b/libc/cpu.c @@ -99,10 +99,16 @@ void cr4_set(u32 cr4) __asm__ volatile("movl %%eax, %%cr4" ::"a"(cr4)); } -static u32 cpu_features = 0; -static u8 cpu_has_feature(u32 feature) +static u32 cpu_cfeatures = 0; +u8 cpu_has_cfeature(enum cpuid_features feature) { - return (cpu_features & feature) != 0; + return (cpu_cfeatures & feature) != 0; +} + +static u32 cpu_dfeatures = 0; +u8 cpu_has_dfeature(enum cpuid_features feature) +{ + return (cpu_dfeatures & feature) != 0; } static void fpu_handler(struct regs *r) @@ -121,8 +127,9 @@ void cpu_enable_features(void) { u32 a, b, c, d; cpuid(CPUID_FEATURES, &a, &b, &c, &d); - cpu_features = d; - if (cpu_has_feature(CPUID_FEAT_EDX_SSE)) { + cpu_cfeatures = c; + cpu_dfeatures = d; + if (cpu_has_dfeature(CPUID_FEAT_EDX_SSE)) { cr0_set(cr0_get() & ~(1 << 2)); cr0_set(cr0_get() | (1 << 1)); cr4_set(cr4_get() | (3 << 9)); @@ -130,7 +137,7 @@ void cpu_enable_features(void) panic("No SSE support!\n"); } - if (cpu_has_feature(CPUID_FEAT_EDX_FPU)) { + if (cpu_has_dfeature(CPUID_FEAT_EDX_FPU)) { __asm__ volatile("fninit"); __asm__ volatile("fxsave %0" : "=m"(fpu_state)); irq_install_handler(7, fpu_handler); diff --git a/libc/inc/cpu.h b/libc/inc/cpu.h index 5c55913..161b7a4 100644 --- a/libc/inc/cpu.h +++ b/libc/inc/cpu.h @@ -41,63 +41,69 @@ void loop(void); enum cpuid_requests { CPUID_VENDOR_STRING, CPUID_FEATURES, CPUID_TLB, CPUID_SERIAL }; enum cpuid_features { - CPUID_FEAT_ECX_SSE3 = 1 << 0, - CPUID_FEAT_ECX_PCLMUL = 1 << 1, - CPUID_FEAT_ECX_DTES64 = 1 << 2, - CPUID_FEAT_ECX_MONITOR = 1 << 3, - CPUID_FEAT_ECX_DS_CPL = 1 << 4, - CPUID_FEAT_ECX_VMX = 1 << 5, - CPUID_FEAT_ECX_SMX = 1 << 6, - CPUID_FEAT_ECX_EST = 1 << 7, - CPUID_FEAT_ECX_TM2 = 1 << 8, - CPUID_FEAT_ECX_SSSE3 = 1 << 9, - CPUID_FEAT_ECX_CID = 1 << 10, - CPUID_FEAT_ECX_FMA = 1 << 12, - CPUID_FEAT_ECX_CX16 = 1 << 13, - CPUID_FEAT_ECX_ETPRD = 1 << 14, - CPUID_FEAT_ECX_PDCM = 1 << 15, - CPUID_FEAT_ECX_PCIDE = 1 << 17, - CPUID_FEAT_ECX_DCA = 1 << 18, - CPUID_FEAT_ECX_SSE4_1 = 1 << 19, - CPUID_FEAT_ECX_SSE4_2 = 1 << 20, - CPUID_FEAT_ECX_x2APIC = 1 << 21, - CPUID_FEAT_ECX_MOVBE = 1 << 22, - CPUID_FEAT_ECX_POPCNT = 1 << 23, - CPUID_FEAT_ECX_AES = 1 << 25, - CPUID_FEAT_ECX_XSAVE = 1 << 26, - CPUID_FEAT_ECX_OSXSAVE = 1 << 27, - CPUID_FEAT_ECX_AVX = 1 << 28, + CPUID_FEAT_ECX_SSE3 = 1u << 0, + CPUID_FEAT_ECX_PCLMUL = 1u << 1, + CPUID_FEAT_ECX_DTES64 = 1u << 2, + CPUID_FEAT_ECX_MONITOR = 1u << 3, + CPUID_FEAT_ECX_DS_CPL = 1u << 4, + CPUID_FEAT_ECX_VMX = 1u << 5, + CPUID_FEAT_ECX_SMX = 1u << 6, + CPUID_FEAT_ECX_EST = 1u << 7, + CPUID_FEAT_ECX_TM2 = 1u << 8, + CPUID_FEAT_ECX_SSSE3 = 1u << 9, + CPUID_FEAT_ECX_CID = 1u << 10, + CPUID_FEAT_ECX_FMA = 1u << 12, + CPUID_FEAT_ECX_CX16 = 1u << 13, + CPUID_FEAT_ECX_ETPRD = 1u << 14, + CPUID_FEAT_ECX_PDCM = 1u << 15, + CPUID_FEAT_ECX_PCIDE = 1u << 17, + CPUID_FEAT_ECX_DCA = 1u << 18, + CPUID_FEAT_ECX_SSE4_1 = 1u << 19, + CPUID_FEAT_ECX_SSE4_2 = 1u << 20, + CPUID_FEAT_ECX_x2APIC = 1u << 21, + CPUID_FEAT_ECX_MOVBE = 1u << 22, + CPUID_FEAT_ECX_POPCNT = 1u << 23, + CPUID_FEAT_ECX_AES = 1u << 25, + CPUID_FEAT_ECX_XSAVE = 1u << 26, + CPUID_FEAT_ECX_OSXSAVE = 1u << 27, + CPUID_FEAT_ECX_AVX = 1u << 28, + CPUID_FEAT_ECX_F16C = 1u << 29, + CPUID_FEAT_ECX_RDRND = 1u << 30, - CPUID_FEAT_EDX_FPU = 1 << 0, - CPUID_FEAT_EDX_VME = 1 << 1, - CPUID_FEAT_EDX_DE = 1 << 2, - CPUID_FEAT_EDX_PSE = 1 << 3, - CPUID_FEAT_EDX_TSC = 1 << 4, - CPUID_FEAT_EDX_MSR = 1 << 5, - CPUID_FEAT_EDX_PAE = 1 << 6, - CPUID_FEAT_EDX_MCE = 1 << 7, - CPUID_FEAT_EDX_CX8 = 1 << 8, - CPUID_FEAT_EDX_APIC = 1 << 9, - CPUID_FEAT_EDX_SEP = 1 << 11, - CPUID_FEAT_EDX_MTRR = 1 << 12, - CPUID_FEAT_EDX_PGE = 1 << 13, - CPUID_FEAT_EDX_MCA = 1 << 14, - CPUID_FEAT_EDX_CMOV = 1 << 15, - CPUID_FEAT_EDX_PAT = 1 << 16, - CPUID_FEAT_EDX_PSE36 = 1 << 17, - CPUID_FEAT_EDX_PSN = 1 << 18, - CPUID_FEAT_EDX_CLF = 1 << 19, - CPUID_FEAT_EDX_DTES = 1 << 21, - CPUID_FEAT_EDX_ACPI = 1 << 22, - CPUID_FEAT_EDX_MMX = 1 << 23, - CPUID_FEAT_EDX_FXSR = 1 << 24, - CPUID_FEAT_EDX_SSE = 1 << 25, - CPUID_FEAT_EDX_SSE2 = 1 << 26, - CPUID_FEAT_EDX_SS = 1 << 27, - CPUID_FEAT_EDX_HTT = 1 << 28, - CPUID_FEAT_EDX_TM1 = 1 << 29, - CPUID_FEAT_EDX_IA64 = 1 << 30, + CPUID_FEAT_EDX_FPU = 1u << 0, + CPUID_FEAT_EDX_VME = 1u << 1, + CPUID_FEAT_EDX_DE = 1u << 2, + CPUID_FEAT_EDX_PSE = 1u << 3, + CPUID_FEAT_EDX_TSC = 1u << 4, + CPUID_FEAT_EDX_MSR = 1u << 5, + CPUID_FEAT_EDX_PAE = 1u << 6, + CPUID_FEAT_EDX_MCE = 1u << 7, + CPUID_FEAT_EDX_CX8 = 1u << 8, + CPUID_FEAT_EDX_APIC = 1u << 9, + CPUID_FEAT_EDX_SEP = 1u << 11, + CPUID_FEAT_EDX_MTRR = 1u << 12, + CPUID_FEAT_EDX_PGE = 1u << 13, + CPUID_FEAT_EDX_MCA = 1u << 14, + CPUID_FEAT_EDX_CMOV = 1u << 15, + CPUID_FEAT_EDX_PAT = 1u << 16, + CPUID_FEAT_EDX_PSE36 = 1u << 17, + CPUID_FEAT_EDX_PSN = 1u << 18, + CPUID_FEAT_EDX_CLF = 1u << 19, + CPUID_FEAT_EDX_DTES = 1u << 21, + CPUID_FEAT_EDX_ACPI = 1u << 22, + CPUID_FEAT_EDX_MMX = 1u << 23, + CPUID_FEAT_EDX_FXSR = 1u << 24, + CPUID_FEAT_EDX_SSE = 1u << 25, + CPUID_FEAT_EDX_SSE2 = 1u << 26, + CPUID_FEAT_EDX_SS = 1u << 27, + CPUID_FEAT_EDX_HTT = 1u << 28, + CPUID_FEAT_EDX_TM1 = 1u << 29, + CPUID_FEAT_EDX_IA64 = 1u << 30, }; + +u8 cpu_has_cfeature(enum cpuid_features feature); +u8 cpu_has_dfeature(enum cpuid_features feature); + #endif #endif diff --git a/libc/inc/random.h b/libc/inc/random.h index 59add9b..a82524c 100644 --- a/libc/inc/random.h +++ b/libc/inc/random.h @@ -6,6 +6,8 @@ #include void srand(u32 seed); +u32 rdrand(void); +u32 rdseed(void); u32 rand(void); char *randstr(u32 size); diff --git a/libc/random.c b/libc/random.c index 8c8076f..cfd082d 100644 --- a/libc/random.c +++ b/libc/random.c @@ -1,5 +1,6 @@ // MIT License, Copyright (c) 2020 Marvin Borner +#include #include #include #include @@ -11,6 +12,34 @@ void srand(u32 seed) g_seed = seed; } +u32 rdrand(void) +{ +#ifdef kernel + if (!cpu_has_cfeature(CPUID_FEAT_ECX_RDRND)) + return rand(); + + u32 rd; + __asm__ volatile("rdrand %%eax" : "=a"(rd)); + return rd; +#else + return rand(); +#endif +} + +u32 rdseed(void) +{ +#ifdef kernel + if (!cpu_has_cfeature(CPUID_FEAT_ECX_RDRND)) + return rand(); + + u32 rd; + __asm__ volatile("rdseed %%eax" : "=a"(rd)); + return rd; +#else + return rand(); +#endif +} + u32 rand(void) { g_seed = g_seed * 1103515245 + 12345; -- cgit v1.2.3 From f1751c121d48f2d8936c72bdc347777d1e7402d9 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Fri, 12 Mar 2021 16:07:45 +0100 Subject: Let's gooo! --- apps/init.c | 2 ++ kernel/drivers/interrupts.c | 4 ++-- kernel/features/load.c | 37 +++++++++++++++++-------------------- kernel/features/mm.c | 39 ++++++++++++++++++++++----------------- kernel/features/proc.c | 20 +++++++++++--------- kernel/inc/mm.h | 2 ++ kernel/main.c | 4 +++- libc/alloc.c | 12 ++++++++++++ libc/inc/def.h | 1 + libc/inc/print.h | 3 ++- libc/print.c | 2 +- libc/sanitize.c | 4 ++-- 12 files changed, 77 insertions(+), 53 deletions(-) (limited to 'kernel/main.c') diff --git a/apps/init.c b/apps/init.c index 87f0d82..7044365 100644 --- a/apps/init.c +++ b/apps/init.c @@ -8,6 +8,8 @@ int main(int argc, char **argv) { + while (1) { + }; (void)argc; log("%s loaded\n", argv[0]); diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index 55926b7..a0cd106 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -171,9 +171,9 @@ void isr_uninstall_handler(int isr) void isr_panic(struct regs *r) { + printf("%s Exception (%x) at 0x%x (ring %d), exiting!\n", isr_exceptions[r->int_no], + r->err_code, r->eip, r->cs & 3); struct proc *proc = proc_current(); - printf("%s Exception (%x) at 0x%x, exiting!\n", isr_exceptions[r->int_no], r->err_code, - r->eip); if (proc) { printf("\t-> Exception occurred in %s at addr 0x%x\n", proc->name, r->eip - proc->entry); diff --git a/kernel/features/load.c b/kernel/features/load.c index 31e22dc..ec9a387 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -6,45 +6,42 @@ #include #include -// TODO: Fix pdi < 256! -#define PROC_DATA_ADDR 0xc000000 - #define PROC_STACK_SIZE 0x4000 -#define PROC_STACK_ADDR (PROC_DATA_ADDR - 256) -void proc_load(struct proc *proc, u32 entry) +/*void proc_load(struct proc *proc, u32 entry) { - /* memory_dir_switch(proc->page_dir); */ - u32 paddr = physical_alloc(PROC_STACK_SIZE); - virtual_map(proc->page_dir, PROC_STACK_ADDR, paddr, PROC_STACK_SIZE, - MEMORY_USER | MEMORY_CLEAR); + u32 stack = (u32)memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_USER | MEMORY_CLEAR); - proc->regs.ebp = PROC_STACK_ADDR; - proc->regs.useresp = PROC_STACK_ADDR; + proc->regs.ebp = stack; + proc->regs.useresp = stack; proc->regs.eip = entry; proc->entry = entry; -} +}*/ int bin_load(const char *path, struct proc *proc) { struct stat s = { 0 }; vfs_stat(path, &s); struct proc *current = proc_current(); - struct page_dir *prev = current ? current->page_dir : memory_kernel_dir(); + struct page_dir *prev = current ? current->page_dir : virtual_kernel_dir(); u32 size = PAGE_ALIGN_UP(s.size); - memory_dir_switch(proc->page_dir); - u32 paddr = physical_alloc(size); - virtual_map(proc->page_dir, PROC_DATA_ADDR, paddr, size, MEMORY_USER | MEMORY_CLEAR); + memory_switch_dir(proc->page_dir); + u32 data = (u32)memory_alloc(proc->page_dir, size, MEMORY_USER | MEMORY_CLEAR); - if (!vfs_read(path, (void *)PROC_DATA_ADDR, 0, s.size)) { - memory_dir_switch(prev); + if (!vfs_read(path, (void *)data, 0, s.size)) { + memory_switch_dir(prev); return 1; } strcpy(proc->name, path); - proc_load(proc, PROC_DATA_ADDR); - memory_dir_switch(prev); + u32 stack = (u32)memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_USER | MEMORY_CLEAR); + proc->regs.ebp = stack; + proc->regs.useresp = stack; + proc->regs.eip = data; + proc->entry = data; + + memory_switch_dir(prev); return 0; } diff --git a/kernel/features/mm.c b/kernel/features/mm.c index cde9a94..c39b8b7 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -6,7 +6,6 @@ #include #include #include - #include static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; @@ -138,7 +137,7 @@ static u8 physical_is_used(struct memory_range range) return 0; } -static struct memory_range physical_alloc(u32 size) +struct memory_range physical_alloc(u32 size) { assert(PAGE_ALIGNED(size)); @@ -165,34 +164,34 @@ static void physical_free(struct memory_range range) * Virtual */ -#define PDI(vaddr) ((vaddr) >> 22) +#define PDI(vaddr) (((vaddr) >> 22) & 0x03ff) #define PTI(vaddr) (((vaddr) >> 12) & 0x03ff) u8 virtual_present(struct page_dir *dir, u32 vaddr) { u32 pdi = PDI(vaddr); - u32 pti = PTI(vaddr); - union page_dir_entry *dir_entry = &dir->entries[pdi]; if (!dir_entry->bits.present) return 0; struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + + u32 pti = PTI(vaddr); union page_table_entry *table_entry = &table->entries[pti]; - return !table_entry->bits.present; + return table_entry->bits.present; } u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) { u32 pdi = PDI(vaddr); - u32 pti = PTI(vaddr); - union page_dir_entry *dir_entry = &dir->entries[pdi]; if (!dir_entry->bits.present) return 0; struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + + u32 pti = PTI(vaddr); union page_table_entry *table_entry = &table->entries[pti]; if (!table_entry->bits.present) return 0; @@ -204,9 +203,8 @@ void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u3 { for (u32 i = 0; i < prange.size / PAGE_SIZE; i++) { u32 offset = i * PAGE_SIZE; - u32 pdi = PDI(vaddr + offset); - u32 pti = PTI(vaddr + offset); + u32 pdi = PDI(vaddr + offset); union page_dir_entry *dir_entry = &dir->entries[pdi]; struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); @@ -219,6 +217,7 @@ void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u3 dir_entry->bits.address = (u32)(table) >> 12; } + u32 pti = PTI(vaddr + offset); union page_table_entry *table_entry = &table->entries[pti]; table_entry->bits.present = 1; table_entry->bits.writable = 1; @@ -263,14 +262,14 @@ void virtual_free(struct page_dir *dir, struct memory_range vrange) u32 offset = i * PAGE_SIZE; u32 pdi = PDI(vrange.base + offset); - u32 pti = PTI(vrange.base + offset); - union page_dir_entry *dir_entry = &dir->entries[pdi]; if (!dir_entry->bits.present) continue; struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + + u32 pti = PTI(vrange.base + offset); union page_table_entry *table_entry = &table->entries[pti]; if (table_entry->bits.present) @@ -284,12 +283,14 @@ struct page_dir *virtual_create_dir(void) { struct page_dir *dir = memory_alloc(&kernel_dir, sizeof(*dir), MEMORY_CLEAR); + memset(dir, 0, sizeof(*dir)); + for (u32 i = 0; i < 256; i++) { union page_dir_entry *dir_entry = &dir->entries[i]; - dir_entry->bits.user = 0; - dir_entry->bits.writable = 1; dir_entry->bits.present = 1; + dir_entry->bits.writable = 1; + dir_entry->bits.user = 0; dir_entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; } @@ -334,22 +335,26 @@ void *memory_alloc(struct page_dir *dir, u32 size, u32 flags) assert(PAGE_ALIGNED(size)); if (!size) - return 0; + goto err; struct memory_range prange = physical_alloc(size); if (prange.size == 0) - return 0; + goto err; u32 vaddr = virtual_alloc(dir, prange, flags).base; if (!vaddr) { physical_free(prange); - return 0; + goto err; } if (flags & MEMORY_CLEAR) memset((void *)vaddr, 0, size); return (void *)vaddr; + +err: + print("Memory allocation error!\n"); + return 0; } void *memory_alloc_identity(struct page_dir *dir, u32 flags) diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 19a92d3..4d1311e 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -57,7 +57,7 @@ void scheduler(struct regs *regs) } } - memory_dir_switch(((struct proc *)current->data)->page_dir); + memory_switch_dir(((struct proc *)current->data)->page_dir); memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); if (regs->cs != GDT_USER_CODE_OFFSET) { @@ -248,9 +248,9 @@ struct proc *proc_make(enum proc_priv priv) proc->state = PROC_RUNNING; if (priv == PROC_PRIV_KERNEL) - proc->page_dir = memory_kernel_dir(); + proc->page_dir = virtual_kernel_dir(); else - proc->page_dir = memory_dir_create(); + proc->page_dir = virtual_create_dir(); if (current) list_add(proc_list, proc); @@ -472,11 +472,11 @@ void proc_init(void) vfs_mount(dev, "/proc/"); // Idle proc - struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); - proc_load(kernel_proc, (u32)kernel_idle); - strcpy(kernel_proc->name, "idle"); - kernel_proc->state = PROC_SLEEPING; - idle_proc = list_add(proc_list, kernel_proc); + /* struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); */ + /* proc_load(kernel_proc, (u32)kernel_idle); */ + /* strcpy(kernel_proc->name, "idle"); */ + /* kernel_proc->state = PROC_SLEEPING; */ + /* idle_proc = list_add(proc_list, kernel_proc); */ // Init proc (root) struct node *new = list_add(proc_list, proc_make(PROC_PRIV_ROOT)); @@ -496,7 +496,9 @@ void proc_init(void) /* ((u32 *)_esp)[-1] = (u32)argv; // Second argument (argv) */ printf("Jumping to userspace!\n"); - memory_dir_switch(((struct proc *)new->data)->page_dir); + /* printf("%x\n", ((u32 *)((struct proc *)new->data)->entry)[5]); */ + memory_switch_dir(((struct proc *)new->data)->page_dir); + /* printf("%x\n", ((u32 *)((struct proc *)new->data)->entry)[5]); */ proc_jump_userspace(); while (1) { }; diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 6d3714d..aad4ffd 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -15,6 +15,8 @@ struct memory_range { * Physical */ +struct memory_range physical_alloc(u32 size); + /** * Virtual */ diff --git a/kernel/main.c b/kernel/main.c index f0bfc3c..8247672 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -17,6 +17,8 @@ #include #include +#include + struct vid_info *boot_passed; void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info); // Decl @@ -31,7 +33,7 @@ void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); serial_print("Serial connected.\n"); - paging_install(mem_info); + memory_install(mem_info); boot_passed = vid_info; diff --git a/libc/alloc.c b/libc/alloc.c index 11639a6..f621c4e 100644 --- a/libc/alloc.c +++ b/libc/alloc.c @@ -303,6 +303,9 @@ static void _free(void *ptr) void *zalloc(u32 size) { +#ifdef userspace + panic("AAH!\n"); +#endif void *ret = malloc(size); memset(ret, 0, size); return ret; @@ -311,6 +314,9 @@ void *zalloc(u32 size) // Naive realloc implementation - TODO! void *realloc(void *ptr, u32 size) { +#ifdef userspace + panic("AAH!\n"); +#endif if (!ptr) return malloc(size); @@ -330,6 +336,9 @@ void *realloc(void *ptr, u32 size) void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp) { +#ifdef userspace + panic("AAH!\n"); +#endif assert(size < (100 << 20)); // Don't brag with memory pls void *ret = _malloc(size); @@ -343,6 +352,9 @@ void *malloc_debug(u32 size, const char *file, int line, const char *func, const void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp) { +#ifdef userspace + panic("AAH!\n"); +#endif if (ptr) _free(ptr); diff --git a/libc/inc/def.h b/libc/inc/def.h index 945ccb0..db1c95e 100644 --- a/libc/inc/def.h +++ b/libc/inc/def.h @@ -25,6 +25,7 @@ typedef unsigned long long u64; #define UNUSED(a) ((void)(a)) +#define NORETURN __attribute__((noreturn)) #define NO_SANITIZE __attribute__((no_sanitize("undefined"))) #define PACKED __attribute__((packed)) #define ALIGNED(align) __attribute__((aligned(align))) diff --git a/libc/inc/print.h b/libc/inc/print.h index 110ba4c..58b5dc6 100644 --- a/libc/inc/print.h +++ b/libc/inc/print.h @@ -4,13 +4,14 @@ #define PRINT_H #include "arg.h" +#include int printf(const char *format, ...); int vprintf(const char *format, va_list ap); int sprintf(char *str, const char *format, ...); int vsprintf(char *str, const char *format, va_list ap); int print(const char *str); -void panic(const char *format, ...); +NORETURN void panic(const char *format, ...); #ifdef userspace int vfprintf(const char *path, const char *format, va_list ap); diff --git a/libc/print.c b/libc/print.c index ca2ab98..173e117 100644 --- a/libc/print.c +++ b/libc/print.c @@ -230,7 +230,7 @@ void print_trace(u32 count) #endif -void panic(const char *format, ...) +NORETURN void panic(const char *format, ...) { char buf[1024] = { 0 }; va_list ap; diff --git a/libc/sanitize.c b/libc/sanitize.c index 8cfec49..8514e49 100644 --- a/libc/sanitize.c +++ b/libc/sanitize.c @@ -13,13 +13,13 @@ u32 __stack_chk_guard = STACK_CHK_GUARD; void __stack_chk_fail(void); -void __stack_chk_fail(void) +NORETURN void __stack_chk_fail(void) { panic("FATAL: Stack smashing detected\n"); } void __stack_chk_fail_local(void); -void __stack_chk_fail_local(void) +NORETURN void __stack_chk_fail_local(void) { panic("FATAL: Local stack smashing detected\n"); } -- cgit v1.2.3 From bbf700a0c6b2f8ca9a73c2a334973286d5b8afcc Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Fri, 12 Mar 2021 19:11:26 +0100 Subject: Started basic ioctl fb interface --- apps/init.c | 6 ++---- kernel/Makefile | 1 + kernel/drivers/fb.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ kernel/features/fs.c | 46 +++++++++++++++++++++++++++++++++++++++++----- kernel/features/proc.c | 9 --------- kernel/features/syscall.c | 5 +++++ kernel/inc/boot.h | 1 - kernel/inc/fb.h | 10 ++++++++++ kernel/inc/fs.h | 4 ++++ kernel/main.c | 8 ++------ libc/inc/ioctl.h | 11 +++++++++++ libc/inc/sys.h | 2 ++ 12 files changed, 123 insertions(+), 25 deletions(-) create mode 100644 kernel/drivers/fb.c create mode 100644 kernel/inc/fb.h create mode 100644 libc/inc/ioctl.h (limited to 'kernel/main.c') diff --git a/apps/init.c b/apps/init.c index 9e57078..6503022 100644 --- a/apps/init.c +++ b/apps/init.c @@ -8,13 +8,11 @@ int main(int argc, char **argv) { - log("Loaded!\n"); + log("%s loaded\n", argv[0]); while (1) { }; - (void)argc; - log("%s loaded\n", argv[0]); - int wm = exec("/bin/wm", "wm", argv[1], NULL); + int wm = exec("/bin/wm", "wm", NULL); int test = exec("/bin/window", "test", NULL); return wm + test; diff --git a/kernel/Makefile b/kernel/Makefile index 2db201b..e9ade73 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -8,6 +8,7 @@ COBJS = main.o \ drivers/mouse.o \ drivers/pci.o \ drivers/ide.o \ + drivers/fb.o \ drivers/timer.o \ drivers/rtl8139.o \ features/mm.o \ diff --git a/kernel/drivers/fb.c b/kernel/drivers/fb.c new file mode 100644 index 0000000..a1a7729 --- /dev/null +++ b/kernel/drivers/fb.c @@ -0,0 +1,45 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include +#include +#include +#include +#include +#include +#include + +static u32 dev_id = 0; +static struct vid_info *info = NULL; + +static s32 fb_ioctl(u32 request, void *arg1, void *arg2, void *arg3, struct device *dev) +{ + UNUSED(arg2); + UNUSED(arg3); + UNUSED(dev); + + switch (request) { + case IO_FB_GET: + memcpy(arg1, info->vbe, 256); + return 0; + default: + return -1; + } +} + +static u8 fb_ready(void) +{ + return 1; +} + +void fb_install(struct vid_info *boot) +{ + info = boot; + + struct device *dev = zalloc(sizeof(*dev)); + dev->name = strdup("fb"); + dev->type = DEV_CHAR; + dev->ioctl = fb_ioctl; + dev->ready = fb_ready; + device_add(dev); + dev_id = dev->id; +} diff --git a/kernel/features/fs.c b/kernel/features/fs.c index 687d7ad..4d19dde 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -131,7 +131,8 @@ s32 vfs_read(const char *path, void *buf, u32 offset, u32 count) path++; struct mount_info *m = vfs_find_mount_info(path); - assert(m && m->dev && m->dev->vfs && m->dev->vfs->read && m->dev->vfs->perm); + if (!(m && m->dev && m->dev->vfs && m->dev->vfs->read && m->dev->vfs->perm)) + return -1; u32 len = strlen(m->path); if (len > 1) @@ -156,7 +157,8 @@ s32 vfs_write(const char *path, void *buf, u32 offset, u32 count) path++; struct mount_info *m = vfs_find_mount_info(path); - assert(m && m->dev && m->dev->vfs && m->dev->vfs->write && m->dev->vfs->perm); + if (!(m && m->dev && m->dev->vfs && m->dev->vfs->write && m->dev->vfs->perm)) + return -1; u32 len = strlen(m->path); if (len > 1) @@ -168,6 +170,25 @@ s32 vfs_write(const char *path, void *buf, u32 offset, u32 count) return m->dev->vfs->write(path, buf, offset, count, m->dev); } +s32 vfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3) +{ + while (*path == ' ') + path++; + + struct mount_info *m = vfs_find_mount_info(path); + if (!(m && m->dev && m->dev->vfs && m->dev->vfs->ioctl && m->dev->vfs->perm)) + return -1; + + u32 len = strlen(m->path); + if (len > 1) + path += len; + + if (!m->dev->vfs->perm(path, VFS_WRITE, m->dev) && !proc_super()) + return -1; + + return m->dev->vfs->ioctl(path, request, arg1, arg2, arg3, m->dev); +} + s32 vfs_stat(const char *path, struct stat *buf) { while (*path == ' ') @@ -177,12 +198,16 @@ s32 vfs_stat(const char *path, struct stat *buf) return -1; struct mount_info *m = vfs_find_mount_info(path); - assert(m && m->dev && m->dev->vfs && m->dev->vfs->stat); + if (!(m && m->dev && m->dev->vfs && m->dev->vfs->stat && m->dev->vfs->perm)) + return -1; u32 len = strlen(m->path); if (len > 1) path += len; + if (!m->dev->vfs->perm(path, VFS_WRITE, m->dev) && !proc_super()) + return -1; + return m->dev->vfs->stat(path, buf, m->dev); } @@ -192,7 +217,8 @@ s32 vfs_wait(const char *path, u32 func_ptr) path++; struct mount_info *m = vfs_find_mount_info(path); - assert(m && m->dev && m->dev->vfs); + if (!(m && m->dev && m->dev->vfs)) + return -1; // Default wait if (!m->dev->vfs->wait) { @@ -280,10 +306,19 @@ static s32 devfs_read(const char *path, void *buf, u32 offset, u32 count, struct { struct device *target = device_get_by_name(path + 1); if (!target || !target->read) - return 0; + return -1; return target->read(buf, offset, count, dev); } +static s32 devfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3, + struct device *dev) +{ + struct device *target = device_get_by_name(path + 1); + if (!target || !target->ioctl) + return -1; + return target->ioctl(request, arg1, arg2, arg3, dev); +} + static u8 devfs_perm(const char *path, enum vfs_perm perm, struct device *dev) { (void)path; @@ -309,6 +344,7 @@ void device_install(void) struct vfs *vfs = zalloc(sizeof(*vfs)); vfs->type = VFS_DEVFS; vfs->read = devfs_read; + vfs->ioctl = devfs_ioctl; vfs->perm = devfs_perm; vfs->ready = devfs_ready; struct device *dev = zalloc(sizeof(*dev)); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index db2291c..38d88f8 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -479,15 +479,6 @@ void proc_init(void) _eip = ((struct proc *)new->data)->regs.eip; _esp = ((struct proc *)new->data)->regs.useresp; - /* u32 argc = 2; */ - /* char **argv = malloc(sizeof(*argv) * (argc + 1)); */ - /* argv[0] = strdup("init"); */ - /* argv[1] = (char *)boot_passed->vbe; */ - /* argv[2] = NULL; */ - - /* ((u32 *)_esp)[0] = argc; // First argument (argc) */ - /* ((u32 *)_esp)[-1] = (u32)argv; // Second argument (argv) */ - printf("Jumping to userspace!\n"); memory_switch_dir(((struct proc *)new->data)->page_dir); proc_jump_userspace(); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index b3e69e0..bac1738 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -52,6 +52,11 @@ static void syscall_handler(struct regs *r) r->eax = (u32)vfs_write((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); break; } + case SYS_IOCTL: { + r->eax = (u32)vfs_ioctl((char *)r->ebx, r->ecx, (void *)r->edx, (void *)r->esi, + (void *)r->edi); + break; + } case SYS_POLL: { s32 ret = vfs_poll((const char **)r->ebx); if (ret == PROC_MAX_WAIT_IDS + 1) diff --git a/kernel/inc/boot.h b/kernel/inc/boot.h index 052a56f..7f085cd 100644 --- a/kernel/inc/boot.h +++ b/kernel/inc/boot.h @@ -6,7 +6,6 @@ #include -extern struct vid_info *boot_passed; struct vid_info { u32 mode; u32 *vbe; diff --git a/kernel/inc/fb.h b/kernel/inc/fb.h new file mode 100644 index 0000000..3e7b08f --- /dev/null +++ b/kernel/inc/fb.h @@ -0,0 +1,10 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef FB +#define FB + +#include + +void fb_install(struct vid_info *boot); + +#endif diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h index 33b1afb..cd97b99 100644 --- a/kernel/inc/fs.h +++ b/kernel/inc/fs.h @@ -20,6 +20,7 @@ struct device { void *data; s32 (*read)(void *buf, u32 offset, u32 count, struct device *dev); s32 (*write)(void *buf, u32 offset, u32 count, struct device *dev); + s32 (*ioctl)(u32 request, void *arg1, void *arg2, void *arg3, struct device *dev); u8 (*ready)(void); }; @@ -40,6 +41,8 @@ struct vfs { void *data; s32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); s32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); + s32 (*ioctl)(const char *path, u32 request, void *arg1, void *arg2, void *arg3, + struct device *dev); s32 (*stat)(const char *path, struct stat *buf, struct device *dev); s32 (*wait)(const char *path, u32 func_ptr, struct device *dev); u8 (*perm)(const char *path, enum vfs_perm perm, struct device *dev); @@ -60,6 +63,7 @@ struct device *vfs_find_dev(const char *path); s32 vfs_read(const char *path, void *buf, u32 offset, u32 count); s32 vfs_write(const char *path, void *buf, u32 offset, u32 count); +s32 vfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3); s32 vfs_stat(const char *path, struct stat *buf); s32 vfs_wait(const char *path, u32 func_ptr); s32 vfs_poll(const char **files); diff --git a/kernel/main.c b/kernel/main.c index 8247672..118fe11 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -17,10 +18,6 @@ #include #include -#include - -struct vid_info *boot_passed; - void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info); // Decl void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) { @@ -35,8 +32,6 @@ void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) memory_install(mem_info); - boot_passed = vid_info; - cpu_enable_features(); cpu_print(); srand(rdseed()); @@ -50,6 +45,7 @@ void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) timer_install(); keyboard_install(); mouse_install(); + fb_install(vid_info); /* net_install(); */ // Enable drivers diff --git a/libc/inc/ioctl.h b/libc/inc/ioctl.h new file mode 100644 index 0000000..c3eec56 --- /dev/null +++ b/libc/inc/ioctl.h @@ -0,0 +1,11 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef IOCTL +#define IOCTL + +// FB interface +#define IO_FB_GET 0 + +int ioctl_is_awesome; // GCC is not + +#endif diff --git a/libc/inc/sys.h b/libc/inc/sys.h index 5858579..c20eabc 100644 --- a/libc/inc/sys.h +++ b/libc/inc/sys.h @@ -16,6 +16,7 @@ enum sys { SYS_STAT, // Get file information SYS_READ, // Read file SYS_WRITE, // Write to file + SYS_IOCTL, // Interact with a file/device SYS_POLL, // Wait for multiple files SYS_EXEC, // Execute path SYS_EXIT, // Exit current process // TODO: Free all memory of process @@ -70,6 +71,7 @@ int sysv(enum sys num, ...); (s32) sys4(SYS_READ, (int)(path), (int)(buf), (int)(offset), (int)(count)) #define write(path, buf, offset, count) \ (s32) sys4(SYS_WRITE, (int)(path), (int)(buf), (int)(offset), (int)(count)) +#define ioctl(path, ...) (s32) sysv(SYS_IOCTL, (int)(path), ##__VA_ARGS__) #define stat(path, stat) (s32) sys2(SYS_STAT, (int)(path), (int)(stat)) #define poll(files) (s32) sys1(SYS_POLL, (int)(files)) #define exec(path, ...) (s32) sysv(SYS_EXEC, (int)(path), ##__VA_ARGS__) -- cgit v1.2.3 From 8176351e1a3d1598bedbc007897d530475942275 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Sat, 13 Mar 2021 13:33:26 +0100 Subject: Nicü --- Makefile | 4 +++- apps/init.c | 6 ++---- apps/wm.c | 8 +++++--- kernel/drivers/fb.c | 23 +++++++++++++++++++++-- kernel/features/fs.c | 6 ++++-- kernel/features/load.c | 6 +++--- kernel/features/mm.c | 11 ++++++----- kernel/features/proc.c | 32 +++++++++++++++++++------------- kernel/features/syscall.c | 12 ++---------- kernel/inc/mm.h | 2 +- kernel/inc/proc.h | 1 + kernel/main.c | 2 +- libc/alloc.c | 4 +++- 13 files changed, 71 insertions(+), 46 deletions(-) (limited to 'kernel/main.c') diff --git a/Makefile b/Makefile index 1e20a7a..fa1954c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,9 @@ CFLAGS_DEFAULT = $(CFLAGS_WARNINGS) $(CFLAGS_OPTIMIZATION) -std=c99 -m32 -nostdl all: compile -debug: CFLAGS_DEFAULT += -Wno-error -ggdb3 -s -fsanitize=undefined # -fstack-protector-all # TODO: Fix stack protector in userspace +# TODO: Fix stack protector in userspace +# TODO: Fix ubsan in userspace (probably due to kernel size) +debug: CFLAGS_DEFAULT += -Wno-error -ggdb3 -s #-fsanitize=undefined # -fstack-protector-all debug: compile export diff --git a/apps/init.c b/apps/init.c index 705f178..f854a81 100644 --- a/apps/init.c +++ b/apps/init.c @@ -10,11 +10,9 @@ int main(int argc, char **argv) { UNUSED(argc); UNUSED(argv); - while (1) { - }; int wm = exec("/bin/wm", "wm", NULL); - int test = exec("/bin/window", "test", NULL); + /* int test = exec("/bin/window", "test", NULL); */ - return wm + test; + return wm; //+ test; } diff --git a/apps/wm.c b/apps/wm.c index becbf0a..8eb6f70 100644 --- a/apps/wm.c +++ b/apps/wm.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -361,11 +362,12 @@ static void handle_message(struct message *msg) int main(int argc, char **argv) { - (void)argc; - screen = *(struct vbe *)argv[1]; + UNUSED(argc); + UNUSED(argv); + assert(ioctl("/dev/fb", IO_FB_GET, &screen) == 0); + log("WM loaded: %dx%d\n", screen.width, screen.height); wm_client = (struct client){ .pid = getpid() }; bypp = (screen.bpp >> 3); - log("WM loaded: %dx%d\n", screen.width, screen.height); windows = list_new(); keymap = keymap_parse("/res/keymaps/en.keymap"); diff --git a/kernel/drivers/fb.c b/kernel/drivers/fb.c index a1a7729..8e73f5b 100644 --- a/kernel/drivers/fb.c +++ b/kernel/drivers/fb.c @@ -1,13 +1,25 @@ // MIT License, Copyright (c) 2021 Marvin Borner +#include #include #include #include #include #include +#include #include #include +struct vbe_basic { + u8 stuff1[16]; + u16 pitch; + u16 width; + u16 height; + u8 stuff2[18]; + u8 *fb; + u8 stuff3[212]; +}; + static u32 dev_id = 0; static struct vid_info *info = NULL; @@ -18,9 +30,16 @@ static s32 fb_ioctl(u32 request, void *arg1, void *arg2, void *arg3, struct devi UNUSED(dev); switch (request) { - case IO_FB_GET: - memcpy(arg1, info->vbe, 256); + case IO_FB_GET: { + if (!info) + return -1; + struct vbe_basic *vbe = (struct vbe_basic *)info->vbe; + memcpy(arg1, info->vbe, sizeof(struct vbe_basic)); + u32 size = vbe->height * vbe->pitch; + memory_map_identity(proc_current()->page_dir, + memory_range_around((u32)vbe->fb, size), MEMORY_USER); return 0; + } default: return -1; } diff --git a/kernel/features/fs.c b/kernel/features/fs.c index 4d19dde..20d00e5 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -62,13 +62,15 @@ static struct mount_info *vfs_recursive_find(char *path) static struct mount_info *vfs_find_mount_info(const char *path) { - assert(path[0] == '/'); + if (path[0] != '/') + return NULL; return vfs_recursive_find(strdup(path)); } struct device *vfs_find_dev(const char *path) { - assert(path[0] == '/'); + if (path[0] != '/') + return NULL; struct mount_info *m = vfs_find_mount_info(path); if (m->dev->vfs->type == VFS_DEVFS) // TODO: ? return device_get_by_name(path + strlen(m->path) + 1); diff --git a/kernel/features/load.c b/kernel/features/load.c index 4ad2cbf..9e6db79 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -13,6 +13,8 @@ int bin_load(const char *path, struct proc *proc) struct stat s = { 0 }; vfs_stat(path, &s); + strcpy(proc->name, path); + struct page_dir *prev; memory_backup_dir(&prev); memory_switch_dir(proc->page_dir); @@ -20,13 +22,11 @@ int bin_load(const char *path, struct proc *proc) u32 size = PAGE_ALIGN_UP(s.size); u32 data = (u32)memory_alloc(proc->page_dir, size, MEMORY_USER | MEMORY_CLEAR); - if (!vfs_read(path, (void *)data, 0, s.size)) { + if (!vfs_read(proc->name, (void *)data, 0, s.size)) { memory_switch_dir(prev); return 1; } - strcpy(proc->name, path); - u32 stack = (u32)memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_USER | MEMORY_CLEAR); proc->regs.ebp = stack; proc->regs.useresp = stack; diff --git a/kernel/features/mm.c b/kernel/features/mm.c index b5fd33c..bd32683 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -35,9 +35,9 @@ extern void paging_invalidate_tlb(void); static void page_fault(struct regs *r) { // Check error code - const char *type = (r->err_code & 4) ? "present" : "non-present"; + const char *type = (r->err_code & 1) ? "present" : "non-present"; const char *operation = (r->err_code & 2) ? "write" : "read"; - const char *super = (r->err_code & 1) ? "User" : "Super"; + const char *super = (r->err_code & 4) ? "User" : "Super"; // Check cr2 address u32 vaddr; @@ -446,7 +446,7 @@ static struct memory_range kernel_memory_range(void) return memory_range_around((u32)&kernel_start, (u32)&kernel_end - (u32)&kernel_start); } -void memory_install(struct mem_info *mem_info) +void memory_install(struct mem_info *mem_info, struct vid_info *vid_info) { for (struct mmap_boot *p = mem_info->start; (u32)(p - mem_info->start) < mem_info->size; p++) { @@ -484,8 +484,9 @@ void memory_install(struct mem_info *mem_info) memory_map_identity(&kernel_dir, memory_range_around(STACK_START - STACK_SIZE, STACK_SIZE), MEMORY_NONE); - // TODO: Triple fault prevention? Probably bootloader stuff or something - memory_map_identity(&kernel_dir, memory_range_around(0x7000, 0x1000), MEMORY_NONE); + // Map VBE data + memory_map_identity(&kernel_dir, memory_range_around((u32)vid_info->vbe, 0x1000), + MEMORY_NONE); // Unmap NULL byte/page struct memory_range zero = memory_range(0, PAGE_SIZE); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index e7ddf4b..6bbe894 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -157,6 +157,9 @@ void proc_yield(struct regs *r) void proc_enable_waiting(u32 id, enum proc_wait_type type) { + struct page_dir *dir_bak; + memory_backup_dir(&dir_bak); + struct proc *proc_bak = proc_current(); if (!proc_bak) return; @@ -179,8 +182,11 @@ void proc_enable_waiting(u32 id, enum proc_wait_type type) struct regs *r = &p->regs; u32 (*func)(u32, u32, u32, u32) = (u32(*)(u32, u32, u32, u32))w->ids[i].func_ptr; - if (w->ids[i].func_ptr) + if (w->ids[i].func_ptr) { + memory_switch_dir(p->page_dir); r->eax = func(r->ebx, r->ecx, r->edx, r->esi); + memory_switch_dir(dir_bak); + } memset(&w->ids[i], 0, sizeof(w->ids[i])); p->wait.id_cnt--; p->state = PROC_RUNNING; @@ -252,6 +258,18 @@ struct proc *proc_make(enum proc_priv priv) return proc; } +void proc_stack_push(struct proc *proc, u32 data) +{ + struct page_dir *prev; + memory_backup_dir(&prev); + memory_switch_dir(proc->page_dir); + + proc->regs.useresp -= sizeof(data); + *(u32 *)proc->regs.useresp = data; + + memory_switch_dir(prev); +} + // TODO: Procfs needs a simpler interface structure (memcmp and everything sucks) static const char *procfs_parse_path(const char **path, u32 *pid) @@ -437,18 +455,6 @@ static u8 procfs_ready(const char *path, struct device *dev) return 1; } -static void proc_stack_push(struct proc *proc, u32 data) -{ - struct page_dir *prev; - memory_backup_dir(&prev); - memory_switch_dir(proc->page_dir); - - proc->regs.useresp -= sizeof(data); - *(u32 *)proc->regs.useresp = data; - - memory_switch_dir(prev); -} - extern void proc_jump_userspace(void); u32 _esp, _eip; diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 31cdf5f..dc49d67 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -71,22 +71,14 @@ static void syscall_handler(struct regs *r) char *path = (char *)r->ebx; struct proc *proc = proc_make(PROC_PRIV_NONE); r->eax = (u32)bin_load(path, proc); - u32 argc = 3; // TODO: Add argc evaluator - char **argv = malloc(sizeof(*argv) * (argc + 1)); - argv[0] = (char *)r->ecx; - argv[1] = (char *)r->edx; - argv[2] = (char *)r->esi; - argv[3] = (char *)r->edi; - argv[4] = NULL; - ((u32 *)proc->regs.useresp)[0] = argc; - ((u32 *)proc->regs.useresp)[1] = (u32)argv; + // TODO: Reimplement argc,argv + proc_stack_push(proc, 0); if (r->eax) proc_exit(proc, (int)r->eax); proc_yield(r); break; } case SYS_EXIT: { - print("EXIT!\n"); proc_exit(proc_current(), (int)r->ebx); break; } diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 6a1c063..590875c 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -100,6 +100,6 @@ void memory_free(struct page_dir *dir, struct memory_range vrange); void memory_switch_dir(struct page_dir *dir); void memory_backup_dir(struct page_dir **backup); -void memory_install(struct mem_info *mem_info); +void memory_install(struct mem_info *mem_info, struct vid_info *vid_info); #endif diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index de4eb84..a44fd68 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -70,5 +70,6 @@ void proc_clear_quantum(void); void proc_enable_waiting(u32 id, enum proc_wait_type type); void proc_wait_for(u32 id, enum proc_wait_type type, u32 func_ptr); struct proc *proc_make(enum proc_priv priv); +void proc_stack_push(struct proc *proc, u32 data); #endif diff --git a/kernel/main.c b/kernel/main.c index 118fe11..3b75c7d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -30,7 +30,7 @@ void kernel_main(struct mem_info *mem_info, struct vid_info *vid_info) serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n"); serial_print("Serial connected.\n"); - memory_install(mem_info); + memory_install(mem_info, vid_info); cpu_enable_features(); cpu_print(); diff --git a/libc/alloc.c b/libc/alloc.c index 083f2c0..4ccf35f 100644 --- a/libc/alloc.c +++ b/libc/alloc.c @@ -139,7 +139,7 @@ static void *_malloc(u32 req_size) l_mem_root = allocate_new_page(size); if (l_mem_root == NULL) { liballoc_unlock(); - return NULL; + panic("Malloc failed!\n"); } } @@ -295,6 +295,7 @@ static void *_malloc(u32 req_size) liballoc_unlock(); + panic("Malloc failed!\n"); return NULL; } @@ -361,6 +362,7 @@ static void *_realloc(void *ptr, u32 size) if (min->magic != LIBALLOC_MAGIC) { liballoc_unlock(); + panic("Malloc failed!\n"); return NULL; } -- cgit v1.2.3