Complete (almost!) printf fmt support
authorMinep <zelong56@gmail.com>
Thu, 3 Mar 2022 17:36:53 +0000 (17:36 +0000)
committerMinep <zelong56@gmail.com>
Thu, 3 Mar 2022 17:36:53 +0000 (17:36 +0000)
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)

23 files changed:
lunaix-os/includes/arch/x86/interrupts.h
lunaix-os/includes/hal/cpu.h
lunaix-os/includes/libc/string.h
lunaix-os/includes/lunaix/assert.h [deleted file]
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/mm/vmm.h
lunaix-os/includes/lunaix/spike.h
lunaix-os/kernel/asm/x86/idt.c
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/interrupts.c
lunaix-os/kernel/asm/x86/prologue.S
lunaix-os/kernel/assert.c [deleted file]
lunaix-os/kernel/k_init.c
lunaix-os/kernel/k_main.c
lunaix-os/kernel/mm/dmm.c
lunaix-os/kernel/mm/page.c [new file with mode: 0644]
lunaix-os/kernel/mm/vmm.c
lunaix-os/kernel/spike.c [new file with mode: 0644]
lunaix-os/libs/libc/stdio/sprintf.c
lunaix-os/libs/libc/string/strchr.c [new file with mode: 0644]
lunaix-os/libs/libc/string/strlen.c
lunaix-os/link/linker.ld [moved from lunaix-os/linker.ld with 100% similarity]
lunaix-os/makefile

index 3fb86d63841f1b0662c419a45a9a5c0dc0caf781..3ac415a15c693faec8471d02e3d58b2713be07fc 100644 (file)
@@ -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 <hal/cpu.h>
 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 */
index 63811432ccf5e5dfda139c6cc76587168d74344a..1a3173bb2771079c9c564aa9392b1aa75eb3d6aa 100644 (file)
@@ -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
index 671fdec08089d0bfa51303a4db6ea057bf55be73..7347de2abc2f1bce7fbe4ca46865cd4e87a8318d 100644 (file)
@@ -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 (file)
index 0697b33..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __LUNAIX_ASSERT_H
-#define __LUNAIX_ASSERT_H
-
-#include <libc/stdio.h>
-#include <lunaix/tty/tty.h>
-
-#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 */
index 4ea31bc0a5221cdb4642ebb955cdaf5642bae486..935909cbbeb17f401dc49a38b1c3c57865dae5fe 100644 (file)
@@ -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 */
index a0c455fdf4c765576c86faa7b4cbede8210cdd3d..752f23caf40efa7369170b95b612a3722a907444 100644 (file)
@@ -17,7 +17,7 @@ vmm_init();
  *
  * @return ptd_entry* 页目录的物理地址,随时可以加载进CR3
  */
-ptd_t*
+x86_page_table*
 vmm_init_pd();
 
 /**
index fa4e797ddad4898649f9a290832c370ce8a774b1..7e50693bc6fa37e77467078ceb63505c422d121b 100644 (file)
 // 获取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 */
index 296fa150828b402f149caaf4d39dddfe7876f2af..aa0714070ff63e44e7a22761d7f0ed79f3389963 100644 (file)
@@ -2,7 +2,7 @@
 #include <arch/x86/interrupts.h>
 #include <stdint.h>
 
-#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
index 10fa393ace27c0a643d0cc3f07ba2619b3839444..9d392734efbbd7e7f640e01c7611984ce193e447 100644 (file)
@@ -1,3 +1,6 @@
+#define __ASM__
+#include <arch/x86/interrupts.h>
+
 .macro isr_template vector, no_error_code=1
     .global _asm_isr\vector
     .type _asm_isr\vector, @function
 .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
         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
index 925c13de340acb108f72b337d27016afbaa11e98..8dfb23bf32a176e33a935b3bd455c834360fe189 100644 (file)
@@ -1,14 +1,20 @@
 #include <arch/x86/interrupts.h>
-#include <lunaix/assert.h>
+#include <lunaix/tty/tty.h>
 #include <libc/stdio.h>
 
-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
index fe1b645e54ca2a1f4e2bed238b9d6665e2cfa973..cbfd414765ed0cfa3086f3b1fb21cb1002ed7be6 100644 (file)
@@ -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 (file)
index 10fb78b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <lunaix/assert.h>
-
-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
index 07091ca53fcfaab4db805b330c384145df1c75cd..0b73f92d59e953829b38510146bd1c42268535c3 100644 (file)
@@ -4,8 +4,13 @@
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
+#include <lunaix/mm/dmm.h>
+#include <lunaix/spike.h>
 
 #include <arch/x86/boot/multiboot.h>
+#include <arch/x86/idt.h>
+
+#include <libc/stdio.h>
 
 #include <stdint.h>
 #include <stddef.h>
@@ -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 标识可用的物理页
index 3f56166b14f57c659c9920c4156412ac5e0d3237..121273bed02243126a09f629905968e04bed6652 100644 (file)
@@ -3,6 +3,7 @@
 #include <lunaix/mm/dmm.h>
 #include <hal/cpu.h>
 #include <libc/stdio.h>
+#include <lunaix/spike.h>
 
 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
index e15e4321bc816a2ea0a87e350c6c9c7274706cc2..e5f2ec50222551f2e95a716915e9941a21299340 100644 (file)
  *
  */
 
+// TODO: Make the dmm portable
+
 #include <lunaix/mm/dmm.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/vmm.h>
 
-#include <lunaix/assert.h>
 #include <lunaix/constants.h>
 #include <lunaix/spike.h>
 
@@ -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 (file)
index 0000000..400197f
--- /dev/null
@@ -0,0 +1 @@
+#include <lunaix/mm/page.h>
\ No newline at end of file
index 63ff9ac4bba11b05358a0bc1f0106f90c53844c7..54da656e695519ac61734665226df0be721be80e 100644 (file)
@@ -1,9 +1,9 @@
+#include <hal/cpu.h>
 #include <libc/string.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
-#include <lunaix/assert.h>
-#include <hal/cpu.h>
+#include <lunaix/spike.h>
 
 #include <stdbool.h>
 
@@ -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 (file)
index 0000000..91f597d
--- /dev/null
@@ -0,0 +1,19 @@
+#include <lunaix/spike.h>
+#include <arch/x86/interrupts.h>
+#include <libc/stdio.h>
+
+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
index 51466cd59483035be7e76e10f68c5a9b96e13888..61772676c3aeff4bcc4da7ea10c96f704d37738c 100644 (file)
 #include <libc/string.h>
 #include <stdint.h>
 
+#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 (file)
index 0000000..f122a7a
--- /dev/null
@@ -0,0 +1,14 @@
+#include <libc/string.h>
+
+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
index 8b26def28331dfc3460d6fc36a8ee89ab13b030d..b57ec902fde1ec7489f700c783294a1f3c1da830 100644 (file)
@@ -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
similarity index 100%
rename from lunaix-os/linker.ld
rename to lunaix-os/link/linker.ld
index 9d3c79942ac68bc71367b1204d82cac001294cef..163f91fafe4462ee52236117f6b7cf0665fbc094 100644 (file)
@@ -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)