From b9f4a7b7475e62dbff22da6dd768222f03889c00 Mon Sep 17 00:00:00 2001 From: Minep Date: Sun, 20 Aug 2023 17:14:13 +0100 Subject: [PATCH] feat: kernel stack tracing refactor: move cpu.h to arch specific --- lunaix-os/GRUB_TEMPLATE | 2 +- lunaix-os/arch/i386/exceptions/interrupt.S | 4 + lunaix-os/arch/i386/exceptions/interrupts.c | 2 +- .../arch/i386/exceptions/intr_routines.c | 30 ++-- lunaix-os/arch/i386/hal/apic.c | 2 +- lunaix-os/arch/i386/hal/cpu.c | 96 ++---------- lunaix-os/arch/i386/includes/sys/cpu.h | 136 +++++++++++++++++ lunaix-os/arch/i386/includes/sys/interrupts.h | 5 +- lunaix-os/arch/i386/mm/pfault.c | 4 + lunaix-os/includes/hal/cpu.h | 83 ----------- lunaix-os/includes/lunaix/trace.h | 21 ++- lunaix-os/kernel/block/blkio.c | 2 +- lunaix-os/kernel/boot_helper.c | 9 ++ lunaix-os/kernel/debug/trace.c | 140 +++++++++++++++++- lunaix-os/kernel/mm/vmm.c | 2 +- lunaix-os/kernel/peripheral/ps2kbd.c | 2 +- lunaix-os/kernel/peripheral/serial.c | 2 +- lunaix-os/kernel/process/sched.c | 2 +- lunaix-os/scripts/syms_export.py | 10 +- lunaix-os/usr/libc/arch/i386/crt0.S | 3 +- 20 files changed, 355 insertions(+), 202 deletions(-) create mode 100644 lunaix-os/arch/i386/includes/sys/cpu.h delete mode 100644 lunaix-os/includes/hal/cpu.h diff --git a/lunaix-os/GRUB_TEMPLATE b/lunaix-os/GRUB_TEMPLATE index 7d5fd86..176f426 100644 --- a/lunaix-os/GRUB_TEMPLATE +++ b/lunaix-os/GRUB_TEMPLATE @@ -3,5 +3,5 @@ timeout=0 menuentry "$_OS_NAME" { multiboot /boot/kernel.bin - module /boot/modksyms modksyms + module --nounzip /boot/modksyms modksyms } \ No newline at end of file diff --git a/lunaix-os/arch/i386/exceptions/interrupt.S b/lunaix-os/arch/i386/exceptions/interrupt.S index e5a125f..c61e6a6 100644 --- a/lunaix-os/arch/i386/exceptions/interrupt.S +++ b/lunaix-os/arch/i386/exceptions/interrupt.S @@ -33,6 +33,7 @@ */ .section .text + .type interrupt_wrapper, @function .global interrupt_wrapper interrupt_wrapper: cld @@ -90,6 +91,7 @@ subl $16, %esp movl %eax, (%esp) + xorl %ebp, %ebp # marks the boundary of stack walking call intr_handler movl (%esp), %eax @@ -158,6 +160,7 @@ iret + .type switch_to, @function .global switch_to switch_to: # 约定 @@ -201,6 +204,7 @@ movl proc_intr_ctx(%ebx), %eax jmp soft_iret + .type handle_signal, @function .global handle_signal handle_signal: # 注意1:任何对proc_sig的布局改动,都须及时的保证这里的一致性! diff --git a/lunaix-os/arch/i386/exceptions/interrupts.c b/lunaix-os/arch/i386/exceptions/interrupts.c index adde973..c45f961 100644 --- a/lunaix-os/arch/i386/exceptions/interrupts.c +++ b/lunaix-os/arch/i386/exceptions/interrupts.c @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include diff --git a/lunaix-os/arch/i386/exceptions/intr_routines.c b/lunaix-os/arch/i386/exceptions/intr_routines.c index 6571f9a..100df0b 100644 --- a/lunaix-os/arch/i386/exceptions/intr_routines.c +++ b/lunaix-os/arch/i386/exceptions/intr_routines.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -23,47 +24,42 @@ extern u32_t debug_resv; void __print_panic_msg(const char* msg, const isr_param* param) { - volatile struct exec_param* execp = param->execp; - - kprint_panic(" INT %u: (%x) [%p: %p] %s", - execp->vector, - execp->err_code, - execp->cs, - execp->eip, - msg); + kprintf(KERROR "panic: %s\n", msg); + trace_printstack_isr(param); } void intr_routine_divide_zero(const isr_param* param) { + __print_panic_msg("div zero", param); + console_flush(); - __print_panic_msg("Divide by zero!", param); spin(); } void intr_routine_general_protection(const isr_param* param) { - kprintf(KERROR "Pid: %d\n", __current->pid); - kprintf(KERROR "Addr: %p\n", (&debug_resv)[0]); - kprintf(KERROR "Expected: %p\n", (&debug_resv)[1]); + __print_panic_msg("general protection", param); + console_flush(); - __print_panic_msg("General Protection", param); spin(); } void intr_routine_sys_panic(const isr_param* param) { - console_flush(); __print_panic_msg((char*)(param->registers.edi), param); + + console_flush(); spin(); } void intr_routine_fallback(const isr_param* param) { - __print_panic_msg("Unknown Interrupt", param); + __print_panic_msg("unknown interrupt", param); + console_flush(); spin(); } @@ -85,8 +81,10 @@ intr_routine_apic_error(const isr_param* param) u32_t error_reg = apic_read_reg(APIC_ESR); char buf[32]; ksprintf(buf, "APIC error, ESR=0x%x", error_reg); - console_flush(); + __print_panic_msg(buf, param); + + console_flush(); spin(); } diff --git a/lunaix-os/arch/i386/hal/apic.c b/lunaix-os/arch/i386/hal/apic.c index bd53fc5..4323ac8 100644 --- a/lunaix-os/arch/i386/hal/apic.c +++ b/lunaix-os/arch/i386/hal/apic.c @@ -9,7 +9,7 @@ * */ -#include +#include #include #include diff --git a/lunaix-os/arch/i386/hal/cpu.c b/lunaix-os/arch/i386/hal/cpu.c index 2ca126a..00ba7f4 100644 --- a/lunaix-os/arch/i386/hal/cpu.c +++ b/lunaix-os/arch/i386/hal/cpu.c @@ -1,7 +1,7 @@ -#include #include -#include #include +#include +#include #define BRAND_LEAF 0x80000000UL @@ -46,68 +46,20 @@ cpu_get_id(char* id_out) id_out[48] = '\0'; } -u32_t -cpu_ldstate() -{ - ptr_t val; - asm volatile("pushf\n" - "popl %0\n" - : "=r"(val)::); - return val; -} - -u32_t -cpu_ldconfig() -{ - ptr_t val; - asm volatile("movl %%cr0,%0" : "=r"(val)); - return val; -} - -void -cpu_chconfig(u32_t val) -{ - asm("mov %0, %%cr0" ::"r"(val)); -} - -u32_t -cpu_ldvmspace() -{ - ptr_t val; - asm volatile("movl %%cr3,%0" : "=r"(val)); - return val; -} - -void -cpu_chvmspace(u32_t val) -{ - asm("mov %0, %%cr3" ::"r"(val)); -} - -void -cpu_flush_page(ptr_t va) -{ - asm volatile("invlpg (%0)" ::"r"(va) : "memory"); -} - void -cpu_flush_vmspace() +cpu_rdmsr(u32_t msr_idx, u32_t* reg_high, u32_t* reg_low) { - asm("movl %%cr3, %%eax\n" - "movl %%eax, %%cr3" :: - : "eax"); -} + u32_t h = 0, l = 0; + asm volatile("rdmsr" : "=d"(h), "=a"(l) : "c"(msr_idx)); -void -cpu_enable_interrupt() -{ - asm volatile("sti"); + *reg_high = h; + *reg_low = l; } void -cpu_disable_interrupt() +cpu_wrmsr(u32_t msr_idx, u32_t reg_high, u32_t reg_low) { - asm volatile("cli"); + asm volatile("wrmsr" : : "d"(reg_high), "a"(reg_low), "c"(msr_idx)); } void @@ -121,33 +73,3 @@ cpu_trap_panic(char* message) { asm("int %0" ::"i"(LUNAIX_SYS_PANIC), "D"(message)); } - -void -cpu_wait() -{ - asm("hlt"); -} - -ptr_t -cpu_ldeaddr() -{ - ptr_t val; - asm volatile("movl %%cr2,%0" : "=r"(val)); - return val; -} - -void -cpu_rdmsr(u32_t msr_idx, u32_t* reg_high, u32_t* reg_low) -{ - u32_t h = 0, l = 0; - asm volatile("rdmsr" : "=d"(h), "=a"(l) : "c"(msr_idx)); - - *reg_high = h; - *reg_low = l; -} - -void -cpu_wrmsr(u32_t msr_idx, u32_t reg_high, u32_t reg_low) -{ - asm volatile("wrmsr" : : "d"(reg_high), "a"(reg_low), "c"(msr_idx)); -} \ No newline at end of file diff --git a/lunaix-os/arch/i386/includes/sys/cpu.h b/lunaix-os/arch/i386/includes/sys/cpu.h new file mode 100644 index 0000000..3289522 --- /dev/null +++ b/lunaix-os/arch/i386/includes/sys/cpu.h @@ -0,0 +1,136 @@ +#ifndef __LUNAIX_CPU_H +#define __LUNAIX_CPU_H + +#include + +/** + * @brief Get processor ID string + * + * @param id_out + */ +void +cpu_get_id(char* id_out); + +void +cpu_trap_sched(); + +void +cpu_trap_panic(char* message); + +static inline ptr_t +cpu_get_fp() +{ + ptr_t val; + asm("movl %%ebp, %0" : "=r"(val)::); + return val; +} + +/** + * @brief Load current processor state + * + * @return u32_t + */ +static inline u32_t +cpu_ldstate() +{ + ptr_t val; + asm volatile("pushf\n" + "popl %0\n" + : "=r"(val)::); + return val; +} + +/** + * @brief Load current processor config + * + * @return u32_t + */ +static inline u32_t +cpu_ldconfig() +{ + ptr_t val; + asm volatile("movl %%cr0,%0" : "=r"(val)); + return val; +} + +/** + * @brief Change current processor state + * + * @return u32_t + */ +static inline void +cpu_chconfig(u32_t val) +{ + asm("mov %0, %%cr0" ::"r"(val)); +} + +/** + * @brief Load current virtual memory space + * + * @return u32_t + */ +static inline u32_t +cpu_ldvmspace() +{ + ptr_t val; + asm volatile("movl %%cr3,%0" : "=r"(val)); + return val; +} + +/** + * @brief Change current virtual memory space + * + * @return u32_t + */ +static inline void +cpu_chvmspace(u32_t val) +{ + asm("mov %0, %%cr3" ::"r"(val)); +} + +/** + * @brief Flush TLB + * + * @return u32_t + */ +static inline void +cpu_flush_page(ptr_t va) +{ + asm volatile("invlpg (%0)" ::"r"(va) : "memory"); +} + +static inline void +cpu_flush_vmspace() +{ + asm("movl %%cr3, %%eax\n" + "movl %%eax, %%cr3" :: + : "eax"); +} + +static inline void +cpu_enable_interrupt() +{ + asm volatile("sti"); +} + +static inline void +cpu_disable_interrupt() +{ + asm volatile("cli"); +} + +static inline void +cpu_wait() +{ + asm("hlt"); +} + +static inline ptr_t +cpu_ldeaddr() +{ + ptr_t val; + asm volatile("movl %%cr2,%0" : "=r"(val)); + return val; +} + +#endif /* __LUNAIX_CPU_H */ diff --git a/lunaix-os/arch/i386/includes/sys/interrupts.h b/lunaix-os/arch/i386/includes/sys/interrupts.h index 003a2cd..f1b7bf9 100644 --- a/lunaix-os/arch/i386/includes/sys/interrupts.h +++ b/lunaix-os/arch/i386/includes/sys/interrupts.h @@ -4,7 +4,10 @@ #include "vectors.h" #ifndef __ASM__ -#include +#include + +#define saved_fp(isrm) ((isrm)->registers.ebp) +#define uspace_context(isrm) (((isrm)->execp->cs) == 0x8) struct exec_param; diff --git a/lunaix-os/arch/i386/mm/pfault.c b/lunaix-os/arch/i386/mm/pfault.c index 4c28a95..b028d84 100644 --- a/lunaix-os/arch/i386/mm/pfault.c +++ b/lunaix-os/arch/i386/mm/pfault.c @@ -7,6 +7,8 @@ #include #include #include +#include + #include #include @@ -159,6 +161,8 @@ segv_term: sigset_add(__current->sigctx.sig_pending, _SIGSEGV); + trace_printstack_isr(param); + schedule(); // should not reach while (1) diff --git a/lunaix-os/includes/hal/cpu.h b/lunaix-os/includes/hal/cpu.h deleted file mode 100644 index c68bb95..0000000 --- a/lunaix-os/includes/hal/cpu.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __LUNAIX_CPU_H -#define __LUNAIX_CPU_H - -#include - -/** - * @brief Get processor ID string - * - * @param id_out - */ -void -cpu_get_id(char* id_out); - -/** - * @brief Load current processor state - * - * @return u32_t - */ -u32_t -cpu_ldstate(); - -/** - * @brief Load current processor config - * - * @return u32_t - */ -u32_t -cpu_ldconfig(); - -/** - * @brief Change current processor state - * - * @return u32_t - */ -void -cpu_chconfig(u32_t val); - -/** - * @brief Load current virtual memory space - * - * @return u32_t - */ -u32_t -cpu_ldvmspace(); - -/** - * @brief Change current virtual memory space - * - * @return u32_t - */ -void -cpu_chvmspace(u32_t val); - -/** - * @brief Flush TLB - * - * @return u32_t - */ -void -cpu_flush_page(ptr_t va); - -void -cpu_flush_vmspace(); - -void -cpu_enable_interrupt(); - -void -cpu_disable_interrupt(); - -void -cpu_trap_sched(); - -void -cpu_trap_panic(char* message); - -void -cpu_wait(); - -ptr_t -cpu_ldeaddr(); - -#endif /* __LUNAIX_CPU_H */ diff --git a/lunaix-os/includes/lunaix/trace.h b/lunaix-os/includes/lunaix/trace.h index 80cf5f3..4fbddd9 100644 --- a/lunaix-os/includes/lunaix/trace.h +++ b/lunaix-os/includes/lunaix/trace.h @@ -2,6 +2,7 @@ #define __LUNAIX_TRACE_H #include +#include struct ksym_entry { @@ -9,6 +10,12 @@ struct ksym_entry u32_t label_off; }; +struct trace_record +{ + ptr_t pc; + char* symbol; +}; + struct ksyms { u32_t ksym_count; @@ -27,7 +34,19 @@ trace_modksyms_init(struct boot_handoff* bhctx); struct ksym_entry* trace_sym_lookup(ptr_t pc); +int +trace_walkback(struct trace_record* tb_buffer, + ptr_t fp, + int limit, + ptr_t* last_fp); + +void +trace_printstack_of(ptr_t fp); + +void +trace_printstack_isr(const isr_param* isrm); + void -trace_walkback(ptr_t fp); +trace_printstack(); #endif /* __LUNAIX_TRACE_H */ diff --git a/lunaix-os/kernel/block/blkio.c b/lunaix-os/kernel/block/blkio.c index 0427622..9fcd670 100644 --- a/lunaix-os/kernel/block/blkio.c +++ b/lunaix-os/kernel/block/blkio.c @@ -2,7 +2,7 @@ #include #include -#include +#include static struct cake_pile* blkio_reqpile; diff --git a/lunaix-os/kernel/boot_helper.c b/lunaix-os/kernel/boot_helper.c index fa87bff..1383f60 100644 --- a/lunaix-os/kernel/boot_helper.c +++ b/lunaix-os/kernel/boot_helper.c @@ -32,6 +32,15 @@ boot_begin(struct boot_handoff* bhctx) vmm_set_mapping(VMS_SELF, pa, pa, PG_PREM_RW, VMAP_IGNORE); } } + + /* Reserve region for all loaded modules */ + for (size_t i = 0; i < bhctx->mods.mods_num; i++) { + struct boot_modent* mod = &bhctx->mods.entries[i]; + pmm_mark_chunk_occupied(KERNEL_PID, + PN(mod->start), + CEIL(mod->end - mod->start, PG_SIZE_BITS), + PP_FGLOCKED); + } } extern u8_t __kexec_boot_end; /* link/linker.ld */ diff --git a/lunaix-os/kernel/debug/trace.c b/lunaix-os/kernel/debug/trace.c index c08a6f7..a3553f1 100644 --- a/lunaix-os/kernel/debug/trace.c +++ b/lunaix-os/kernel/debug/trace.c @@ -1,10 +1,19 @@ #include #include +#include #include +#include #include +#include +#include + #include +#define NB_TRACEBACK 16 + +LOG_MODULE("TRACE") + static struct trace_context trace_ctx; void @@ -26,12 +35,137 @@ trace_modksyms_init(struct boot_handoff* bhctx) } struct ksym_entry* -trace_sym_lookup(ptr_t pc) +trace_sym_lookup(ptr_t addr) +{ + int c = trace_ctx.ksym_table->ksym_count; + struct ksym_entry* ksent = trace_ctx.ksym_table->syms; + + int i = c - 1, j = 0, m = 0; + + if (addr > ksent[i].pc || addr < ksent[j].pc || addr < KERNEL_EXEC) { + return NULL; + } + + while (i - j != 1) { + m = (i + j) / 2; + if (ksent[m].pc > addr) { + i = m; + } else if (ksent[m].pc < addr) { + j = m; + } else { + break; + } + } + + struct ksym_entry* result = &ksent[MIN(i, j)]; + if (result->pc > addr) { + return NULL; + } + + return result; +} + +static char* +ksym_getstr(struct ksym_entry* sym) +{ + if (!sym) { + return "???"; + } + + return (char*)((ptr_t)trace_ctx.ksym_table + + trace_ctx.ksym_table->ksym_label_off + sym->label_off); +} + +int +trace_walkback(struct trace_record* tb_buffer, + ptr_t fp, + int limit, + ptr_t* last_fp) +{ + ptr_t* frame = (ptr_t*)fp; + struct ksym_entry* current = NULL; + int i = 0; + + while (frame && i < limit) { + ptr_t pc = *(frame + 1); + + current = trace_sym_lookup(pc); + tb_buffer[i] = (struct trace_record){ .pc = current ? current->pc : pc, + .symbol = ksym_getstr(current) }; + + frame = (ptr_t*)*frame; + i++; + } + + if (last_fp) { + *last_fp = (ptr_t)frame; + } + + return i; +} + +void +trace_printstack_of(ptr_t fp) +{ + struct trace_record tbs[NB_TRACEBACK]; + + int n = trace_walkback(tbs, fp, NB_TRACEBACK, &fp); + + if (fp) { + kprintf(KDEBUG "...\n"); + } + + for (int i = 0; i < n; i++) { + kprintf(KDEBUG "%p: %s\n", tbs[i].pc, tbs[i].symbol); + } +} + +void +trace_printstack() { - return NULL; + trace_printstack_of(cpu_get_fp()); } void -trace_walkback(ptr_t fp) +trace_printswctx(const isr_param* p, char* direction) { + + struct ksym_entry* sym = trace_sym_lookup(p->execp->eip); + + kprintf( + KDEBUG ">> (sw:%s) iv:%d, errno:%p <<\n", direction, p->execp->vector); + kprintf(KDEBUG "%p:%s\n", p->execp->eip, ksym_getstr(sym)); +} + +void +trace_printstack_isr(const isr_param* isrm) +{ + isr_param* p = isrm; + ptr_t fp = cpu_get_fp(); + int prev_fromusr = uspace_context(p); + + kprintf(KDEBUG "\n"); + kprintf(KDEBUG "stack trace (pid=%d)\n", __current->pid); + + trace_printstack_of(fp); + + while (p) { + if (!prev_fromusr) { + if (uspace_context(p)) { + trace_printswctx(p, "s/u"); + } else { + trace_printswctx(p, "s/s"); + } + } else { + trace_printswctx(p, "u/s"); + } + + fp = saved_fp(p); + trace_printstack_of(fp); + + prev_fromusr = uspace_context(p); + + p = p->execp->saved_prev_ctx; + } + kprintf(KDEBUG "\n"); } \ No newline at end of file diff --git a/lunaix-os/kernel/mm/vmm.c b/lunaix-os/kernel/mm/vmm.c index 5a868d4..c3ba814 100644 --- a/lunaix-os/kernel/mm/vmm.c +++ b/lunaix-os/kernel/mm/vmm.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index fc55ece..6690faf 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/lunaix-os/kernel/peripheral/serial.c b/lunaix-os/kernel/peripheral/serial.c index 516d569..8cdced6 100644 --- a/lunaix-os/kernel/peripheral/serial.c +++ b/lunaix-os/kernel/peripheral/serial.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 82c73c0..31a94ee 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include diff --git a/lunaix-os/scripts/syms_export.py b/lunaix-os/scripts/syms_export.py index af5d901..7edbfcb 100644 --- a/lunaix-os/scripts/syms_export.py +++ b/lunaix-os/scripts/syms_export.py @@ -4,7 +4,7 @@ import re sym_line = re.compile(r"^(?P[0-9a-f]+)\s[a-z]\s+F\s+\.[a-z._]+\s+[0-9a-f]+(?P