diff --git a/.gitmodules b/.gitmodules index bf1e091..29b5c7d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "user/pishell"] - path = user/pishell - url = git@github.com:ryuukumar/pishell.git [submodule "lib/newlib-cygwin"] path = lib/newlib-cygwin url = https://sourceware.org/git/newlib-cygwin.git diff --git a/kernel/include/kernel/idt.h b/kernel/include/kernel/idt.h index 739bcbb..78bcdda 100644 --- a/kernel/include/kernel/idt.h +++ b/kernel/include/kernel/idt.h @@ -33,3 +33,5 @@ typedef void (*irq_handler_t) (registers_t*); void init_idt (void); void idt_register_handler (int vector, irq_handler_t handler); void idt_set_flags (int vector, uint8_t gate_type, uint8_t dpl, uint8_t ist); + +void log_registers_to_serial (registers_t* registers); diff --git a/kernel/include/kernel/memmgt.h b/kernel/include/kernel/memmgt.h index 30699f1..bfcd006 100644 --- a/kernel/include/kernel/memmgt.h +++ b/kernel/include/kernel/memmgt.h @@ -99,6 +99,7 @@ void* get_vaddr_from_phys_addr (uint64_t phys_address); void* vaddr_t_to_ptr (vaddr_t* virtual_addr); bool is_vaddr_t_user (vaddr_t* addr); bool is_vaddr_t_lt (vaddr_t* a, vaddr_t* b); +bool is_vaddr_t_eq (vaddr_t a, vaddr_t b); void* alloc_vpages (size_t req_count, bool user); void* alloc_vpage (bool user); diff --git a/kernel/src/kernel/elf.c b/kernel/src/kernel/elf.c index 1d745b2..64fd49b 100644 --- a/kernel/src/kernel/elf.c +++ b/kernel/src/kernel/elf.c @@ -31,6 +31,8 @@ bool verify_elf_loadable (elf64_header_t* elf) { } int load_elf (const char* filepath, process* target_process, uintptr_t* entry_point_r) { + int64_t err = 0; + // TODO: open file as readonly once flags implemented int64_t fd = (int64_t)sys_open ((uint64_t)filepath, 0ull, 0ull); if (fd < 0) return fd; @@ -49,8 +51,13 @@ int load_elf (const char* filepath, process* target_process, uintptr_t* entry_po size_t ph_size = elf_header.elf_phnum * elf_header.elf_phentsize; elf64_pheader_t* program_headers = kmalloc (ph_size); - sys_seek ((uint64_t)fd, elf_header.elf_phoff, SEEK_SET); - sys_read ((uint64_t)fd, (uint64_t)program_headers, ph_size); + err = sys_seek ((uint64_t)fd, elf_header.elf_phoff, SEEK_SET); + if (err < 0) return err; + err = sys_read ((uint64_t)fd, (uint64_t)program_headers, ph_size); + if (err < 0) + return err; + else if (err != (int64_t)ph_size) + return -ENOEXEC; uintptr_t init_break = 0; @@ -69,11 +76,16 @@ int load_elf (const char* filepath, process* target_process, uintptr_t* entry_po alloc_by_cr3 (target_process->p_cr3, (uintptr_t)start, num_pages, is_writable); - sys_seek ((uint64_t)fd, ph->p_offset, SEEK_SET); - sys_read ((uint64_t)fd, ph->p_vaddr, ph->p_filesz); + err = sys_seek ((uint64_t)fd, ph->p_offset, SEEK_SET); + if (err < 0) return err; + err = sys_read ((uint64_t)fd, ph->p_vaddr, ph->p_filesz); + if (err < 0) + return err; + else if (err != (int64_t)ph->p_filesz) + return -ENOEXEC; if (ph->p_memsz > ph->p_filesz) - kmemset ((void*)(ph->p_vaddr + ph->p_filesz), 0, ph->p_memsz - ph->p_filesz); + kmemset_explicit ((void*)(ph->p_vaddr + ph->p_filesz), 0, ph->p_memsz - ph->p_filesz); } init_break = ((init_break + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); diff --git a/kernel/src/kernel/graphics.c b/kernel/src/kernel/graphics.c index 6a1e53f..af32ed0 100644 --- a/kernel/src/kernel/graphics.c +++ b/kernel/src/kernel/graphics.c @@ -1,9 +1,12 @@ +#include #include +#include #include #include static struct limine_framebuffer* framebuffer; static size_t frmw, frmh; +static size_t stride_pixels; uint32_t* fb_ptr; /*! @@ -15,6 +18,7 @@ void init_graphics (struct limine_framebuffer* buf) { framebuffer = buf; frmw = framebuffer->width; frmh = framebuffer->height; + stride_pixels = framebuffer->pitch / (framebuffer->bpp / 8); fb_ptr = framebuffer->address; } @@ -36,7 +40,7 @@ Convert screen position to index. @param x x-position @param y y-position */ -inline size_t postoi (int x, int y) { return x + y * frmw; } +inline size_t postoi (int x, int y) { return (size_t)x + ((size_t)y * stride_pixels); } /*! Place a pixel on the screen. @@ -45,7 +49,11 @@ Place a pixel on the screen. @param x x-position @param y y-position */ -static void putPixel (uint32_t color, int x, int y) { fb_ptr[postoi (x, y)] = color; } +static void putPixel (uint32_t color, int x, int y) { + if (x < 0 || y < 0) return; + if ((size_t)x >= frmw || (size_t)y >= frmh) return; + fb_ptr[postoi (x, y)] = color; +} /*! Place a character on the screen @@ -74,9 +82,8 @@ Draw a white border around the screen. @param padding pixels to leave around the edges */ void drawBorder (size_t padding) { - for (size_t i = 0; i < frmw * frmh; i++) - if (i % frmw == padding || i % frmw == frmw - padding) - fb_ptr[i] = 0xffffff; - else if (i / frmw == padding || i / frmw == frmh - padding) - fb_ptr[i] = 0xffffff; + for (size_t y = 0; y < frmh; y++) + for (size_t x = 0; x < frmw; x++) + if (x == padding || x + padding + 1 == frmw || y == padding || y + padding + 1 == frmh) + putPixel (0xffffff, (int)x, (int)y); } \ No newline at end of file diff --git a/kernel/src/kernel/handlers.c b/kernel/src/kernel/handlers.c index eacd5ca..bf6d42c 100644 --- a/kernel/src/kernel/handlers.c +++ b/kernel/src/kernel/handlers.c @@ -1,9 +1,11 @@ #include #include +#include +#include void handle_gpf (registers_t* registers) { - (void)registers; - kserial_printf ("\nOopsy! Looks like someone tried to execute a disallowed instruction!"); + kserial_printf ("Triggered GPF on PID #%lld\n", get_current_process ()->p_id); + log_registers_to_serial (registers); for (;;) ; } diff --git a/kernel/src/kernel/idt.c b/kernel/src/kernel/idt.c index 4134be5..d180673 100644 --- a/kernel/src/kernel/idt.c +++ b/kernel/src/kernel/idt.c @@ -32,33 +32,33 @@ static void idt_set_gate (uint8_t vector, void* isr, uint8_t gate_type, uint8_t descriptor->present = present & 0x01; } -static void log_registers_to_serial (registers_t* registers) { +void log_registers_to_serial (registers_t* registers) { kserial_printf ("\n--- Interrupt/Exception Caught ---\n"); kserial_printf ("interrupt_number: 0x%llx\n", registers->interrupt_number); kserial_printf ("error_code: 0x%llx\n", registers->error_code); - kserial_printf ("rip: 0x%llx\n", registers->rip); - kserial_printf ("cs: 0x%llx\n", registers->cs); - kserial_printf ("rflags: 0x%llx\n", registers->rflags); - kserial_printf ("rsp: 0x%llx\n", registers->rsp); - kserial_printf ("ss: 0x%llx\n\n", registers->ss); - - kserial_printf ("rax: 0x%llx\n", registers->rax); - kserial_printf ("rbx: 0x%llx\n", registers->rbx); - kserial_printf ("rcx: 0x%llx\n", registers->rcx); - kserial_printf ("rdx: 0x%llx\n", registers->rdx); - kserial_printf ("rsi: 0x%llx\n", registers->rsi); - kserial_printf ("rdi: 0x%llx\n", registers->rdi); - kserial_printf ("rbp: 0x%llx\n\n", registers->rbp); - - kserial_printf ("r8: 0x%llx\n", registers->r8); - kserial_printf ("r9: 0x%llx\n", registers->r9); - kserial_printf ("r10: 0x%llx\n", registers->r10); - kserial_printf ("r11: 0x%llx\n", registers->r11); - kserial_printf ("r12: 0x%llx\n", registers->r12); - kserial_printf ("r13: 0x%llx\n", registers->r13); - kserial_printf ("r14: 0x%llx\n", registers->r14); - kserial_printf ("r15: 0x%llx\n", registers->r15); + kserial_printf ("rip 0x%016llx ", registers->rip); + kserial_printf ("cs 0x%016llx ", registers->cs); + kserial_printf ("rflags 0x%016llx\n", registers->rflags); + kserial_printf ("rsp 0x%016llx ", registers->rsp); + kserial_printf ("ss 0x%016llx\n\n", registers->ss); + + kserial_printf ("rax 0x%016llx ", registers->rax); + kserial_printf ("rbx 0x%016llx ", registers->rbx); + kserial_printf ("rcx 0x%016llx ", registers->rcx); + kserial_printf ("rdx 0x%016llx\n", registers->rdx); + kserial_printf ("rsi 0x%016llx ", registers->rsi); + kserial_printf ("rdi 0x%016llx ", registers->rdi); + kserial_printf ("rbp 0x%016llx\n\n", registers->rbp); + + kserial_printf ("r8 0x%016llx ", registers->r8); + kserial_printf ("r9 0x%016llx ", registers->r9); + kserial_printf ("r10 0x%016llx ", registers->r10); + kserial_printf ("r11 0x%016llx\n", registers->r11); + kserial_printf ("r12 0x%016llx ", registers->r12); + kserial_printf ("r13 0x%016llx ", registers->r13); + kserial_printf ("r14 0x%016llx ", registers->r14); + kserial_printf ("r15 0x%016llx\n", registers->r15); kserial_printf ("----------------------------------\n\n"); } diff --git a/kernel/src/kernel/memory/memmgt.c b/kernel/src/kernel/memory/memmgt.c index ecb1b8c..ebe5ad0 100644 --- a/kernel/src/kernel/memory/memmgt.c +++ b/kernel/src/kernel/memory/memmgt.c @@ -41,8 +41,7 @@ static void page_fault_handler (registers_t* registers) { __asm__ volatile ("mov %%cr2, %0" : "=r"(cr2)); kserial_printf ("\nEncountered a page fault!\nFaulting address: 0x%llx\n", cr2); - kserial_printf ("RIP: 0x%llx, RSP: 0x%llx\n", registers->rip, registers->rsp); - kserial_printf ("Error code: 0x%llx\n", registers->error_code); + log_registers_to_serial (registers); for (;;) ; diff --git a/kernel/src/kernel/memory/pmm.c b/kernel/src/kernel/memory/pmm.c index 093c87c..81e1812 100644 --- a/kernel/src/kernel/memory/pmm.c +++ b/kernel/src/kernel/memory/pmm.c @@ -148,10 +148,10 @@ void init_physical_bitmap (struct limine_memmap_response* memmap_response) { for (uint64_t i = 0; i < memmap_response->entry_count; i++) { struct limine_memmap_entry* entry = memmap_response->entries[i]; if (entry->type == LIMINE_MEMMAP_USABLE) { - for (uint64_t p = entry->base / PAGE_SIZE; - p < (entry->base + entry->length) / PAGE_SIZE; p++) { + uint64_t start_page = (entry->base + PAGE_SIZE - 1) / PAGE_SIZE; + uint64_t end_page = (entry->base + entry->length) / PAGE_SIZE; + for (uint64_t p = start_page; p < end_page; p++) if (p < bitmap_fst_page || p >= bitmap_lst_page) bitmap_clear_bit (p); - } } } } diff --git a/kernel/src/kernel/memory/vaddr.c b/kernel/src/kernel/memory/vaddr.c index f3dae0b..9904856 100644 --- a/kernel/src/kernel/memory/vaddr.c +++ b/kernel/src/kernel/memory/vaddr.c @@ -79,3 +79,14 @@ bool is_vaddr_t_lt (vaddr_t* a, vaddr_t* b) { } return a->pml4_index < b->pml4_index; } + +/*! + * Check if vaddr a is strictly equal to vaddr b + * @param a first vaddr + * @param b second vaddr + * @return true if a == b, false otherwise + */ +bool is_vaddr_t_eq (vaddr_t a, vaddr_t b) { + return a.pml4_index == b.pml4_index && a.pdpt_index == b.pdpt_index && + a.pd_index == b.pd_index && a.pt_index == b.pt_index && a.offset == b.offset; +} diff --git a/kernel/src/kernel/memory/vmm.c b/kernel/src/kernel/memory/vmm.c index 2898340..0ae4c6f 100644 --- a/kernel/src/kernel/memory/vmm.c +++ b/kernel/src/kernel/memory/vmm.c @@ -1,3 +1,4 @@ +#include "kclib/stdio.h" #include #include #include @@ -187,52 +188,69 @@ static bool is_table_empty (void* table_vaddr) { * @param last last virtual page in range */ void free_all_vpages_in_range (vaddr_t first, vaddr_t last) { - pml4t_entry_t* pml4t_entry = &pml4_base_ptr[first.pml4_index]; - if (!pml4t_entry->present) return; - vaddr_t current = first; + while (is_vaddr_t_lt (¤t, &last)) { + pml4t_entry_t* pml4t_entry = &pml4_base_ptr[current.pml4_index]; + + if (!pml4t_entry->present) { + current.pml4_index++; + current.pdpt_index = current.pd_index = current.pt_index = 0; + continue; + } - while (true) { pdpt_entry_t* pdpt_base = (pdpt_entry_t*)get_vaddr_from_frame (pml4t_entry->pdpt_base_address); pdpt_entry_t* pdpt_entry = &pdpt_base[current.pdpt_index]; - if (pdpt_entry->present) { - pd_entry_t* pd_base = (pd_entry_t*)get_vaddr_from_frame (pdpt_entry->pd_base_address); - pd_entry_t* pd_entry = &pd_base[current.pd_index]; - - if (pd_entry->present) { - pt_entry_t* pt_base = (pt_entry_t*)get_vaddr_from_frame (pd_entry->pt_base_address); - pt_entry_t* pt_entry = &pt_base[current.pt_index]; - - if (pt_entry->present) { - pt_entry->present = 0; - pt_entry->frame_base_address = 0; - - void* current_vaddr_ptr = vaddr_t_to_ptr (¤t); - __asm__ volatile ("invlpg (%0)" : : "r"(current_vaddr_ptr) : "memory"); - - // --- GARBAGE COLLECTION --- - // We only need to check if a table is empty when we cross its boundary OR on - // our final page. - bool on_final_pg = !is_vaddr_t_lt (¤t, &last); - if (((current.pt_index == 511) || on_final_pg) && is_table_empty (pt_base)) { - free_ppage ((void*)(pd_entry->pt_base_address * PAGE_SIZE)); - pd_entry->present = 0; - pd_entry->pt_base_address = 0; - - if (((current.pd_index == 511) || on_final_pg) && - is_table_empty (pd_base)) { - free_ppage ((void*)(pdpt_entry->pd_base_address * PAGE_SIZE)); - pdpt_entry->present = 0; - pdpt_entry->pd_base_address = 0; - } - } + if (!pdpt_entry->present) { + current.pdpt_index++; + if (current.pdpt_index >= 512) current.pdpt_index -= 512, current.pml4_index++; + current.pd_index = current.pt_index = 0; + continue; + } + + pd_entry_t* pd_base = (pd_entry_t*)get_vaddr_from_frame (pdpt_entry->pd_base_address); + pd_entry_t* pd_entry = &pd_base[current.pd_index]; + + if (!pd_entry->present) { + current.pd_index++; + if (current.pd_index >= 512) current.pd_index -= 512, current.pdpt_index++; + if (current.pdpt_index >= 512) current.pdpt_index -= 512, current.pml4_index++; + current.pt_index = 0; + continue; + } + + pt_entry_t* pt_base = (pt_entry_t*)get_vaddr_from_frame (pd_entry->pt_base_address); + pt_entry_t* pt_entry = &pt_base[current.pt_index]; + + if (pt_entry->present) { + pt_entry->present = 0; + free_ppage ((void*)(pt_entry->frame_base_address * PAGE_SIZE)); + pt_entry->frame_base_address = 0; + + __asm__ volatile ("invlpg (%0)" : : "r"(vaddr_t_to_ptr (¤t)) : "memory"); + } + + bool on_final_pg = !is_vaddr_t_lt (¤t, &last); + if (((current.pt_index == 511) || on_final_pg) && is_table_empty (pt_base)) { + pd_entry->present = 0; + free_ppage ((void*)(pd_entry->pt_base_address * PAGE_SIZE)); + pd_entry->pt_base_address = 0; + + if (((current.pd_index == 511) || on_final_pg) && is_table_empty (pd_base)) { + pdpt_entry->present = 0; + free_ppage ((void*)(pdpt_entry->pd_base_address * PAGE_SIZE)); + pdpt_entry->pd_base_address = 0; + + if (((current.pdpt_index == 511) || on_final_pg) && is_table_empty (pdpt_base)) { + pml4t_entry->present = 0; + free_ppage ((void*)(pml4t_entry->pdpt_base_address * PAGE_SIZE)); + pml4t_entry->pdpt_base_address = 0; } } } - if (!is_vaddr_t_lt (¤t, &last)) break; + if (on_final_pg) break; current.pt_index++; if (current.pt_index >= 512) { @@ -241,6 +259,10 @@ void free_all_vpages_in_range (vaddr_t first, vaddr_t last) { if (current.pd_index >= 512) { current.pd_index = 0; current.pdpt_index++; + if (current.pdpt_index >= 512) { + current.pdpt_index = 0; + current.pml4_index++; + } } } } @@ -260,8 +282,6 @@ void free_vpages (void* ptr, size_t count) { void* phys_base = get_paddr (ptr); if (phys_base == nullptr) return; - free_ppages (phys_base, count); - uint64_t start_ptr_64t = (uint64_t)ptr; uint64_t last_ptr_64t = start_ptr_64t + ((count - 1) * PAGE_SIZE); @@ -281,11 +301,11 @@ void alloc_by_cr3 (uint64_t cr3, uintptr_t start, size_t num_pages, bool write) if (num_pages == 0) return; pml4t_entry_t* original_ptr = pml4_base_ptr; pml4_base_ptr = (pml4t_entry_t*)(cr3 + get_hhdm_offset ()); + uintptr_t last_page_base = ALIGN_PAGE_DOWN (start + (num_pages * PAGE_SIZE) - 1); paddr_t physmem = alloc_ppages (num_pages); alloc_all_vpages_in_range (get_vaddr_t_from_ptr ((void*)start), - get_vaddr_t_from_ptr ((void*)(start + (num_pages * PAGE_SIZE) - 1)), - physmem); + get_vaddr_t_from_ptr ((void*)last_page_base), physmem); (void)write; // TODO: set rw flag @@ -296,9 +316,10 @@ void dealloc_by_cr3 (uint64_t cr3, uintptr_t start, size_t num_pages) { if (num_pages == 0) return; pml4t_entry_t* original_ptr = pml4_base_ptr; pml4_base_ptr = (pml4t_entry_t*)(cr3 + get_hhdm_offset ()); + uintptr_t last_page_base = ALIGN_PAGE_DOWN (start + (num_pages * PAGE_SIZE) - 1); free_all_vpages_in_range (get_vaddr_t_from_ptr ((void*)start), - get_vaddr_t_from_ptr ((void*)(start + (num_pages * PAGE_SIZE) - 1))); + get_vaddr_t_from_ptr ((void*)last_page_base)); pml4_base_ptr = original_ptr; } diff --git a/kernel/src/kernel/sys/execve.c b/kernel/src/kernel/sys/execve.c index 431e07f..718de4a 100644 --- a/kernel/src/kernel/sys/execve.c +++ b/kernel/src/kernel/sys/execve.c @@ -27,7 +27,7 @@ static char** arg_deep_copy (char* const arg_og[]) { } static int do_execve (const char* path, char* const argv[], char* const envp[]) { - int err = 0; + int err = 0, argc = 0, envc = 0; const char* path_cp = kstrdup (path); char** argv_cp = arg_deep_copy (argv); @@ -48,7 +48,6 @@ static int do_execve (const char* path, char* const argv[], char* const envp[]) alloc_by_cr3 (get_current_process ()->p_cr3, user_stack_base - (stack_pages * PAGE_SIZE), stack_pages, true); - int argc = 0, envc = 0; while (argv_cp && argv_cp[argc]) argc++; while (envp_cp && envp_cp[envc]) @@ -120,7 +119,7 @@ static int do_execve (const char* path, char* const argv[], char* const envp[]) } kfree ((void*)path_cp); - return 0; + return err; } uint64_t sys_execve (uint64_t path, uint64_t argv, uint64_t envp) { diff --git a/lib/cos/src/crt0.S b/lib/cos/src/crt0.S index 44e0a61..8244df1 100644 --- a/lib/cos/src/crt0.S +++ b/lib/cos/src/crt0.S @@ -4,20 +4,59 @@ .extern main .extern exit +.extern __preinit_array_start +.extern __preinit_array_end +.extern __init_array_start +.extern __init_array_end +.extern environ _start: xor %ebp, %ebp - - pop %rdi // argc - mov %rsp, %rsi // argv - lea 8(%rsp, %rdi, 8), %rdx // envp + cld + + pop %r12 // argc + mov %rsp, %r13 // argv + lea 8(%rsp, %r12, 8), %r14 // envp and $-16, %rsp // align to 16 byte + mov %r14, environ(%rip) // initialise environ + + lea __preinit_array_start(%rip), %rbx + lea __preinit_array_end(%rip), %r15 + +.Lpreinit_array_loop: + cmp %r15, %rbx + je .Linit_array + mov (%rbx), %rax + add $8, %rbx + test %rax, %rax + je .Lpreinit_array_loop + call *%rax + jmp .Lpreinit_array_loop + +.Linit_array: + lea __init_array_start(%rip), %rbx + lea __init_array_end(%rip), %r15 + +.Linit_array_loop: + cmp %r15, %rbx + je .Lcall_main + mov (%rbx), %rax + add $8, %rbx + test %rax, %rax + je .Linit_array_loop + call *%rax + jmp .Linit_array_loop + +.Lcall_main: + mov %r12, %rdi + mov %r13, %rsi + mov %r14, %rdx + call main mov %eax, %edi call exit .Lhang: - hlt - jmp .Lhang \ No newline at end of file + jmp .Lhang diff --git a/user/Makefile b/user/Makefile index 14b61d5..edd2c7b 100644 --- a/user/Makefile +++ b/user/Makefile @@ -1,17 +1,13 @@ -.PHONY: all hello pishell +.PHONY: all hello -all: hello pishell +all: hello -bin: hello pishell +bin: hello hello: @echo "Building hello..." $(MAKE) -C hello -pishell: - @echo "Building pishell..." - $(MAKE) -C pishell - format: @echo "Formatting hello..." $(MAKE) -C hello format diff --git a/user/hello/hello.c b/user/hello/hello.c index 64bd05e..464ad0c 100644 --- a/user/hello/hello.c +++ b/user/hello/hello.c @@ -5,12 +5,8 @@ int main (int argc, char* argv[]) { printf ("Hello from USERLAND using newlib!!!\n"); - char* new_argv[] = {"/bin/pishell", NULL}; - char* new_envp[] = {NULL}; + for (;;) + ; - printf ("Attempting to execve /bin/pishell...\n"); - execve ("/bin/pishell", new_argv, new_envp); - - printf ("If you see this, execve failed!\n"); return 1; } diff --git a/user/pishell b/user/pishell deleted file mode 160000 index 4fa647a..0000000 --- a/user/pishell +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4fa647ae77a5422b0cf0295350646ccdde45a6f9