From 7b0dccbab69e806a63c4504c3ddb82e45241985b Mon Sep 17 00:00:00 2001 From: Minep Date: Thu, 3 Mar 2022 17:36:53 +0000 Subject: [PATCH] Complete (almost!) printf fmt support Enriched string.h Enhance the readability of vmm.c Better assert & panic implementation (use syscall to panic) Some housekeeping routines (remove warnings, restructure project folders) --- lunaix-os/includes/arch/x86/interrupts.h | 113 ++++++++-- lunaix-os/includes/hal/cpu.h | 95 ++++++--- lunaix-os/includes/libc/string.h | 6 + lunaix-os/includes/lunaix/assert.h | 19 -- lunaix-os/includes/lunaix/mm/page.h | 9 + lunaix-os/includes/lunaix/mm/vmm.h | 2 +- lunaix-os/includes/lunaix/spike.h | 14 +- lunaix-os/kernel/asm/x86/idt.c | 6 +- lunaix-os/kernel/asm/x86/interrupt.S | 31 ++- lunaix-os/kernel/asm/x86/interrupts.c | 16 +- lunaix-os/kernel/asm/x86/prologue.S | 1 - lunaix-os/kernel/assert.c | 12 -- lunaix-os/kernel/k_init.c | 15 +- lunaix-os/kernel/k_main.c | 4 +- lunaix-os/kernel/mm/dmm.c | 18 +- lunaix-os/kernel/mm/page.c | 1 + lunaix-os/kernel/mm/vmm.c | 109 +++++----- lunaix-os/kernel/spike.c | 19 ++ lunaix-os/libs/libc/stdio/sprintf.c | 255 ++++++++++++++++------- lunaix-os/libs/libc/string/strchr.c | 14 ++ lunaix-os/libs/libc/string/strlen.c | 8 + lunaix-os/{ => link}/linker.ld | 0 lunaix-os/makefile | 14 +- 23 files changed, 537 insertions(+), 244 deletions(-) delete mode 100644 lunaix-os/includes/lunaix/assert.h delete mode 100644 lunaix-os/kernel/assert.c create mode 100644 lunaix-os/kernel/mm/page.c create mode 100644 lunaix-os/kernel/spike.c create mode 100644 lunaix-os/libs/libc/string/strchr.c rename lunaix-os/{ => link}/linker.ld (100%) diff --git a/lunaix-os/includes/arch/x86/interrupts.h b/lunaix-os/includes/arch/x86/interrupts.h index 3fb86d6..3ac415a 100644 --- a/lunaix-os/includes/arch/x86/interrupts.h +++ b/lunaix-os/includes/arch/x86/interrupts.h @@ -1,30 +1,36 @@ #ifndef __LUNAIX_INTERRUPTS_H #define __LUNAIX_INTERRUPTS_H -#define FAULT_DIVISION_ERROR 0x0 -#define FAULT_TRAP_DEBUG_EXCEPTION 0x1 -#define INT_NMI 0x2 -#define TRAP_BREAKPOINT 0x3 -#define TRAP_OVERFLOW 0x4 -#define FAULT_BOUND_EXCEED 0x5 -#define FAULT_INVALID_OPCODE 0x6 -#define FAULT_NO_MATH_PROCESSOR 0x7 -#define ABORT_DOUBLE_FAULT 0x8 -#define FAULT_RESERVED_0 0x9 -#define FAULT_INVALID_TSS 0xa -#define FAULT_SEG_NOT_PRESENT 0xb -#define FAULT_STACK_SEG_FAULT 0xc -#define FAULT_GENERAL_PROTECTION 0xd -#define FAULT_PAGE_FAULT 0xe -#define FAULT_RESERVED_1 0xf -#define FAULT_X87_FAULT 0x10 -#define FAULT_ALIGNMENT_CHECK 0x11 -#define ABORT_MACHINE_CHECK 0x12 -#define FAULT_SIMD_FP_EXCEPTION 0x13 -#define FAULT_VIRTUALIZATION_EXCEPTION 0x14 -#define FAULT_CONTROL_PROTECTION 0x15 +#define FAULT_DIVISION_ERROR 0 +#define FAULT_TRAP_DEBUG_EXCEPTION 1 +#define INT_NMI 2 +#define TRAP_BREAKPOINT 3 +#define TRAP_OVERFLOW 4 +#define FAULT_BOUND_EXCEED 5 +#define FAULT_INVALID_OPCODE 6 +#define FAULT_NO_MATH_PROCESSOR 7 +#define ABORT_DOUBLE_FAULT 8 +#define FAULT_RESERVED_0 9 +#define FAULT_INVALID_TSS 10 +#define FAULT_SEG_NOT_PRESENT 11 +#define FAULT_STACK_SEG_FAULT 12 +#define FAULT_GENERAL_PROTECTION 13 +#define FAULT_PAGE_FAULT 14 +#define FAULT_RESERVED_1 15 +#define FAULT_X87_FAULT 16 +#define FAULT_ALIGNMENT_CHECK 17 +#define ABORT_MACHINE_CHECK 18 +#define FAULT_SIMD_FP_EXCEPTION 19 +#define FAULT_VIRTUALIZATION_EXCEPTION 20 +#define FAULT_CONTROL_PROTECTION 21 + +#define LUNAIX_SYS_PANIC 32 + +#ifndef __ASM__ +#include typedef struct { + gp_regs registers; unsigned int vector; unsigned int err_code; unsigned int eip; @@ -37,13 +43,76 @@ typedef struct { void _asm_isr0(); +void +_asm_isr1(); + +void +_asm_isr2(); + +void +_asm_isr3(); + +void +_asm_isr4(); + +void +_asm_isr5(); + +void +_asm_isr6(); + +void +_asm_isr7(); + +void +_asm_isr8(); + +void +_asm_isr9(); + +void +_asm_isr10(); + +void +_asm_isr11(); + +void +_asm_isr12(); + void _asm_isr13(); void _asm_isr14(); +void +_asm_isr15(); + +void +_asm_isr16(); + +void +_asm_isr17(); + +void +_asm_isr18(); + +void +_asm_isr19(); + +void +_asm_isr20(); + +void +_asm_isr21(); + + +void +_asm_isr32(); + void interrupt_handler(isr_param* param); +#endif + #endif /* __LUNAIX_INTERRUPTS_H */ diff --git a/lunaix-os/includes/hal/cpu.h b/lunaix-os/includes/hal/cpu.h index 6381143..1a3173b 100644 --- a/lunaix-os/includes/hal/cpu.h +++ b/lunaix-os/includes/hal/cpu.h @@ -6,7 +6,8 @@ typedef unsigned int reg32; typedef unsigned short reg16; -typedef struct { +typedef struct +{ reg32 eax; reg32 ebx; reg32 ecx; @@ -15,58 +16,86 @@ typedef struct { reg32 ebp; reg32 esi; reg32 esp; - reg32 cs; - reg32 eip; -} __attribute__((packed)) registers; +} __attribute__((packed)) gp_regs; + +typedef struct +{ + reg16 ss; + reg16 es; + reg16 ds; + reg16 fs; + reg16 gs; + reg16 cs; +} __attribute__((packed)) sg_reg; + +void +cpu_get_brand(char* brand_out); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wreturn-type" -static inline reg32 cpu_rcr0() { - asm volatile ("mov %cr0, %eax"); +static inline reg32 +cpu_rcr0() +{ + asm("mov %cr0, %eax"); } -static inline reg32 cpu_rcr2() { - asm volatile ("mov %cr2, %eax"); +static inline reg32 +cpu_rcr2() +{ + asm("mov %cr2, %eax"); } -static inline reg32 cpu_rcr3() { - asm volatile ("mov %cr3, %eax"); +static inline reg32 +cpu_rcr3() +{ + asm("mov %cr3, %eax"); } #pragma GCC diagnostic pop -static inline void cpu_lcr0(reg32 v) { - asm volatile ( - "mov %0, %%cr0" - :: "r"(v) - ); +static inline void +cpu_lcr0(reg32 v) +{ + asm("mov %0, %%cr0" ::"r"(v)); +} + +static inline void +cpu_lcr2(reg32 v) +{ + asm("mov %0, %%cr2" ::"r"(v)); +} + +static inline void +cpu_lcr3(reg32 v) +{ + asm("mov %0, %%cr3" ::"r"(v)); } -static inline void cpu_lcr2(reg32 v) { - asm volatile ( - "mov %0, %%cr2" - :: "r"(v) - ); +static inline void +cpu_invplg(void* va) +{ + asm("invlpg (%0)" ::"r"((uintptr_t)va) : "memory"); } -static inline void cpu_lcr3(reg32 v) { - asm volatile ( - "mov %0, %%cr3" - :: "r"(v) - ); +static inline void +cpu_enable_interrupt() +{ + asm("sti"); } -static inline void cpu_invplg(void* va) { - __asm__("invlpg (%0)" ::"r"((uintptr_t)va) : "memory"); +static inline void +cpu_disable_interrupt() +{ + asm("cli"); } -static inline void cpu_invtlb() { +static inline void +cpu_invtlb() +{ reg32 interm; - __asm__( - "movl %%cr3, %0\n" + asm("movl %%cr3, %0\n" "movl %0, %%cr3" - :"=r"(interm) - :"r"(interm) - ); + : "=r"(interm) + : "r"(interm)); } #endif \ No newline at end of file diff --git a/lunaix-os/includes/libc/string.h b/lunaix-os/includes/libc/string.h index 671fdec..7347de2 100644 --- a/lunaix-os/includes/libc/string.h +++ b/lunaix-os/includes/libc/string.h @@ -21,4 +21,10 @@ strlen(const char* str); char* strcpy(char* dest, const char* src); +size_t +strnlen(const char* str, size_t max_len); + +const char* +strchr(const char* str, int character); + #endif /* __LUNAIX_STRING_H */ diff --git a/lunaix-os/includes/lunaix/assert.h b/lunaix-os/includes/lunaix/assert.h deleted file mode 100644 index 0697b33..0000000 --- a/lunaix-os/includes/lunaix/assert.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __LUNAIX_ASSERT_H -#define __LUNAIX_ASSERT_H - -#include -#include - -#ifdef __LUNAIXOS_DEBUG__ -#define assert(cond) \ - if (!(cond)) { \ - __assert_fail(#cond, __FILE__, __LINE__); \ - } -#else -#define assert(cond) //nothing -#endif - - -void __assert_fail(const char* expr, const char* file, unsigned int line) __attribute__((noinline, noreturn)); - -#endif /* __LUNAIX_ASSERT_H */ diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index 4ea31bc..935909c 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -11,6 +11,8 @@ #define PG_LAST_TABLE PG_MAX_ENTRIES - 1 #define PG_FIRST_TABLE 0 +#define PTE_NULL 0 + #define P2V(paddr) ((uintptr_t)(paddr) + HIGHER_HLF_BASE) #define V2P(vaddr) ((uintptr_t)(vaddr) - HIGHER_HLF_BASE) @@ -79,5 +81,12 @@ typedef struct { uint16_t flags; } v_mapping; +typedef uint32_t x86_pte_t; +typedef struct +{ + x86_pte_t entry[PG_MAX_ENTRIES]; +} __attribute__((packed)) x86_page_table; + + #endif /* __LUNAIX_PAGE_H */ diff --git a/lunaix-os/includes/lunaix/mm/vmm.h b/lunaix-os/includes/lunaix/mm/vmm.h index a0c455f..752f23c 100644 --- a/lunaix-os/includes/lunaix/mm/vmm.h +++ b/lunaix-os/includes/lunaix/mm/vmm.h @@ -17,7 +17,7 @@ vmm_init(); * * @return ptd_entry* 页目录的物理地址,随时可以加载进CR3 */ -ptd_t* +x86_page_table* vmm_init_pd(); /** diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index fa4e797..7e50693 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -15,8 +15,20 @@ // 获取v最近的最小k倍数 #define ROUNDDOWN(v, k) ((v) & ~((k) - 1)) -static void inline spin() { +inline static void spin() { while(1); } +#ifdef __LUNAIXOS_DEBUG__ +#define assert(cond) \ + if (!(cond)) { \ + __assert_fail(#cond, __FILE__, __LINE__); \ + } +void __assert_fail(const char* expr, const char* file, unsigned int line) __attribute__((noinline, noreturn)); +#else +#define assert(cond) //nothing +#endif + + + #endif /* __LUNAIX_SPIKE_H */ diff --git a/lunaix-os/kernel/asm/x86/idt.c b/lunaix-os/kernel/asm/x86/idt.c index 296fa15..aa07140 100644 --- a/lunaix-os/kernel/asm/x86/idt.c +++ b/lunaix-os/kernel/asm/x86/idt.c @@ -2,7 +2,7 @@ #include #include -#define IDT_ENTRY 32 +#define IDT_ENTRY 256 uint64_t _idt[IDT_ENTRY]; uint16_t _idt_limit = sizeof(_idt) - 1; @@ -17,7 +17,11 @@ void _set_idt_entry(uint32_t vector, uint16_t seg_selector, void (*isr)(), uint8 void _init_idt() { + // CPU defined interrupts _set_idt_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0); _set_idt_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0); _set_idt_entry(FAULT_PAGE_FAULT, 0x08, _asm_isr14, 0); + + // system defined interrupts + _set_idt_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0); } \ No newline at end of file diff --git a/lunaix-os/kernel/asm/x86/interrupt.S b/lunaix-os/kernel/asm/x86/interrupt.S index 10fa393..9d39273 100644 --- a/lunaix-os/kernel/asm/x86/interrupt.S +++ b/lunaix-os/kernel/asm/x86/interrupt.S @@ -1,3 +1,6 @@ +#define __ASM__ +#include + .macro isr_template vector, no_error_code=1 .global _asm_isr\vector .type _asm_isr\vector, @function @@ -10,11 +13,21 @@ .endm .section .text - isr_template 0 - isr_template 13, no_error_code=0 - isr_template 14, no_error_code=0 + isr_template FAULT_DIVISION_ERROR + isr_template FAULT_GENERAL_PROTECTION, no_error_code=0 + isr_template FAULT_PAGE_FAULT, no_error_code=0 + + isr_template LUNAIX_SYS_PANIC interrupt_wrapper: + pushl %esp + pushl %esi + pushl %ebp + pushl %edi + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax movl %esp, %eax andl $0xfffffff0, %esp @@ -22,8 +35,18 @@ movl %eax, (%esp) call interrupt_handler - pop %eax + popl %eax movl %eax, %esp + + popl %eax + popl %ebx + popl %ecx + popl %edx + popl %edi + popl %ebp + popl %esi + popl %esp + addl $8, %esp iret \ No newline at end of file diff --git a/lunaix-os/kernel/asm/x86/interrupts.c b/lunaix-os/kernel/asm/x86/interrupts.c index 925c13d..8dfb23b 100644 --- a/lunaix-os/kernel/asm/x86/interrupts.c +++ b/lunaix-os/kernel/asm/x86/interrupts.c @@ -1,14 +1,20 @@ #include -#include +#include #include -void panic (const char* msg, isr_param* param) { +void panic_msg(const char* msg) { tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED); tty_clear_line(10); tty_clear_line(11); tty_clear_line(12); tty_set_cpos(0, 11); - printf(" INT %u: (%x) [0x%x: 0x%x] %s", param->vector, param->err_code, param->cs, param->eip, msg); + printf(" %s", msg); +} + +void panic (const char* msg, isr_param* param) { + char buf[1024]; + sprintf(buf, "INT %u: (%x) [%p: %p] %s", param->vector, param->err_code, param->cs, param->eip, msg); + panic_msg(buf); while(1); } @@ -25,6 +31,10 @@ interrupt_handler(isr_param* param) { case FAULT_PAGE_FAULT: panic("Page Fault", param); break; // never reach + case LUNAIX_SYS_PANIC: + panic_msg((char*)(param->registers.edi)); + while(1); + break; // never reach default: panic("Unknown Interrupt", param); break; // never reach diff --git a/lunaix-os/kernel/asm/x86/prologue.S b/lunaix-os/kernel/asm/x86/prologue.S index fe1b645..cbfd414 100644 --- a/lunaix-os/kernel/asm/x86/prologue.S +++ b/lunaix-os/kernel/asm/x86/prologue.S @@ -52,7 +52,6 @@ addl $6, %esp - movl $mb_info, (%esp) call _kernel_init /* diff --git a/lunaix-os/kernel/assert.c b/lunaix-os/kernel/assert.c deleted file mode 100644 index 10fb78b..0000000 --- a/lunaix-os/kernel/assert.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -void __assert_fail(const char* expr, const char* file, unsigned int line) { - tty_set_theme(VGA_COLOR_BLACK, VGA_COLOR_LIGHT_RED); - tty_clear_line(10); - tty_clear_line(11); - tty_clear_line(12); - tty_set_cpos(0, 11); - printf(" Assert %s failed (%s:%u)", expr, file, line); - __spin: - goto __spin; -} \ No newline at end of file diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 07091ca..0b73f92 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -4,8 +4,13 @@ #include #include #include +#include +#include #include +#include + +#include #include #include @@ -15,6 +20,12 @@ extern uint8_t __kernel_start; extern uint8_t __kernel_end; extern uint8_t __init_hhk_end; +void +setup_memory(multiboot_memory_map_t* map, size_t map_size); + +void +setup_kernel_runtime(); + void _kernel_pre_init(multiboot_info_t* mb_info) { _init_idt(); @@ -35,7 +46,7 @@ _kernel_init(multiboot_info_t* mb_info) { mb_info->mem_upper); unsigned int map_size = mb_info->mmap_length / sizeof(multiboot_memory_map_t); - setup_memory(mb_info->mmap_addr, map_size); + setup_memory((multiboot_memory_map_t*)mb_info->mmap_addr, map_size); setup_kernel_runtime(); } @@ -49,6 +60,8 @@ _kernel_post_init() { for (size_t i = 0; i < hhk_init_pg_count; i++) { vmm_unmap_page((void*)(i << PG_SIZE_BITS)); } + + assert(dmm_init()); } // 按照 Memory map 标识可用的物理页 diff --git a/lunaix-os/kernel/k_main.c b/lunaix-os/kernel/k_main.c index 3f56166..121273b 100644 --- a/lunaix-os/kernel/k_main.c +++ b/lunaix-os/kernel/k_main.c @@ -3,6 +3,7 @@ #include #include #include +#include extern uint8_t __kernel_start; @@ -20,8 +21,6 @@ _kernel_main() void* k_start = vmm_v2p(&__kernel_start); printf("The kernel's base address mapping: %p->%p\n", &__kernel_start, k_start); - dmm_init(); - // test malloc & free uint32_t** arr = (uint32_t**) lx_malloc(10 * sizeof(uint32_t*)); @@ -40,5 +39,4 @@ _kernel_main() lx_free(arr); lx_free(big_); - // assert(0); } \ No newline at end of file diff --git a/lunaix-os/kernel/mm/dmm.c b/lunaix-os/kernel/mm/dmm.c index e15e432..e5f2ec5 100644 --- a/lunaix-os/kernel/mm/dmm.c +++ b/lunaix-os/kernel/mm/dmm.c @@ -10,11 +10,12 @@ * */ +// TODO: Make the dmm portable + #include #include #include -#include #include #include @@ -67,7 +68,7 @@ dmm_init() SW(heap_start + WSIZE, PACK(0, M_ALLOCATED)); current_heap_top += WSIZE; - return lx_grow_heap(HEAP_INIT_SIZE); + return lx_grow_heap(HEAP_INIT_SIZE) != NULL; } int @@ -80,14 +81,14 @@ void* lxbrk(size_t size) { if (size == 0) { - return NULL; + return current_heap_top; } // plus WSIZE is the overhead for epilogue marker size += WSIZE; void* next = current_heap_top + ROUNDUP((uintptr_t)size, WSIZE); - if (next >= K_STACK_START) { + if ((uintptr_t)next >= K_STACK_START) { return NULL; } @@ -98,20 +99,20 @@ lxbrk(size_t size) if (heap_top_pg != PG_ALIGN(next)) { // if next do require new pages to be allocated - if (!vmm_alloc_pages(heap_top_pg + PG_SIZE, ROUNDUP(size, PG_SIZE), PG_PRESENT | PG_WRITE)) { + if (!vmm_alloc_pages((void*)(heap_top_pg + PG_SIZE), ROUNDUP(size, PG_SIZE), PG_PREM_RW)) { return NULL; } } - uintptr_t old = current_heap_top; + void* old = current_heap_top; current_heap_top = next - WSIZE; return old; } void* lx_grow_heap(size_t sz) { - uintptr_t start; + void* start; sz = ROUNDUP(sz, BOUNDARY); if (!(start = lxbrk(sz))) { @@ -136,7 +137,7 @@ lx_malloc(size_t size) // round to largest 4B aligned value // and space for header size = ROUNDUP(size, BOUNDARY) + WSIZE; - while (ptr < current_heap_top) { + while (ptr < (uint8_t*)current_heap_top) { uint32_t header = *((uint32_t*)ptr); size_t chunk_size = CHUNK_S(header); if (chunk_size >= size && !CHUNK_A(header)) { @@ -203,7 +204,6 @@ coalesce(uint8_t* chunk_ptr) uint32_t hdr = LW(chunk_ptr); uint32_t pf = CHUNK_PF(hdr); uint32_t sz = CHUNK_S(hdr); - uint32_t ftr = LW(chunk_ptr + sz - WSIZE); uint32_t n_hdr = LW(chunk_ptr + sz); diff --git a/lunaix-os/kernel/mm/page.c b/lunaix-os/kernel/mm/page.c new file mode 100644 index 0000000..400197f --- /dev/null +++ b/lunaix-os/kernel/mm/page.c @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index 63ff9ac..54da656 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -1,9 +1,9 @@ +#include #include #include #include #include -#include -#include +#include #include @@ -13,45 +13,50 @@ vmm_init() // TODO: something here? } -ptd_t* +x86_page_table* vmm_init_pd() { - ptd_t* dir = pmm_alloc_page(); + x86_page_table* dir = (x86_page_table*)pmm_alloc_page(); for (size_t i = 0; i < PG_MAX_ENTRIES; i++) { - dir[i] = 0; + dir->entry[i] = PTE_NULL; } // 递归映射,方便我们在软件层面进行查表地址转换 - dir[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, dir); + dir->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, dir); return dir; } int -__vmm_map_internal(uint32_t l1_inx, uint32_t l2_inx, uintptr_t pa, pt_attr attr, int forced) { - ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR; - pt_t* l2pt = (pt_t*)L2_VADDR(l1_inx); +__vmm_map_internal(uint32_t l1_inx, + uint32_t l2_inx, + uintptr_t pa, + pt_attr attr, + int forced) +{ + x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR; + x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_inx); // See if attr make sense assert(attr <= 128); - if(!l1pt[l1_inx]) { - uint8_t* new_l1pt_pa = pmm_alloc_page(); + if (!l1pt->entry[l1_inx]) { + x86_page_table* new_l1pt_pa = pmm_alloc_page(); // 物理内存已满! if (!new_l1pt_pa) { return 0; } - l1pt[l1_inx] = NEW_L1_ENTRY(attr, new_l1pt_pa); + l1pt->entry[l1_inx] = NEW_L1_ENTRY(attr, new_l1pt_pa); memset((void*)L2_VADDR(l1_inx), 0, PG_SIZE); } - if (!forced && l2pt[l2_inx]) { + if (!forced && l2pt->entry[l2_inx]) { return 0; } - l2pt[l2_inx] = NEW_L2_ENTRY(attr, pa); + l2pt->entry[l2_inx] = NEW_L2_ENTRY(attr, pa); return 1; } @@ -64,26 +69,25 @@ vmm_map_page(void* va, void* pa, pt_attr tattr) return NULL; } - assert(((uintptr_t)va & 0xFFFU) == 0) - assert(((uintptr_t)pa & 0xFFFU) == 0) + assert(((uintptr_t)va & 0xFFFU) == 0) assert(((uintptr_t)pa & 0xFFFU) == 0); uint32_t l1_index = L1_INDEX(va); uint32_t l2_index = L2_INDEX(va); - ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR; + x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR; // 在页表与页目录中找到一个可用的空位进行映射(位于va或其附近) - ptd_t l1pte = l1pt[l1_index]; - pt_t* l2pt = (pt_t*)L2_VADDR(l1_index); + x86_pte_t l1pte = l1pt->entry[l1_index]; + x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_index); while (l1pte && l1_index < PG_MAX_ENTRIES) { if (l2_index == PG_MAX_ENTRIES) { l1_index++; l2_index = 0; - l1pte = l1pt[l1_index]; - l2pt = (pt_t*)L2_VADDR(l1_index); + l1pte = l1pt->entry[l1_index]; + l2pt = (x86_page_table*)L2_VADDR(l1_index); } // 页表有空位,只需要开辟一个新的 PTE (Level 2) - if (l2pt && !l2pt[l2_index]) { - l2pt[l2_index] = NEW_L2_ENTRY(tattr, pa); + if (l2pt && !l2pt->entry[l2_index]) { + l2pt->entry[l2_index] = NEW_L2_ENTRY(tattr, pa); return (void*)V_ADDR(l1_index, l2_index, PG_OFFSET(va)); } l2_index++; @@ -94,7 +98,7 @@ vmm_map_page(void* va, void* pa, pt_attr tattr) return NULL; } - if (!__vmm_map_internal(l1_index, l2_index, pa, tattr, false)) { + if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, false)) { return NULL; } @@ -102,18 +106,18 @@ vmm_map_page(void* va, void* pa, pt_attr tattr) } void* -vmm_fmap_page(void* va, void* pa, pt_attr tattr) { +vmm_fmap_page(void* va, void* pa, pt_attr tattr) +{ if (!pa || !va) { return NULL; } - assert(((uintptr_t)va & 0xFFFU) == 0) - assert(((uintptr_t)pa & 0xFFFU) == 0) + assert(((uintptr_t)va & 0xFFFU) == 0) assert(((uintptr_t)pa & 0xFFFU) == 0); uint32_t l1_index = L1_INDEX(va); uint32_t l2_index = L2_INDEX(va); - if (!__vmm_map_internal(l1_index, l2_index, pa, tattr, true)) { + if (!__vmm_map_internal(l1_index, l2_index, (uintptr_t)pa, tattr, true)) { return NULL; } @@ -134,70 +138,68 @@ vmm_alloc_page(void* vpn, pt_attr tattr) } int -vmm_alloc_pages(void* va, size_t sz, pt_attr tattr) { - assert((uintptr_t)va % PG_SIZE == 0) - assert(sz % PG_SIZE == 0) - +vmm_alloc_pages(void* va, size_t sz, pt_attr tattr) +{ + assert((uintptr_t)va % PG_SIZE == 0) assert(sz % PG_SIZE == 0); + void* va_ = va; - for (size_t i = 0; i < (sz >> PG_SIZE_BITS); i++, va_ += PG_SIZE) - { + for (size_t i = 0; i < (sz >> PG_SIZE_BITS); i++, va_ += PG_SIZE) { void* pp = pmm_alloc_page(); uint32_t l1_index = L1_INDEX(va_); uint32_t l2_index = L2_INDEX(va_); - if (!pp || !__vmm_map_internal(l1_index, l2_index, pp, tattr, false)) { + if (!pp || !__vmm_map_internal( + l1_index, l2_index, (uintptr_t)pp, tattr, false)) { // if one failed, release previous allocated pages. va_ = va; - for (size_t j = 0; j < i; j++, va_ += PG_SIZE) - { + for (size_t j = 0; j < i; j++, va_ += PG_SIZE) { vmm_unmap_page(va_); } - + return false; } } - + return true; } void vmm_unmap_page(void* va) { - assert(((uintptr_t)va & 0xFFFU) == 0) + assert(((uintptr_t)va & 0xFFFU) == 0); uint32_t l1_index = L1_INDEX(va); uint32_t l2_index = L2_INDEX(va); - ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR; + x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR; - ptd_t l1pte = l1pt[l1_index]; + x86_pte_t l1pte = l1pt->entry[l1_index]; if (l1pte) { - pt_t* l2pt = (pt_t*)L2_VADDR(l1_index); - uint32_t l2pte = l2pt[l2_index]; + x86_page_table* l2pt = (x86_page_table*)L2_VADDR(l1_index); + x86_pte_t l2pte = l2pt->entry[l2_index]; if (IS_CACHED(l2pte)) { pmm_free_page((void*)l2pte); } cpu_invplg(va); - l2pt[l2_index] = 0; + l2pt->entry[l2_index] = PTE_NULL; } } v_mapping vmm_lookup(void* va) { - assert(((uintptr_t)va & 0xFFFU) == 0) + assert(((uintptr_t)va & 0xFFFU) == 0); uint32_t l1_index = L1_INDEX(va); uint32_t l2_index = L2_INDEX(va); - uint32_t po = PG_OFFSET(va); - ptd_t* l1pt = (ptd_t*)L1_BASE_VADDR; - ptd_t l1pte = l1pt[l1_index]; + x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR; + x86_pte_t l1pte = l1pt->entry[l1_index]; v_mapping mapping = { .flags = 0, .pa = 0, .pn = 0 }; if (l1pte) { - pt_t l2pte = ((pt_t*)L2_VADDR(l1_index))[l2_index]; + x86_pte_t l2pte = + ((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index]; if (l2pte) { - uintptr_t ppn = l2pte >> PG_SIZE_BITS; mapping.flags = PG_ENTRY_FLAGS(l2pte); mapping.pa = PG_ENTRY_ADDR(l2pte); mapping.pn = mapping.pa >> PG_SIZE_BITS; @@ -208,6 +210,7 @@ vmm_lookup(void* va) } void* -vmm_v2p(void* va) { - return vmm_lookup(va).pa; +vmm_v2p(void* va) +{ + return (void*)vmm_lookup(va).pa; } \ No newline at end of file diff --git a/lunaix-os/kernel/spike.c b/lunaix-os/kernel/spike.c new file mode 100644 index 0000000..91f597d --- /dev/null +++ b/lunaix-os/kernel/spike.c @@ -0,0 +1,19 @@ +#include +#include +#include + +static char buffer[1024]; + +void __assert_fail(const char* expr, const char* file, unsigned int line) { + sprintf(buffer, "Assert %s failed (%s:%u)", expr, file, line); + + // Here we load the buffer's address into %edi ("D" constraint) + // This is a convention we made that the LUNAIX_SYS_PANIC syscall will + // print the panic message passed via %edi. (see kernel/asm/x86/interrupts.c) + asm( + "int %0" + ::"i"(LUNAIX_SYS_PANIC), "D"(buffer) + ); + + spin(); // never reach +} \ No newline at end of file diff --git a/lunaix-os/libs/libc/stdio/sprintf.c b/lunaix-os/libs/libc/stdio/sprintf.c index 51466cd..6177267 100644 --- a/lunaix-os/libs/libc/stdio/sprintf.c +++ b/lunaix-os/libs/libc/stdio/sprintf.c @@ -4,86 +4,193 @@ #include #include +#define NUMBUFSIZ 24 + +static const char flag_chars[] = "#0- +"; + +#define FLAG_ALT (1<<0) +#define FLAG_ZERO (1<<1) +#define FLAG_LEFTJUSTIFY (1<<2) +#define FLAG_SPACEPOSITIVE (1<<3) +#define FLAG_PLUSPOSITIVE (1<<4) +#define FLAG_NUMERIC (1<<5) +#define FLAG_SIGNED (1<<6) +#define FLAG_NEGATIVE (1<<7) +#define FLAG_ALT2 (1<<8) +#define FLAG_CAPS (1<<9) + + +// FIXME: use something like IO_FILE to abstract this into a more flexible, stream based, vprintf void -__sprintf_internal(char* buffer, char* fmt, va_list args) +__sprintf_internal(char* buffer, char* fmt, va_list vargs) { - char c; - int num; - unsigned int ptr = 0; - unsigned int adv = 0; - while ((c = *fmt)) { - if (c != '%') { - buffer[ptr] = c; - adv = 1; - } else { - adv = 0; - fmt++; - switch (c = *fmt) { - case 'c': { - buffer[ptr] = (char)va_arg(args, int); - adv = 1; - break; - } - case 's': { - char* str = va_arg(args, char*); - strcpy(buffer + ptr, str); - adv = strlen(str); - break; - } - case 'i': - // fall through - case 'd': { - num = va_arg(args, int); - __itoa_internal(num, buffer + ptr, 10, &adv); - break; - } - case 'u': { - unsigned int unum = va_arg(args, unsigned int); - __uitoa_internal(unum, buffer + ptr, 10, &adv); - break; - } - case 'o': { - num = va_arg(args, int); - __itoa_internal(num, buffer + ptr, 8, &adv); - break; - } - case 'x': - // fall through - case 'X': { - num = va_arg(args, int); - __itoa_internal(num, buffer + ptr, 16, &adv); - if (c == 'X') { - int p = ptr; - char c_; - while ((c_ = buffer[p])) { - buffer[p] = c_ & ~((c_ & 0x40) >> 1); - p++; - } - } - break; - } - case 'p': { - uintptr_t dptr = va_arg(args, uintptr_t); - buffer[ptr] = '0'; - buffer[ptr+1] = 'x'; - __itoa_internal((int)dptr, buffer + ptr + 2, 16, &adv); - adv+=2; - break; - } - case '%': { - buffer[ptr] = c; - adv = 1; - break; + // This sprintf just a random implementation I found it on Internet . lol. + // Of course, with some modifications for porting to LunaixOS :) + + // TODO: support floating point. + + char numbuf[NUMBUFSIZ]; + uint32_t ptr = 0; + for (; *fmt; ++fmt) { + if (*fmt != '%') { + buffer[ptr++] = *fmt; + continue; + } + + // process flags + int flags = 0; + for (++fmt; *fmt; ++fmt) { + const char* flagc = strchr(flag_chars, *fmt); + if (flagc) { + flags |= 1 << (flagc - flag_chars); + } else { + break; + } + } + + // process width + int width = -1; + if (*fmt >= '1' && *fmt <= '9') { + for (width = 0; *fmt >= '0' && *fmt <= '9'; ) { + width = 10 * width + *fmt++ - '0'; + } + } else if (*fmt == '*') { + width = va_arg(vargs, int); + ++fmt; + } + + // process precision + int precision = -1; + if (*fmt == '.') { + ++fmt; + if (*fmt >= '0' && *fmt <= '9') { + for (precision = 0; *fmt >= '0' && *fmt <= '9'; ) { + precision = 10 * precision + *fmt++ - '0'; } - default: - // unknown - break; + } else if (*fmt == '*') { + precision = va_arg(vargs, int); + ++fmt; } + if (precision < 0) { + precision = 0; + } + } + + // process main conversion character + int base = 10; + unsigned long num = 0; + int length = 0; + char* data = ""; + again: + switch (*fmt) { + case 'l': + case 'z': + length = 1; + ++fmt; + goto again; + case 'd': + case 'i': { + long x = length ? va_arg(vargs, long) : va_arg(vargs, int); + int negative = x < 0 ? FLAG_NEGATIVE : 0; + num = negative ? -x : x; + flags |= FLAG_NUMERIC | FLAG_SIGNED | negative; + break; + } + case 'u': + format_unsigned: + num = length ? va_arg(vargs, unsigned long) : va_arg(vargs, unsigned); + flags |= FLAG_NUMERIC; + break; + case 'x': + base = 16; + goto format_unsigned; + case 'X': + flags = flags | FLAG_CAPS; + base = 16; + goto format_unsigned; + case 'p': + num = (uintptr_t) va_arg(vargs, void*); + base = 16; + flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC; + break; + case 's': + data = va_arg(vargs, char*); + break; + case 'c': + data = numbuf; + numbuf[0] = va_arg(vargs, int); + numbuf[1] = '\0'; + break; + default: + data = numbuf; + numbuf[0] = (*fmt ? *fmt : '%'); + numbuf[1] = '\0'; + if (!*fmt) { + fmt--; + } + break; + } + + if (flags & FLAG_NUMERIC) { + data = itoa(num, numbuf, base); + int i = 0; + char c; + while ((flags & FLAG_CAPS) && (c = data[i])) + { + data[i] = c & ~((c & 0x40) >> 1); + i++; + } + } + + const char* prefix = ""; + if ((flags & FLAG_NUMERIC) && (flags & FLAG_SIGNED)) { + if (flags & FLAG_NEGATIVE) { + prefix = "-"; + } else if (flags & FLAG_PLUSPOSITIVE) { + prefix = "+"; + } else if (flags & FLAG_SPACEPOSITIVE) { + prefix = " "; + } + } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT) + && (base == 16 || base == -16) + && (num || (flags & FLAG_ALT2))) { + prefix = "0x"; + } + + int len; + if (precision >= 0 && !(flags & FLAG_NUMERIC)) { + len = strnlen(data, precision); + } else { + len = strlen(data); + } + int zeros; + if ((flags & FLAG_NUMERIC) && precision >= 0) { + zeros = precision > len ? precision - len : 0; + } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO) + && !(flags & FLAG_LEFTJUSTIFY) + && len + (int) strlen(prefix) < width) { + zeros = width - len - strlen(prefix); + } else { + zeros = 0; + } + width -= len + zeros + strlen(prefix); + for (; !(flags & FLAG_LEFTJUSTIFY) && width > 0; --width) { + buffer[ptr++] = ' '; + } + for (; *prefix; ++prefix) { + buffer[ptr++] = *prefix; + } + for (; zeros > 0; --zeros) { + buffer[ptr++] = '0'; + } + for (; len > 0; ++data, --len) { + buffer[ptr++] = *data; + } + for (; width > 0; --width) { + buffer[ptr++] = ' '; } - fmt++; - ptr += adv; } - buffer[ptr] = '\0'; + buffer[ptr++] = '\0'; } void diff --git a/lunaix-os/libs/libc/string/strchr.c b/lunaix-os/libs/libc/string/strchr.c new file mode 100644 index 0000000..f122a7a --- /dev/null +++ b/lunaix-os/libs/libc/string/strchr.c @@ -0,0 +1,14 @@ +#include + +const char* +strchr(const char* str, int character) +{ + char c = (char)character; + while ((*str)) { + if (*str == c) { + return str; + } + str++; + } + return c == '\0' ? str : NULL; +} \ No newline at end of file diff --git a/lunaix-os/libs/libc/string/strlen.c b/lunaix-os/libs/libc/string/strlen.c index 8b26def..b57ec90 100644 --- a/lunaix-os/libs/libc/string/strlen.c +++ b/lunaix-os/libs/libc/string/strlen.c @@ -7,4 +7,12 @@ strlen(const char* str) while (str[len]) len++; return len; +} + +size_t +strnlen(const char* str, size_t max_len) { + size_t len = 0; + while (str[len] && len <= max_len) + len++; + return len; } \ No newline at end of file diff --git a/lunaix-os/linker.ld b/lunaix-os/link/linker.ld similarity index 100% rename from lunaix-os/linker.ld rename to lunaix-os/link/linker.ld diff --git a/lunaix-os/makefile b/lunaix-os/makefile index 9d3c799..163f91f 100644 --- a/lunaix-os/makefile +++ b/lunaix-os/makefile @@ -20,17 +20,17 @@ $(ISO_DIR): $(OBJECT_DIR)/%.S.o: %.S @mkdir -p $(@D) - @echo "$@" + @echo " BUILD: $<" @$(CC) $(INCLUDES) -c $< -o $@ $(OBJECT_DIR)/%.c.o: %.c @mkdir -p $(@D) - @echo "$@" + @echo " BUILD: $<" @$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS) $(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(SRC) - @echo "Generating $(BIN_DIR)/$(OS_BIN)" - @$(CC) -T linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS) + @echo " LINK: $(BIN_DIR)/$(OS_BIN)" + @$(CC) -T link/linker.ld -o $(BIN_DIR)/$(OS_BIN) $(SRC) $(LDFLAGS) $(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE @./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg @@ -40,11 +40,11 @@ $(BUILD_DIR)/$(OS_ISO): $(ISO_DIR) $(BIN_DIR)/$(OS_BIN) GRUB_TEMPLATE all: clean $(BUILD_DIR)/$(OS_ISO) all-debug: O := -Og -all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) +all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__ all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc all-debug: clean $(BUILD_DIR)/$(OS_ISO) - @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt" - @i686-elf-objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt + # @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt" + # @i686-elf-objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt clean: @rm -rf $(BUILD_DIR) -- 2.27.0