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/inc/mm.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 kernel/inc/mm.h (limited to 'kernel/inc/mm.h') 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 -- cgit v1.2.3 From 03e53516ac31639a47584bd7be655cd2f6f44eb9 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Fri, 5 Mar 2021 18:21:57 +0100 Subject: Oh man... Idfk anymore --- kernel/features/load.c | 31 +++++++++++++++++++++++-------- kernel/features/mm.c | 5 +++++ kernel/inc/mm.h | 13 ++++++++++++- 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'kernel/inc/mm.h') diff --git a/kernel/features/load.c b/kernel/features/load.c index 4b3f8ea..31e22dc 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -6,15 +6,21 @@ #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) { - u32 stack; - memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_CLEAR, &stack); + /* 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); - proc->regs.ebp = stack; - proc->regs.useresp = stack; + proc->regs.ebp = PROC_STACK_ADDR; + proc->regs.useresp = PROC_STACK_ADDR; proc->regs.eip = entry; proc->entry = entry; } @@ -23,13 +29,22 @@ int bin_load(const char *path, struct proc *proc) { struct stat s = { 0 }; vfs_stat(path, &s); - u32 data; - memory_alloc(proc->page_dir, PAGE_ALIGN_UP(s.size), MEMORY_CLEAR, &data); - if (!vfs_read(path, (void *)data, 0, s.size)) + struct proc *current = proc_current(); + struct page_dir *prev = current ? current->page_dir : memory_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); + + if (!vfs_read(path, (void *)PROC_DATA_ADDR, 0, s.size)) { + memory_dir_switch(prev); return 1; + } strcpy(proc->name, path); - proc_load(proc, data); + proc_load(proc, PROC_DATA_ADDR); + memory_dir_switch(prev); return 0; } diff --git a/kernel/features/mm.c b/kernel/features/mm.c index ad70685..b17d9fc 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -128,8 +128,13 @@ u32 virtual_to_physical(struct page_dir *dir, u32 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 (table_entry->bits.address * PAGE_SIZE) + (vaddr & (PAGE_SIZE - 1)); } diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 00d9e4b..e680ab7 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -10,6 +10,8 @@ * Physical */ +u32 physical_alloc(u32 n); + /** * Virtual */ @@ -63,6 +65,10 @@ struct page_dir { union page_dir_entry entries[PAGE_COUNT]; } PACKED; +u32 virtual_to_physical(struct page_dir *dir, u32 vaddr); +void virtual_map(struct page_dir *dir, u32 vaddr, u32 paddr, u32 n, u8 user); +struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, + u32 flags); void paging_install(struct mem_info *mem_info); /** @@ -79,9 +85,14 @@ struct memory_range { u32 size; }; +struct memory_range memory_range_from_address(u32 base, u32 size); +struct memory_range memory_range_around_address(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); +// TODO: Remove these wrappers completely? +/* void memory_alloc(struct page_dir *dir, u32 size, u32 flags, u32 *out); */ +/* void memory_map(struct page_dir *dir, struct memory_range range, u32 flags); */ struct page_dir *memory_kernel_dir(void); #endif -- cgit v1.2.3 From 776f1da4686d57dfa1c398d3b875d174fe6082c6 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Mon, 8 Mar 2021 12:25:40 +0100 Subject: im stoopid and i know it --- kernel/features/mm.c | 461 +++++++++++++++++++++++++++------------------------ kernel/inc/mm.h | 32 ++-- 2 files changed, 257 insertions(+), 236 deletions(-) (limited to 'kernel/inc/mm.h') diff --git a/kernel/features/mm.c b/kernel/features/mm.c index b17d9fc..cde9a94 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -9,21 +9,24 @@ #include +static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; +static struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; + /** - * Paging + * Lowlevel paging */ -void paging_disable(void) +static void paging_disable(void) { cr0_set(cr0_get() | 0x7fffffff); } -void paging_enable(void) +static void paging_enable(void) { cr0_set(cr0_get() | 0x80000000); } -void paging_switch_dir(u32 dir) +static void paging_switch_dir(u32 dir) { assert(dir); cr3_set(dir); @@ -31,68 +34,131 @@ void paging_switch_dir(u32 dir) 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 *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); +} + /** * Physical */ static u32 memory_used = 0; static u32 memory_total = 0; +static u32 best_bet = 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))) +static u8 physical_page_is_used(u32 addr) +{ + u32 page = addr / PAGE_SIZE; + return memory[page / 8] & (1 << (page % 8)); +} + +static void physical_page_set_used(u32 address) +{ + u32 page = address / PAGE_SIZE; + + if (page == best_bet) + best_bet++; -#define PHYSICAL_SET_FREE(addr) \ - (memory[(u32)(addr) / PAGE_SIZE / 8] &= ~(1 << ((u32)(addr) / PAGE_SIZE % 8))) + memory[page / 8] |= 1 << (page % 8); +} -u8 physical_is_used(u32 addr, u32 n) +static void physical_page_set_free(u32 address) { - for (u32 i = 0; i < n; i++) { - if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) - return 1; - } - return 0; + u32 page = address / PAGE_SIZE; + + if (page < best_bet) + best_bet = page; + + memory[page / 8] &= ~(1 << (page % 8)); } -void physical_set_used(u32 addr, u32 n) +static void physical_set_used(struct memory_range range) { - for (u32 i = 0; i < n; i++) { - if (!PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { + u32 addr = range.base + i * PAGE_SIZE; + if (!physical_page_is_used(addr)) { memory_used += PAGE_SIZE; - PHYSICAL_SET_USED(addr + (i * PAGE_SIZE)); + physical_page_set_used(addr); } } } -void physical_set_free(u32 addr, u32 n) +static void physical_set_free(struct memory_range range) { - for (u32 i = 0; i < n; i++) { - if (PHYSICAL_IS_USED(addr + (i * PAGE_SIZE))) { + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { + u32 addr = range.base + i * PAGE_SIZE; + + if (physical_page_is_used(addr)) { memory_used -= PAGE_SIZE; - PHYSICAL_SET_FREE(addr + (i * PAGE_SIZE)); + physical_page_set_free(addr); } } } -u32 physical_alloc(u32 n) +static u8 physical_is_used(struct memory_range range) { - 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; + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + + for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { + u32 addr = range.base + i * PAGE_SIZE; + + if (physical_page_is_used(addr)) + return 1; + } + + return 0; +} + +static struct memory_range physical_alloc(u32 size) +{ + assert(PAGE_ALIGNED(size)); + + for (u32 i = best_bet; i < ((memory_total - size) / PAGE_SIZE); i++) { + struct memory_range range = memory_range(i * PAGE_SIZE, size); + + if (!physical_is_used(range)) { + physical_set_used(range); + return range; } } panic("Out of physical memory!\n"); - return 0; + return memory_range(0, 0); } -void physical_free(u32 addr, u32 n) +static void physical_free(struct memory_range range) { - physical_set_free(addr, n); + assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + physical_set_free(range); } /** @@ -102,9 +168,6 @@ void physical_free(u32 addr, u32 n) #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); @@ -116,10 +179,8 @@ u8 virtual_present(struct page_dir *dir, u32 vaddr) 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; + return !table_entry->bits.present; } u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) @@ -139,10 +200,9 @@ u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) 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) +void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u32 flags) { - for (u32 i = 0; i < n; i++) { + 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); @@ -150,41 +210,42 @@ void virtual_map(struct page_dir *dir, u32 vaddr, u32 paddr, u32 n, u8 user) 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); + table = memory_alloc_identity(dir, MEMORY_CLEAR); dir_entry->bits.present = 1; dir_entry->bits.writable = 1; - dir_entry->bits.user = user; - dir_entry->bits.address = (u32)table >> 12; + dir_entry->bits.user = 1; + dir_entry->bits.address = (u32)(table) >> 12; } + union page_table_entry *table_entry = &table->entries[pti]; table_entry->bits.present = 1; table_entry->bits.writable = 1; - table_entry->bits.user = user; - table_entry->bits.address = (paddr + offset) >> 12; + table_entry->bits.user = flags & MEMORY_USER; + table_entry->bits.address = (prange.base + offset) >> 12; } paging_invalidate_tlb(); } -struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, - u32 flags) +struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range prange, u32 flags) { - u8 is_user = flags & MEMORY_USER; + u8 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++) { + + for (u32 i = (user ? 256 : 1) * PAGE_COUNT; i < (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); + + if (size == prange.size) { + virtual_map(dir, prange, vaddr, flags); return memory_range(vaddr, size); } } else { @@ -196,15 +257,18 @@ struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range phys return memory_range(0, 0); } -void virtual_free(struct page_dir *dir, struct memory_range virtual_range) +void virtual_free(struct page_dir *dir, struct memory_range vrange) { - for (u32 i = 0; i < virtual_range.size / PAGE_SIZE; i++) { + for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) { u32 offset = i * PAGE_SIZE; - u32 pdi = PDI(virtual_range.base + offset); - u32 pti = PTI(virtual_range.base + offset); + 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); union page_table_entry *table_entry = &table->entries[pti]; @@ -216,181 +280,165 @@ void virtual_free(struct page_dir *dir, struct memory_range virtual_range) paging_invalidate_tlb(); } -/** - * Memory wrapper - */ - -extern u32 kernel_start; -extern u32 kernel_end; - -struct memory_range memory_range_from_address(u32 base, u32 size) +struct page_dir *virtual_create_dir(void) { - u32 align = PAGE_SIZE - base % PAGE_SIZE; + struct page_dir *dir = memory_alloc(&kernel_dir, sizeof(*dir), MEMORY_CLEAR); - if (base % PAGE_SIZE == 0) { - align = 0; - } + for (u32 i = 0; i < 256; i++) { + union page_dir_entry *dir_entry = &dir->entries[i]; - base += align; - size -= align; + dir_entry->bits.user = 0; + dir_entry->bits.writable = 1; + dir_entry->bits.present = 1; + dir_entry->bits.address = (u32)&kernel_tables[i] / PAGE_SIZE; + } - size -= size % PAGE_SIZE; + return dir; +} - return memory_range(base, size); +struct page_dir *virtual_kernel_dir(void) +{ + return &kernel_dir; } -struct memory_range memory_range_around_address(u32 base, u32 size) +void virtual_destroy_dir(struct page_dir *dir) { - u32 align = base % PAGE_SIZE; + assert(dir != &kernel_dir); - base -= align; - size += align; + 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) { + u32 paddr = table_entry->bits.address * PAGE_SIZE; + physical_free(memory_range(paddr, PAGE_SIZE)); + } + } - size += PAGE_SIZE - size % PAGE_SIZE; + memory_free(&kernel_dir, memory_range((u32)table, sizeof(*table))); + } + } - return memory_range(base, size); + memory_free(&kernel_dir, memory_range((u32)dir, sizeof(*dir))); } -static struct memory_range kernel_memory_range(void) -{ - return memory_range_around_address((u32)&kernel_start, - (u32)&kernel_end - (u32)&kernel_start); -} +/** + * Memory wrappers + */ -void memory_map_identity(struct page_dir *dir, struct memory_range range, u32 flags) +void *memory_alloc(struct page_dir *dir, u32 size, u32 flags) { - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + assert(PAGE_ALIGNED(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); -} + if (!size) + return 0; -void memory_map(struct page_dir *dir, struct memory_range range, u32 flags) -{ - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + struct memory_range prange = physical_alloc(size); + if (prange.size == 0) + return 0; - 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); - } + u32 vaddr = virtual_alloc(dir, prange, flags).base; + if (!vaddr) { + physical_free(prange); + return 0; } if (flags & MEMORY_CLEAR) - memset((void *)range.base, 0, range.size); + memset((void *)vaddr, 0, size); + + return (void *)vaddr; } -void memory_alloc_identity(struct page_dir *dir, u32 flags, u32 *out) +void *memory_alloc_identity(struct page_dir *dir, u32 flags) { 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); + struct memory_range range = memory_range(i * PAGE_SIZE, PAGE_SIZE); + if (!virtual_present(dir, range.base) && !physical_is_used(range)) { + physical_set_used(range); + virtual_map(dir, range, range.base, flags); if (flags & MEMORY_CLEAR) - memset((void *)addr, 0, PAGE_SIZE); - - *out = addr; - - return; + memset((void *)range.base, 0, PAGE_SIZE); + return (void *)range.base; } } - *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; + return 0; } -void memory_free(struct page_dir *dir, struct memory_range range) +void memory_free(struct page_dir *dir, struct memory_range vrange) { - assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); + assert(PAGE_ALIGNED(vrange.base) && PAGE_ALIGNED(vrange.size)); - for (u32 i = 0; i < range.size / PAGE_SIZE; i++) { - u32 vaddr = range.base + i * PAGE_SIZE; + for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) { + u32 vaddr = vrange.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 memory_range page_prange = + memory_range(virtual_to_physical(dir, vaddr), PAGE_SIZE); + struct memory_range page_vrange = memory_range(vaddr, PAGE_SIZE); + physical_free(page_prange); + virtual_free(dir, page_vrange); } } } -struct page_dir *memory_dir_create(void) +void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags) { - struct page_dir *dir = NULL; - memory_alloc(&kernel_dir, sizeof(*dir), MEMORY_CLEAR, (u32 *)&dir); - memset(dir, 0, sizeof(*dir)); + assert(PAGE_ALIGNED(prange.base) && PAGE_ALIGNED(prange.size)); - 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; - } + physical_set_used(prange); + virtual_map(dir, prange, prange.base, flags); + if (flags & MEMORY_CLEAR) + memset((void *)prange.base, 0, prange.size); +} - return dir; +void memory_switch_dir(struct page_dir *dir) +{ + paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); } -void memory_dir_destroy(struct page_dir *dir) +struct memory_range memory_range_from(u32 base, u32 size) { - 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); - } + u32 align = PAGE_SIZE - base % PAGE_SIZE; - memory_free(&kernel_dir, memory_range((u32)table, sizeof(*table))); - } + if (base % PAGE_SIZE == 0) { + align = 0; } - memory_free(&kernel_dir, memory_range((u32)dir, sizeof(*dir))); + + base += align; + size -= align; + + size -= size % PAGE_SIZE; + + return memory_range(base, size); } -void memory_dir_switch(struct page_dir *dir) +struct memory_range memory_range_around(u32 base, u32 size) { - paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); + u32 align = base % PAGE_SIZE; + + base -= align; + size += align; + + size += PAGE_SIZE - size % PAGE_SIZE; + + return memory_range(base, size); } -struct page_dir *memory_kernel_dir(void) +extern u32 kernel_start; +extern u32 kernel_end; +static struct memory_range kernel_memory_range(void) { - return &kernel_dir; + return memory_range_around((u32)&kernel_start, (u32)&kernel_end - (u32)&kernel_start); } -void memory_initialize(struct mem_info *mem_info) +void memory_install(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; - } + heap_init(HEAP_START); - // 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) @@ -402,13 +450,21 @@ void memory_initialize(struct mem_info *mem_info) /* printf("Memory region: %x-%x\n", p->lbase, p->lbase + size); */ if (p->type == MEMORY_AVAILABLE) { - physical_set_free(p->lbase, size / PAGE_SIZE); + physical_set_free(memory_range_around(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); } } + for (u32 i = 0; i < 256; i++) { + union page_dir_entry *dir_entry = &kernel_dir.entries[i]; + 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; + } + memory_used = 0; printf("Detected memory: %dKiB (%dMiB)\n", memory_total >> 10, memory_total >> 20); @@ -416,56 +472,23 @@ void memory_initialize(struct mem_info *mem_info) 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_map_identity(&kernel_dir, memory_range_around(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_map_identity(&kernel_dir, memory_range_around(HEAP_START, HEAP_INIT_SIZE), MEMORY_NONE); // TODO: Triple fault prevention? Probably bootloader stuff or something - memory_map_identity(&kernel_dir, memory_range_around_address(0x7000, 0x1000), MEMORY_NONE); + memory_map_identity(&kernel_dir, memory_range_around(0x7000, 0x1000), MEMORY_NONE); // Unmap NULL byte/page - virtual_free(&kernel_dir, memory_range(0, PAGE_SIZE)); - physical_set_used(0, 1); + struct memory_range zero = memory_range(0, PAGE_SIZE); + virtual_free(&kernel_dir, zero); + physical_set_used(zero); - memory_dir_switch(&kernel_dir); + memory_switch_dir(&kernel_dir); 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/inc/mm.h b/kernel/inc/mm.h index e680ab7..6d3714d 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -6,12 +6,15 @@ #include #include +struct memory_range { + u32 base; + u32 size; +}; + /** * Physical */ -u32 physical_alloc(u32 n); - /** * Virtual */ @@ -66,10 +69,11 @@ struct page_dir { } PACKED; u32 virtual_to_physical(struct page_dir *dir, u32 vaddr); -void virtual_map(struct page_dir *dir, u32 vaddr, u32 paddr, u32 n, u8 user); +void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u32 flags); struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, u32 flags); -void paging_install(struct mem_info *mem_info); +struct page_dir *virtual_create_dir(void); +struct page_dir *virtual_kernel_dir(void); /** * Memory wrappers @@ -80,19 +84,13 @@ void paging_install(struct mem_info *mem_info); #define MEMORY_CLEAR (1 << 1) #define memory_range(base, size) ((struct memory_range){ (base), (size) }) -struct memory_range { - u32 base; - u32 size; -}; - -struct memory_range memory_range_from_address(u32 base, u32 size); -struct memory_range memory_range_around_address(u32 base, u32 size); +struct memory_range memory_range_from(u32 base, u32 size); +struct memory_range memory_range_around(u32 base, u32 size); -struct page_dir *memory_dir_create(void); -void memory_dir_switch(struct page_dir *dir); -// TODO: Remove these wrappers completely? -/* void memory_alloc(struct page_dir *dir, u32 size, u32 flags, u32 *out); */ -/* void memory_map(struct page_dir *dir, struct memory_range range, u32 flags); */ -struct page_dir *memory_kernel_dir(void); +void memory_install(struct mem_info *mem_info); +void *memory_alloc(struct page_dir *dir, u32 size, u32 flags); +void *memory_alloc_identity(struct page_dir *dir, u32 flags); +void memory_free(struct page_dir *dir, struct memory_range vrange); +void memory_switch_dir(struct page_dir *dir); #endif -- 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/inc/mm.h') 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 0aef683b9d1e08555791426ba12223ed78051353 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Fri, 12 Mar 2021 17:27:01 +0100 Subject: Boots successfully... --- Makefile | 2 +- apps/Makefile | 2 +- apps/idle.c | 7 +++++++ apps/init.c | 1 + kernel/features/load.c | 17 ++++------------- kernel/features/mm.c | 24 +++++++++++++++--------- kernel/features/proc.c | 19 +++++-------------- kernel/inc/load.h | 1 - kernel/inc/mm.h | 9 ++++++++- libc/cpu.c | 7 +++++++ libc/inc/cpu.h | 1 + libc/print.c | 1 + 12 files changed, 51 insertions(+), 40 deletions(-) create mode 100644 apps/idle.c (limited to 'kernel/inc/mm.h') diff --git a/Makefile b/Makefile index a9817cd..1e20a7a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ CFLAGS_DEFAULT = $(CFLAGS_WARNINGS) $(CFLAGS_OPTIMIZATION) -std=c99 -m32 -nostdl all: compile -debug: CFLAGS_DEFAULT += -Wno-error -ggdb3 -s -fstack-protector-all -fsanitize=undefined +debug: CFLAGS_DEFAULT += -Wno-error -ggdb3 -s -fsanitize=undefined # -fstack-protector-all # TODO: Fix stack protector in userspace debug: compile export diff --git a/apps/Makefile b/apps/Makefile index 8426b9c..2c6c643 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,6 +1,6 @@ # MIT License, Copyright (c) 2020 Marvin Borner -COBJS = init.o wm.o test.o window.o #mandelbrot.o window.o exec.o files.o test.o cc.o browser.o server.o +COBJS = init.o idle.o wm.o test.o window.o #mandelbrot.o window.o exec.o files.o test.o cc.o browser.o server.o CC = ccache ../cross/opt/bin/i686-elf-gcc LD = ccache ../cross/opt/bin/i686-elf-ld OC = ccache ../cross/opt/bin/i686-elf-objcopy diff --git a/apps/idle.c b/apps/idle.c new file mode 100644 index 0000000..3f10c3e --- /dev/null +++ b/apps/idle.c @@ -0,0 +1,7 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +int main(void) +{ + while (1) + ; +} diff --git a/apps/init.c b/apps/init.c index 7044365..9e57078 100644 --- a/apps/init.c +++ b/apps/init.c @@ -8,6 +8,7 @@ int main(int argc, char **argv) { + log("Loaded!\n"); while (1) { }; (void)argc; diff --git a/kernel/features/load.c b/kernel/features/load.c index ec9a387..4ad2cbf 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -8,25 +8,16 @@ #define PROC_STACK_SIZE 0x4000 -/*void proc_load(struct proc *proc, u32 entry) -{ - 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 = 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 : virtual_kernel_dir(); - u32 size = PAGE_ALIGN_UP(s.size); + struct page_dir *prev; + memory_backup_dir(&prev); memory_switch_dir(proc->page_dir); + + 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)) { diff --git a/kernel/features/mm.c b/kernel/features/mm.c index c39b8b7..5fe70fd 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -15,10 +15,10 @@ static struct page_table kernel_tables[256] ALIGNED(PAGE_SIZE) = { 0 }; * Lowlevel paging */ -static void paging_disable(void) +/*static void paging_disable(void) { cr0_set(cr0_get() | 0x7fffffff); -} +}*/ static void paging_enable(void) { @@ -27,7 +27,6 @@ static void paging_enable(void) static void paging_switch_dir(u32 dir) { - assert(dir); cr3_set(dir); } @@ -154,7 +153,7 @@ struct memory_range physical_alloc(u32 size) return memory_range(0, 0); } -static void physical_free(struct memory_range range) +void physical_free(struct memory_range range) { assert(PAGE_ALIGNED(range.base) && PAGE_ALIGNED(range.size)); physical_set_free(range); @@ -297,11 +296,6 @@ struct page_dir *virtual_create_dir(void) return dir; } -struct page_dir *virtual_kernel_dir(void) -{ - return &kernel_dir; -} - void virtual_destroy_dir(struct page_dir *dir) { assert(dir != &kernel_dir); @@ -326,6 +320,11 @@ void virtual_destroy_dir(struct page_dir *dir) memory_free(&kernel_dir, memory_range((u32)dir, sizeof(*dir))); } +struct page_dir *virtual_kernel_dir(void) +{ + return &kernel_dir; +} + /** * Memory wrappers */ @@ -405,6 +404,13 @@ void memory_switch_dir(struct page_dir *dir) paging_switch_dir(virtual_to_physical(&kernel_dir, (u32)dir)); } +void memory_backup_dir(struct page_dir **backup) +{ + struct proc *proc = proc_current(); + struct page_dir *dir = proc ? proc->page_dir : virtual_kernel_dir(); + *backup = dir; +} + struct memory_range memory_range_from(u32 base, u32 size) { u32 align = PAGE_SIZE - base % PAGE_SIZE; diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 4d1311e..db2291c 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -76,12 +76,6 @@ void scheduler(struct regs *regs) /* printf("{%d}", ((struct proc *)current->data)->pid); */ } -static void kernel_idle(void) -{ - while (1) - ; -} - void proc_print(void) { struct node *node = proc_list->head; @@ -328,7 +322,7 @@ static s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, stru } } - printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev); + printf("ERR: %s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev); return -1; } @@ -472,11 +466,10 @@ 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); + bin_load("/bin/idle", kernel_proc); + 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,9 +489,7 @@ void proc_init(void) /* ((u32 *)_esp)[-1] = (u32)argv; // Second argument (argv) */ printf("Jumping to userspace!\n"); - /* 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/load.h b/kernel/inc/load.h index 330caca..f493e84 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -5,7 +5,6 @@ #include -void proc_load(struct proc *proc, u32 entry); int bin_load(const char *path, struct proc *proc); #endif diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index aad4ffd..6a1c063 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -16,6 +16,7 @@ struct memory_range { */ struct memory_range physical_alloc(u32 size); +void physical_free(struct memory_range range); /** * Virtual @@ -70,11 +71,14 @@ struct page_dir { union page_dir_entry entries[PAGE_COUNT]; } PACKED; +u8 virtual_present(struct page_dir *dir, u32 vaddr); u32 virtual_to_physical(struct page_dir *dir, u32 vaddr); void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u32 flags); struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, u32 flags); +void virtual_free(struct page_dir *dir, struct memory_range vrange); struct page_dir *virtual_create_dir(void); +void virtual_destroy_dir(struct page_dir *dir); struct page_dir *virtual_kernel_dir(void); /** @@ -89,10 +93,13 @@ struct page_dir *virtual_kernel_dir(void); struct memory_range memory_range_from(u32 base, u32 size); struct memory_range memory_range_around(u32 base, u32 size); -void memory_install(struct mem_info *mem_info); void *memory_alloc(struct page_dir *dir, u32 size, u32 flags); void *memory_alloc_identity(struct page_dir *dir, u32 flags); +void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags); 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); #endif diff --git a/libc/cpu.c b/libc/cpu.c index cb9aa49..8ca4d27 100644 --- a/libc/cpu.c +++ b/libc/cpu.c @@ -82,6 +82,13 @@ void cr0_set(u32 cr0) __asm__ volatile("movl %%eax, %%cr0" ::"a"(cr0)); } +u32 cr3_get(void) +{ + u32 cr3; + __asm__ volatile("movl %%cr0, %%eax" : "=a"(cr3)); + return cr3; +} + void cr3_set(u32 cr3) { __asm__ volatile("movl %%eax, %%cr3" ::"a"(cr3)); diff --git a/libc/inc/cpu.h b/libc/inc/cpu.h index 161b7a4..d709d86 100644 --- a/libc/inc/cpu.h +++ b/libc/inc/cpu.h @@ -29,6 +29,7 @@ void fpu_restore(void); u32 cr0_get(void); void cr0_set(u32 cr0); +u32 cr3_get(void); void cr3_set(u32 cr3); u32 cr4_get(void); void cr4_set(u32 cr4); diff --git a/libc/print.c b/libc/print.c index 173e117..1c577e5 100644 --- a/libc/print.c +++ b/libc/print.c @@ -238,6 +238,7 @@ NORETURN void panic(const char *format, ...) vsprintf(buf, format, ap); va_end(ap); #ifdef kernel + print("--- DON'T PANIC! ---\n"); print(buf); loop(); #else -- 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/inc/mm.h') 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 From 6dec7db5158447b66f31a3f786ce2916cab83cec Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Sun, 14 Mar 2021 16:06:57 +0100 Subject: Maaany fixes :) I don't have the motivation to write better commit messages... --- apps/init.c | 6 ++-- apps/window.c | 4 +++ apps/wm.c | 71 ++++++++++++++++++++------------------------- kernel/drivers/interrupts.c | 4 +++ kernel/drivers/keyboard.c | 6 ++-- kernel/drivers/mouse.c | 6 ++-- kernel/features/fs.c | 4 +-- kernel/features/mm.c | 4 +-- kernel/features/proc.c | 20 ++++++++++--- kernel/inc/mm.h | 3 ++ libc/alloc.c | 2 -- libc/inc/def.h | 3 ++ libc/inc/sys.h | 4 ++- libgui/gfx.c | 9 +++--- libgui/gui.c | 18 ++++++++---- libgui/inc/gfx.h | 7 ++--- libgui/inc/gui.h | 3 +- libgui/inc/msg.h | 24 +++++++++++---- libgui/msg.c | 22 +++++++------- run | 9 +++++- 20 files changed, 135 insertions(+), 94 deletions(-) (limited to 'kernel/inc/mm.h') diff --git a/apps/init.c b/apps/init.c index f854a81..c59e3bf 100644 --- a/apps/init.c +++ b/apps/init.c @@ -6,13 +6,15 @@ #include #include +#include + int main(int argc, char **argv) { UNUSED(argc); UNUSED(argv); 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/window.c b/apps/window.c index ac29ba1..90a414c 100644 --- a/apps/window.c +++ b/apps/window.c @@ -8,6 +8,9 @@ int main(void) { struct gui_window win = { 0 }; assert(gui_new_window(&win) > 0); + while (1) + ; +#if 0 gfx_fill(win.ctx, COLOR_GREEN); // Professional testing for (int i = 0; i < 12; i++) { @@ -16,5 +19,6 @@ int main(void) } assert(gui_redraw_window(win.id) > 0); log("%d\n", win.ctx->size.x); +#endif return 0; } diff --git a/apps/wm.c b/apps/wm.c index 8eb6f70..ecc7cb2 100644 --- a/apps/wm.c +++ b/apps/wm.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -308,46 +309,34 @@ static void handle_event_mouse(struct event_mouse *event) window_redraw(cursor); } -static void handle_message_new_window(struct message *msg) +static void handle_message_new_window(struct message_new_window *msg) { - if (!msg->data) { - msg_send(msg->src, GUI_NEW_WINDOW | MSG_FAILURE, NULL); - return; - } - struct gui_window *buf = msg->data; - struct window *win = window_new((struct client){ .pid = msg->src }, "idk", vec2(500, 600), - vec2(600, 400), 0); - buf->id = win->id; - buf->ctx = &win->ctx; - buf->pos = &win->pos; - msg_send(msg->src, GUI_NEW_WINDOW | MSG_SUCCESS, NULL); + struct window *win = window_new((struct client){ .pid = msg->header.src }, "idk", + vec2(500, 600), vec2(600, 400), 0); + msg->ctx = win->ctx; + msg->id = win->id; + msg_send(msg->header.src, GUI_NEW_WINDOW | MSG_SUCCESS, msg, sizeof(*msg)); /* window_redraw(win); */ } -static void handle_message_redraw_window(struct message *msg) +static void handle_message_redraw_window(struct message_redraw_window *msg) { - if (!msg->data) { - msg_send(msg->src, GUI_REDRAW_WINDOW | MSG_FAILURE, NULL); - return; - } - u32 id = *(u32 *)msg->data; + u32 id = msg->id; struct window *win = window_find(id); if (!win) { - msg_send(msg->src, GUI_REDRAW_WINDOW | MSG_FAILURE, NULL); + msg_send(msg->header.src, GUI_REDRAW_WINDOW | MSG_FAILURE, NULL, + sizeof(msg->header)); return; } - msg_send(msg->src, GUI_REDRAW_WINDOW | MSG_SUCCESS, NULL); + msg_send(msg->header.src, GUI_REDRAW_WINDOW | MSG_SUCCESS, NULL, sizeof(msg->header)); window_redraw(win); } -static void handle_message(struct message *msg) +static void handle_message(void *msg) { - if (msg->magic != MSG_MAGIC) { - log("Message magic doesn't match!\n"); - return; - } + struct message_header *header = msg; - switch (msg->type) { + switch (header->type) { case GUI_NEW_WINDOW: handle_message_new_window(msg); break; @@ -355,8 +344,8 @@ static void handle_message(struct message *msg) handle_message_redraw_window(msg); break; default: - log("Message type %d not implemented!\n", msg->type); - msg_send(msg->src, MSG_FAILURE, NULL); + log("Message type %d not implemented!\n", header->type); + msg_send(header->src, MSG_FAILURE, NULL, sizeof(*header)); } } @@ -389,32 +378,34 @@ int main(int argc, char **argv) gfx_load_wallpaper(&cursor->ctx, "/res/cursor.png"); window_redraw(wallpaper); - struct message msg = { 0 }; + u8 msg[1024] = { 0 }; struct event_keyboard event_keyboard = { 0 }; struct event_mouse event_mouse = { 0 }; - const char *listeners[] = { "/dev/kbd", "/dev/mouse", "/proc/self/msg" }; + const char *listeners[] = { "/dev/kbd", "/dev/mouse", "/proc/self/msg", NULL }; while (1) { int poll_ret = 0; if ((poll_ret = poll(listeners)) >= 0) { if (poll_ret == 0) { if (read(listeners[poll_ret], &event_keyboard, 0, - sizeof(event_keyboard)) > 0) + sizeof(event_keyboard)) > 0) { handle_event_keyboard(&event_keyboard); - continue; + continue; + } } else if (poll_ret == 1) { if (read(listeners[poll_ret], &event_mouse, 0, - sizeof(event_mouse)) > 0) + sizeof(event_mouse)) > 0) { handle_event_mouse(&event_mouse); - continue; + continue; + } } else if (poll_ret == 2) { - if (read(listeners[poll_ret], &msg, 0, sizeof(msg)) > 0) - handle_message(&msg); - continue; + if (msg_receive(msg, 1024) > 0) { + handle_message(msg); + continue; + } } - } else { - err(1, "POLL ERROR!\n"); } - }; + panic("Poll/read error!\n"); + } // TODO: Execute? free(keymap); diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index fe2321a..2e1444f 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -236,6 +237,9 @@ static void isr_install(void) // Set default routines for (u32 i = 0; i < 256; i++) isr_routines[i] = isr_panic; + + // Set page fault handler + isr_install_handler(14, page_fault_handler); } /** diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index 3ae3c0e..dbee8e1 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -66,10 +66,10 @@ static s32 keyboard_read(void *buf, u32 offset, u32 count, struct device *dev) if (stack_empty(queue)) return -1; - struct event *e = stack_pop(queue); - memcpy(buf, (u8 *)e + offset, count); + struct event_keyboard *e = stack_pop(queue); + memcpy(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); free(e); - return count; + return MIN(count, sizeof(*e)); } static u8 keyboard_ready(void) diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c index 40094d1..5c481da 100644 --- a/kernel/drivers/mouse.c +++ b/kernel/drivers/mouse.c @@ -94,10 +94,10 @@ static s32 mouse_read(void *buf, u32 offset, u32 count, struct device *dev) if (stack_empty(queue)) return -1; - struct event *e = stack_pop(queue); - memcpy(buf, (u8 *)e + offset, count); + struct event_mouse *e = stack_pop(queue); + memcpy(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); free(e); - return count; + return MIN(count, sizeof(*e)); } void mouse_install(void) diff --git a/kernel/features/fs.c b/kernel/features/fs.c index 20d00e5..c8ad317 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -122,7 +122,7 @@ s32 vfs_mount(struct device *dev, const char *path) s32 vfs_read(const char *path, void *buf, u32 offset, u32 count) { - /* printf("%s READ: %s\n", proc_current()->name, path); */ + /* printf("%s READ: %s\n", proc_current() ? proc_current()->name : "Unknown", path); */ if (!count) return 0; @@ -148,7 +148,7 @@ s32 vfs_read(const char *path, void *buf, u32 offset, u32 count) s32 vfs_write(const char *path, void *buf, u32 offset, u32 count) { - /* printf("%s WRITE: %s\n", proc_current()->name, path); */ + /* printf("%s WRITE: %s\n", proc_current() ? proc_current()->name : "Unknown", path); */ if (!count) return 0; diff --git a/kernel/features/mm.c b/kernel/features/mm.c index bd32683..9eca438 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -32,7 +32,7 @@ static void paging_switch_dir(u32 dir) extern void paging_invalidate_tlb(void); -static void page_fault(struct regs *r) +void page_fault_handler(struct regs *r) { // Check error code const char *type = (r->err_code & 1) ? "present" : "non-present"; @@ -495,6 +495,4 @@ void memory_install(struct mem_info *mem_info, struct vid_info *vid_info) memory_switch_dir(&kernel_dir); paging_enable(); - - isr_install_handler(14, page_fault); } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 6bbe894..b93f7c8 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -305,6 +305,11 @@ static enum stream_defaults procfs_stream(const char *path) } } +struct procfs_message { + u8 *data; + u32 size; +}; + static s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, struct device *dev) { u32 pid = 0; @@ -318,7 +323,10 @@ static s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, stru if (!memcmp(path, "msg", 4)) { void *msg_data = malloc(count); memcpy(msg_data, buf, count); - stack_push_bot(p->messages, msg_data); // TODO: Use offset + struct procfs_message *msg = malloc(sizeof(*msg)); + msg->data = msg_data; + msg->size = count; + stack_push_bot(p->messages, msg); // TODO: Use offset proc_enable_waiting(pid, PROC_WAIT_MSG); return count; } else if (!memcmp(path, "io/", 3)) { @@ -371,12 +379,13 @@ static s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struc if (stack_empty(p->messages)) { return -1; // This shouldn't happen } else { - u8 *msg = stack_pop(p->messages); + struct procfs_message *msg = stack_pop(p->messages); if (!msg) return -1; - memcpy(buf, msg + offset, count); + memcpy(buf, msg->data + offset, MIN(count, msg->size)); + free(msg->data); free(msg); - return count; + return MIN(count, msg->size); } } else if (!memcmp(path, "io/", 3)) { path += 3; @@ -500,7 +509,10 @@ void proc_init(void) printf("Jumping to userspace!\n"); memory_switch_dir(((struct proc *)new->data)->page_dir); + + // You're waiting for a train. A train that will take you far away... proc_jump_userspace(); + while (1) { }; } diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 590875c..d3e37f6 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -5,6 +5,7 @@ #include #include +#include struct memory_range { u32 base; @@ -102,4 +103,6 @@ void memory_backup_dir(struct page_dir **backup); void memory_install(struct mem_info *mem_info, struct vid_info *vid_info); +void page_fault_handler(struct regs *r); + #endif diff --git a/libc/alloc.c b/libc/alloc.c index 4ccf35f..be986dc 100644 --- a/libc/alloc.c +++ b/libc/alloc.c @@ -86,8 +86,6 @@ struct liballoc_minor { #define MAJOR_SIZE (ALIGN_UP(sizeof(struct liballoc_major), 16)) #define MINOR_SIZE (ALIGN_UP(sizeof(struct liballoc_minor), 16)) -#define MIN(__x, __y) ((__x) < (__y) ? (__x) : (__y)) -#define MAX(__x, __y) ((__x) > (__y) ? (__x) : (__y)) static struct liballoc_major *l_mem_root = NULL; static struct liballoc_major *l_best_bet = NULL; diff --git a/libc/inc/def.h b/libc/inc/def.h index db1c95e..c334fcb 100644 --- a/libc/inc/def.h +++ b/libc/inc/def.h @@ -25,6 +25,9 @@ typedef unsigned long long u64; #define UNUSED(a) ((void)(a)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + #define NORETURN __attribute__((noreturn)) #define NO_SANITIZE __attribute__((no_sanitize("undefined"))) #define PACKED __attribute__((packed)) diff --git a/libc/inc/sys.h b/libc/inc/sys.h index 3125cb0..8add0de 100644 --- a/libc/inc/sys.h +++ b/libc/inc/sys.h @@ -93,7 +93,9 @@ int sysv(enum sys num, ...); static inline u32 getpid(void) { - u32 buf = 0; + static u32 buf = 0; + if (buf) + return buf; read("/proc/self/pid", &buf, 0, sizeof(buf)); return buf; } diff --git a/libgui/gfx.c b/libgui/gfx.c index d9457c7..dad8b88 100644 --- a/libgui/gfx.c +++ b/libgui/gfx.c @@ -98,10 +98,11 @@ static void draw_rectangle(struct context *ctx, vec2 pos1, vec2 pos2, u32 c) struct context *gfx_new_ctx(struct context *ctx) { - struct message msg = { 0 }; - assert(msg_send(pidof(WM_PATH), GFX_NEW_CONTEXT, ctx) > 0); - assert(msg_receive(&msg) > 0); - memcpy(ctx, msg.data, sizeof(*ctx)); + /* struct message msg = { 0 }; */ + assert(0); + /* assert(msg_send(pidof(WM_PATH), GFX_NEW_CONTEXT, ctx) > 0); */ + /* assert(msg_receive(&msg) > 0); */ + /* memcpy(ctx, msg.data, sizeof(*ctx)); */ return ctx; } diff --git a/libgui/gui.c b/libgui/gui.c index 2083f23..bc8adb1 100644 --- a/libgui/gui.c +++ b/libgui/gui.c @@ -2,24 +2,30 @@ #include #include +#include #include #define WM_PATH "/bin/wm" s32 gui_new_window(struct gui_window *win) { - struct message msg = { 0 }; - if (msg_send(pidof(WM_PATH), GUI_NEW_WINDOW, win) > 0 && msg_receive(&msg) > 0 && - msg.type == (GUI_NEW_WINDOW | MSG_SUCCESS)) + struct message_new_window msg = { 0 }; + if (msg_send(pidof(WM_PATH), GUI_NEW_WINDOW, &msg, sizeof(msg)) > 0 && + msg_receive(&msg, sizeof(msg)) > 0 && + msg.header.type == (GUI_NEW_WINDOW | MSG_SUCCESS)) { + win->id = msg.id; + win->ctx = msg.ctx; return win->id; + } return -1; } s32 gui_redraw_window(u32 id) { - struct message msg = { 0 }; - if (msg_send(pidof(WM_PATH), GUI_REDRAW_WINDOW, &id) > 0 && msg_receive(&msg) > 0 && - msg.type == (GUI_REDRAW_WINDOW | MSG_SUCCESS)) + struct message_redraw_window msg = { .id = id }; + if (msg_send(pidof(WM_PATH), GUI_REDRAW_WINDOW, &msg, sizeof(msg)) > 0 && + msg_receive(&msg, sizeof(msg)) > 0 && + msg.header.type == (GUI_REDRAW_WINDOW | MSG_SUCCESS)) return id; return -1; } diff --git a/libgui/inc/gfx.h b/libgui/inc/gfx.h index 4a358ca..f3555a4 100644 --- a/libgui/inc/gfx.h +++ b/libgui/inc/gfx.h @@ -5,7 +5,6 @@ #define GFX_H #include -#include #include #include #include @@ -82,8 +81,8 @@ int gfx_font_width(enum font_type); * Wrappers */ -#define gfx_redraw() \ - (msg_send(pidof(WM_PATH), GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization) -#define gfx_redraw_focused() (msg_send(pidof(WM_PATH), GFX_REDRAW_FOCUSED, NULL)) +/* #define gfx_redraw() \ */ +/* (msg_send(pidof(WM_PATH), GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization) */ +/* #define gfx_redraw_focused() (msg_send(pidof(WM_PATH), GFX_REDRAW_FOCUSED, NULL)) */ #endif diff --git a/libgui/inc/gui.h b/libgui/inc/gui.h index 460bf88..d160333 100644 --- a/libgui/inc/gui.h +++ b/libgui/inc/gui.h @@ -8,8 +8,7 @@ struct gui_window { u32 id; - struct context *ctx; - vec2 *pos; + struct context ctx; }; s32 gui_new_window(struct gui_window *win); diff --git a/libgui/inc/msg.h b/libgui/inc/msg.h index db00460..7cbfa2c 100644 --- a/libgui/inc/msg.h +++ b/libgui/inc/msg.h @@ -4,16 +4,28 @@ #define MSG_H #include +#include #define MSG_MAGIC 0x42042069 #define MSG_SUCCESS (1 << 29) #define MSG_FAILURE (1 << 30) -struct message { +struct message_header { u32 magic; - int src; - int type; - void *data; + u32 src; + u32 type; + u32 size; +}; + +struct message_new_window { + struct message_header header; + u32 id; + struct context ctx; +}; + +struct message_redraw_window { + struct message_header header; + u32 id; }; enum message_type { @@ -32,7 +44,7 @@ enum message_type { GUI_MAX }; -int msg_send(u32 pid, enum message_type, void *data); -int msg_receive(struct message *msg); +int msg_send(u32 pid, enum message_type type, void *data, u32 size); +int msg_receive(void *buf, u32 size); #endif diff --git a/libgui/msg.c b/libgui/msg.c index 8448e73..3f58267 100644 --- a/libgui/msg.c +++ b/libgui/msg.c @@ -5,23 +5,23 @@ #include #include -int msg_send(u32 pid, enum message_type type, void *data) +int msg_send(u32 pid, enum message_type type, void *data, u32 size) { - struct message msg = { 0 }; - assert((signed)pid != -1); + assert((signed)pid != -1 && size >= sizeof(struct message_header)); char path[32] = { 0 }; sprintf(path, "/proc/%d/msg", pid); - msg.magic = MSG_MAGIC; - msg.src = getpid(); - msg.type = type; - msg.data = data; - return write(path, &msg, 0, sizeof(msg)); + struct message_header *header = data; + header->magic = MSG_MAGIC; + header->src = getpid(); + header->type = type; + return write(path, data, 0, size); } -int msg_receive(struct message *msg) +int msg_receive(void *buf, u32 size) { - int ret = read("/proc/self/msg", msg, 0, sizeof(*msg)); - if (msg->magic == MSG_MAGIC && ret == sizeof(*msg)) + int ret = read("/proc/self/msg", buf, 0, size); + struct message_header *header = buf; + if (header->magic == MSG_MAGIC) return ret; else return -1; diff --git a/run b/run index 1a8202a..cd03ba3 100755 --- a/run +++ b/run @@ -26,7 +26,7 @@ no_ask="${2}" # TODO: Support -enable-kvm: GPF?! qemu_with_flags() { network="rtl8139" - qemu-system-i386 -cpu max -no-reboot -vga std -rtc base=localtime -m 256M -netdev user,id=net0,hostfwd=tcp:127.0.0.1:8000-10.0.2.15:8000 -device $network,netdev=net0 -object filter-dump,id=dump,netdev=net0,file=dump.pcap "$@" + qemu-system-i386 -d guest_errors -cpu max -no-reboot -vga std -rtc base=localtime -m 256M -netdev user,id=net0,hostfwd=tcp:127.0.0.1:8000-10.0.2.15:8000 -device $network,netdev=net0 -object filter-dump,id=dump,netdev=net0,file=dump.pcap "$@" } make_cross() { @@ -189,6 +189,10 @@ make_addr() { addr2line -e build/"$1".elf -f -p "$2" } +make_cloc() { + cloc . --exclude-dir=build,iso,disk,res,cross +} + make_append_commands() { s="" while read -r data; do @@ -239,6 +243,8 @@ elif [ "${mode}" = "disasm" ]; then make_disasm "$2" "$3" elif [ "${mode}" = "addr" ]; then make_addr "$2" "$3" +elif [ "${mode}" = "cloc" ]; then + make_cloc elif [ "${mode}" = "sync" ]; then make_sync elif [ "${mode}" = "disk" ]; then @@ -267,6 +273,7 @@ else printf "again\t\tOpens QEMU again using the previous build\n" printf "disasm\t\tDisassembles a given part of Melvix\n" printf "addr\t\tResolves an address to a line of code\n" + printf "cloc\t\tCount the total lines of code\n" printf "sync\t\tSyncs the 'tags' and 'compile_commands.json' file\n" printf "disk\t\tPrepares the userspace disk (e.g. fonts)\n" printf "*\t\tAnything else prints this help\n" -- cgit v1.2.3