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
This commit is contained in:
Axel Dörfler 2005-11-04 15:58:04 +00:00
parent fcd75d6357
commit 7b7c38a2a7
4 changed files with 57 additions and 30 deletions

View File

@ -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))

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}