From 7b7c38a2a77b408d1bbb252a003911fa5383e861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 4 Nov 2005 15:58:04 +0000 Subject: [PATCH] The "where" or "sc" command now switches the page directory to the specified thread to be able to follow the stack trace into userland. No symbols there, yet, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14697 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_cpu.h | 4 +- headers/private/kernel/arch/x86/arch_thread.h | 1 + src/system/kernel/arch/x86/arch_debug.c | 18 ++++++ src/system/kernel/arch/x86/arch_thread.c | 64 ++++++++++--------- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index e2be1dcd05..b7a6ab5190 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -83,13 +83,15 @@ void x86_write_msr(uint32 register, uint64 value); void x86_set_task_gate(int32 n, int32 segment); struct tss *x86_get_main_tss(void); - #define read_ebp(value) \ __asm__("movl %%ebp,%0" : "=r" (value)) #define read_cr3(value) \ __asm__("movl %%cr3,%0" : "=r" (value)) +#define write_cr3(value) \ + __asm__("movl %0,%%cr3" : : "r" (value)) + #define read_dr3(value) \ __asm__("movl %%dr3,%0" : "=r" (value)) diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index cd75303db7..0138815bbf 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -19,6 +19,7 @@ extern "C" { void x86_push_iframe(struct iframe_stack *stack, struct iframe *frame); void x86_pop_iframe(struct iframe_stack *stack); struct iframe *i386_get_user_iframe(void); +void *x86_next_page_directory(struct thread *from, struct thread *to); void i386_return_from_signal(); void i386_end_return_from_signal(); diff --git a/src/system/kernel/arch/x86/arch_debug.c b/src/system/kernel/arch/x86/arch_debug.c index cabf1c3bfd..5d8fc841e3 100644 --- a/src/system/kernel/arch/x86/arch_debug.c +++ b/src/system/kernel/arch/x86/arch_debug.c @@ -74,6 +74,7 @@ stack_trace(int argc, char **argv) uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; struct iframe_stack *frameStack; struct thread *thread; + addr_t oldPageDirectory = 0; uint32 ebp; int32 i, num = 0, last = 0; @@ -90,6 +91,18 @@ stack_trace(int argc, char **argv) // read %ebp from the thread's stack stored by a pushad ebp = thread->arch_info.current_stack.esp[2]; + + if (id != thread_get_current_thread_id()) { + // switch to the page directory of the new thread to be + // able to follow the stack trace into userland + addr_t newPageDirectory = (addr_t)x86_next_page_directory( + thread_get_current_thread(), thread); + + if (newPageDirectory != 0) { + read_cr3(oldPageDirectory); + write_cr3(newPageDirectory); + } + } } // We don't have a thread pointer early in the boot process @@ -185,6 +198,11 @@ stack_trace(int argc, char **argv) break; } + if (oldPageDirectory != 0) { + // switch back to the previous page directory to no cause any troubles + write_cr3(oldPageDirectory); + } + return 0; } diff --git a/src/system/kernel/arch/x86/arch_thread.c b/src/system/kernel/arch/x86/arch_thread.c index 0262c08467..da1e7946e9 100644 --- a/src/system/kernel/arch/x86/arch_thread.c +++ b/src/system/kernel/arch/x86/arch_thread.c @@ -112,6 +112,29 @@ i386_get_user_iframe(void) } +inline void * +x86_next_page_directory(struct thread *from, struct thread *to) +{ + if (from->team->aspace != NULL && to->team->aspace != NULL) { + // they are both uspace threads + if (from->team == to->team) { + // dont change the pgdir, same address space + return NULL; + } + // switching to a new address space + return i386_translation_map_get_pgdir(&to->team->aspace->translation_map); + } else if (from->team->aspace == NULL && to->team->aspace == NULL) { + // they must both be kspace threads + return NULL; + } else if (to->team->aspace == NULL) { + // the one we're switching to is kspace + return i386_translation_map_get_pgdir(&to->team->kaspace->translation_map); + } + + return i386_translation_map_get_pgdir(&to->team->aspace->translation_map); +} + + static inline void set_fs_register(uint32 segment) { @@ -225,9 +248,9 @@ arch_thread_switch_kstack_and_call(struct thread *t, addr_t new_kstack, void (*f void -arch_thread_context_switch(struct thread *t_from, struct thread *t_to) +arch_thread_context_switch(struct thread *from, struct thread *to) { - void *new_pgdir; + addr_t newPageDirectory; #if 0 int i; @@ -242,42 +265,25 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to) for (i = 0; i < 11; i++) dprintf("*esp[%d] (0x%x) = 0x%x\n", i, ((unsigned int *)new_at->esp + i), *((unsigned int *)new_at->esp + i)); #endif - i386_set_tss_and_kstack(t_to->kernel_stack_base + KERNEL_STACK_SIZE); + i386_set_tss_and_kstack(to->kernel_stack_base + KERNEL_STACK_SIZE); // set TLS GDT entry to the current thread - since this action is // dependent on the current CPU, we have to do it here - if (t_to->user_local_storage != NULL) - set_tls_context(t_to); + if (to->user_local_storage != NULL) + set_tls_context(to); - if (t_from->team->aspace != NULL && t_to->team->aspace != NULL) { - // they are both uspace threads - if (t_from->team == t_to->team) { - // dont change the pgdir, same address space - new_pgdir = NULL; - } else { - // switching to a new address space - new_pgdir = i386_translation_map_get_pgdir(&t_to->team->aspace->translation_map); - } - } else if (t_from->team->aspace == NULL && t_to->team->aspace == NULL) { - // they must both be kspace threads - new_pgdir = NULL; - } else if (t_to->team->aspace == NULL) { - // the one we're switching to is kspace - new_pgdir = i386_translation_map_get_pgdir(&t_to->team->kaspace->translation_map); - } else { - new_pgdir = i386_translation_map_get_pgdir(&t_to->team->aspace->translation_map); - } + newPageDirectory = (addr_t)x86_next_page_directory(from, to); - if (((uint32)new_pgdir % B_PAGE_SIZE) != 0) - panic("arch_thread_context_switch: bad pgdir 0x%lx\n", new_pgdir); + if ((newPageDirectory % B_PAGE_SIZE) != 0) + panic("arch_thread_context_switch: bad pgdir 0x%lx\n", newPageDirectory); // reinit debugging; necessary, if the thread was preempted after // initializing debugging before returning to userland - if (t_to->team->aspace != NULL) - i386_reinit_user_debug_after_context_switch(t_to); + if (to->team->aspace != NULL) + i386_reinit_user_debug_after_context_switch(to); - i386_fsave_swap(t_from->arch_info.fpu_state, t_to->arch_info.fpu_state); - i386_context_switch(&t_from->arch_info, &t_to->arch_info, (addr_t)new_pgdir); + i386_fsave_swap(from->arch_info.fpu_state, to->arch_info.fpu_state); + i386_context_switch(&from->arch_info, &to->arch_info, newPageDirectory); }