From 9d06770cdc85682b5c21c926be730fedccca9f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 4 Apr 2005 14:13:25 +0000 Subject: [PATCH] The iframe stack is now in a special structure iframe_stack. Introduced a gBootFrameStack that is used until the first thread structure is available - this allows stack crawls and useful register dumps during early startup. Could also be solved differently by making sure there is always a thread structure installed in %dr3 (ie. the boot thread would get a static thread structure instead of a static iframe stack only). This might be a better solution as i386_handle_trap() would no longer need to check for an existing thread structure. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12230 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_thread.h | 23 ++++---- .../private/kernel/arch/x86/thread_struct.h | 20 ++++--- src/kernel/core/arch/x86/arch_debug.c | 58 +++++++++++-------- src/kernel/core/arch/x86/arch_int.c | 10 +++- src/kernel/core/arch/x86/arch_thread.c | 23 ++++---- 5 files changed, 79 insertions(+), 55 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 2465c19688..cd75303db7 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -1,22 +1,23 @@ /* -** Copyright 2002-2004, The Haiku Team. All rights reserved. -** Distributed under the terms of the Haiku License. -** -** Copyright 2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ + * Copyright 2002-2005, The Haiku Team. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ #ifndef _KERNEL_ARCH_x86_THREAD_H #define _KERNEL_ARCH_x86_THREAD_H + +#include + + #ifdef __cplusplus extern "C" { #endif -#include - - -void i386_push_iframe(struct thread *t, struct iframe *frame); -void i386_pop_iframe(struct thread *t); +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 i386_return_from_signal(); diff --git a/headers/private/kernel/arch/x86/thread_struct.h b/headers/private/kernel/arch/x86/thread_struct.h index 4e017914a2..29fb9c262a 100644 --- a/headers/private/kernel/arch/x86/thread_struct.h +++ b/headers/private/kernel/arch/x86/thread_struct.h @@ -1,10 +1,10 @@ /* -** Copyright 2002-2004, The Haiku Team. All rights reserved. -** Distributed under the terms of the Haiku License. -** -** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ + * Copyright 2002-2005, The Haiku Team. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ #ifndef _KERNEL_ARCH_x86_THREAD_STRUCT_H #define _KERNEL_ARCH_x86_THREAD_STRUCT_H @@ -19,14 +19,18 @@ struct farcall { #define IFRAME_TRACE_DEPTH 4 +struct iframe_stack { + struct iframe *frames[IFRAME_TRACE_DEPTH]; + int32 index; +}; + // architecture specific thread info struct arch_thread { struct farcall current_stack; struct farcall interrupt_stack; // used to track interrupts on this thread - struct iframe *iframes[IFRAME_TRACE_DEPTH]; - int iframe_ptr; + struct iframe_stack iframes; // 512 byte floating point save point uint8 fpu_state[512]; diff --git a/src/kernel/core/arch/x86/arch_debug.c b/src/kernel/core/arch/x86/arch_debug.c index e6156b3911..46c7d08bee 100644 --- a/src/kernel/core/arch/x86/arch_debug.c +++ b/src/kernel/core/arch/x86/arch_debug.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -11,13 +11,15 @@ #include #include #include -#include +#include #include #define NUM_PREVIOUS_LOCATIONS 16 +extern struct iframe_stack gBootFrameStack; + static bool already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) @@ -45,50 +47,60 @@ static int dbg_stack_trace(int argc, char **argv) { uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; - struct thread *t; + struct iframe_stack *frameStack; + struct thread *thread; uint32 ebp; int32 i, num = 0, last = 0; - if (argc < 2) - t = thread_get_current_thread(); - else { + if (argc < 2) { + thread = thread_get_current_thread(); + if (thread != NULL) + frameStack = &thread->arch_info.iframes; + else + frameStack = &gBootFrameStack; + } else { dprintf("not supported\n"); return 0; } - for (i = 0; i < t->arch_info.iframe_ptr; i++) { - char *temp = (char *)t->arch_info.iframes[i]; - dprintf("iframe %p %p %p\n", temp, temp + sizeof(struct iframe), temp + sizeof(struct iframe) - 8); + for (i = 0; i < frameStack->index; i++) { + dprintf("iframe %p (end = %p)\n", + frameStack->frames[i], frameStack->frames[i] + 1); } - dprintf("stack trace for thread 0x%lx \"%s\"\n", t->id, t->name); + // We don't have a thread pointer early in the boot process + if (thread != NULL) { + dprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id, thread->name); - dprintf(" kernel stack: %p to %p\n", - (void *)t->kernel_stack_base, (void *)(t->kernel_stack_base + KERNEL_STACK_SIZE)); - if (t->user_stack_base != 0) { - dprintf(" user stack: %p to %p\n", (void *)t->user_stack_base, - (void *)(t->user_stack_base + t->user_stack_size)); + dprintf(" kernel stack: %p to %p\n", + (void *)thread->kernel_stack_base, (void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE)); + if (thread->user_stack_base != 0) { + dprintf(" user stack: %p to %p\n", (void *)thread->user_stack_base, + (void *)(thread->user_stack_base + thread->user_stack_size)); + } } dprintf("frame caller :function + offset\n"); read_ebp(ebp); for (;;) { - bool is_iframe = false; + bool isIFrame = false; // see if the ebp matches the iframe - for (i = 0; i < t->arch_info.iframe_ptr; i++) { - if (ebp == ((uint32)t->arch_info.iframes[i] - 8)) { + for (i = 0; i < frameStack->index; i++) { + if (ebp == ((uint32)frameStack->frames[i] - 8)) { // it's an iframe - is_iframe = true; + isIFrame = true; } } - if (is_iframe) { + if (isIFrame) { struct iframe *frame = (struct iframe *)(ebp + 8); dprintf("iframe at %p\n", frame); - dprintf(" eax 0x%-9x ebx 0x%-9x ecx 0x%-9x edx 0x%x\n", frame->eax, frame->ebx, frame->ecx, frame->edx); - dprintf(" esi 0x%-9x edi 0x%-9x ebp 0x%-9x esp 0x%x\n", frame->esi, frame->edi, frame->ebp, frame->esp); + dprintf(" eax 0x%-9x ebx 0x%-9x ecx 0x%-9x edx 0x%x\n", + frame->eax, frame->ebx, frame->ecx, frame->edx); + dprintf(" esi 0x%-9x edi 0x%-9x ebp 0x%-9x esp 0x%x\n", + frame->esi, frame->edi, frame->ebp, frame->esp); dprintf(" eip 0x%-9x eflags 0x%-9x", frame->eip, frame->flags); if ((frame->error_code & 0x4) != 0) { // from user space @@ -136,7 +148,7 @@ dbg_stack_trace(int argc, char **argv) int -arch_dbg_init(kernel_args *ka) +arch_dbg_init(kernel_args *args) { // at this stage, the debugger command system is alive diff --git a/src/kernel/core/arch/x86/arch_int.c b/src/kernel/core/arch/x86/arch_int.c index 8ff94b14ba..6459d22bdf 100644 --- a/src/kernel/core/arch/x86/arch_int.c +++ b/src/kernel/core/arch/x86/arch_int.c @@ -56,6 +56,8 @@ typedef struct { } desc_table; static desc_table *idt = NULL; +struct iframe_stack gBootFrameStack; + static void interrupt_ack(int n) @@ -191,7 +193,9 @@ i386_handle_trap(struct iframe frame) int ret = B_HANDLED_INTERRUPT; if (thread) - i386_push_iframe(thread, &frame); + x86_push_iframe(&thread->arch_info.iframes, &frame); + else + x86_push_iframe(&gBootFrameStack, &frame); if (frame.cs == USER_CODE_SEG) { i386_exit_user_debug_at_kernel_entry(); @@ -307,7 +311,9 @@ i386_handle_trap(struct iframe frame) // dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu()); if (thread) - i386_pop_iframe(thread); + x86_pop_iframe(&thread->arch_info.iframes); + else + x86_pop_iframe(&gBootFrameStack); } diff --git a/src/kernel/core/arch/x86/arch_thread.c b/src/kernel/core/arch/x86/arch_thread.c index 92a36797d3..6f0f8268f6 100644 --- a/src/kernel/core/arch/x86/arch_thread.c +++ b/src/kernel/core/arch/x86/arch_thread.c @@ -58,18 +58,18 @@ arch_thread_init(struct kernel_args *args) void -i386_push_iframe(struct thread *thread, struct iframe *frame) +x86_push_iframe(struct iframe_stack *stack, struct iframe *frame) { - ASSERT(thread->arch_info.iframe_ptr < IFRAME_TRACE_DEPTH); - thread->arch_info.iframes[thread->arch_info.iframe_ptr++] = frame; + ASSERT(stack->index < IFRAME_TRACE_DEPTH); + stack->frames[stack->index++] = frame; } void -i386_pop_iframe(struct thread *thread) +x86_pop_iframe(struct iframe_stack *stack) { - ASSERT(thread->arch_info.iframe_ptr > 0); - thread->arch_info.iframe_ptr--; + ASSERT(stack->index > 0); + stack->index--; } @@ -84,8 +84,8 @@ i386_get_current_iframe(void) { struct thread *thread = thread_get_current_thread(); - ASSERT(thread->arch_info.iframe_ptr >= 0); - return thread->arch_info.iframes[thread->arch_info.iframe_ptr - 1]; + ASSERT(thread->arch_info.iframes.index >= 0); + return thread->arch_info.iframes.frames[thread->arch_info.iframes.index - 1]; } @@ -95,15 +95,16 @@ i386_get_current_iframe(void) * \return The iframe, or \c NULL, if there is no such iframe (e.g. when * the thread is a kernel thread). */ + struct iframe * i386_get_user_iframe(void) { struct thread *thread = thread_get_current_thread(); int i; - for (i = thread->arch_info.iframe_ptr - 1; i >= 0; i--) { - struct iframe *frame = thread->arch_info.iframes[i]; - if (frame->cs == USER_CODE_SEG) + for (i = thread->arch_info.iframes.index - 1; i >= 0; i--) { + struct iframe *frame = thread->arch_info.iframes.frames[i]; + if (frame->cs == USER_CODE_SEG) return frame; }