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
This commit is contained in:
Axel Dörfler
2005-04-04 14:13:25 +00:00
parent edb5566393
commit 9d06770cdc
5 changed files with 79 additions and 55 deletions
+12 -11
View File
@@ -1,22 +1,23 @@
/* /*
** Copyright 2002-2004, The Haiku Team. All rights reserved. * Copyright 2002-2005, The Haiku Team. All rights reserved.
** Distributed under the terms of the Haiku License. * Distributed under the terms of the MIT License.
** *
** Copyright 2002, Travis Geiselbrecht. All rights reserved. * Copyright 2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License. * Distributed under the terms of the NewOS License.
*/ */
#ifndef _KERNEL_ARCH_x86_THREAD_H #ifndef _KERNEL_ARCH_x86_THREAD_H
#define _KERNEL_ARCH_x86_THREAD_H #define _KERNEL_ARCH_x86_THREAD_H
#include <arch/cpu.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <arch/cpu.h> void x86_push_iframe(struct iframe_stack *stack, struct iframe *frame);
void x86_pop_iframe(struct iframe_stack *stack);
void i386_push_iframe(struct thread *t, struct iframe *frame);
void i386_pop_iframe(struct thread *t);
struct iframe *i386_get_user_iframe(void); struct iframe *i386_get_user_iframe(void);
void i386_return_from_signal(); void i386_return_from_signal();
@@ -1,10 +1,10 @@
/* /*
** Copyright 2002-2004, The Haiku Team. All rights reserved. * Copyright 2002-2005, The Haiku Team. All rights reserved.
** Distributed under the terms of the Haiku License. * Distributed under the terms of the MIT License.
** *
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License. * Distributed under the terms of the NewOS License.
*/ */
#ifndef _KERNEL_ARCH_x86_THREAD_STRUCT_H #ifndef _KERNEL_ARCH_x86_THREAD_STRUCT_H
#define _KERNEL_ARCH_x86_THREAD_STRUCT_H #define _KERNEL_ARCH_x86_THREAD_STRUCT_H
@@ -19,14 +19,18 @@ struct farcall {
#define IFRAME_TRACE_DEPTH 4 #define IFRAME_TRACE_DEPTH 4
struct iframe_stack {
struct iframe *frames[IFRAME_TRACE_DEPTH];
int32 index;
};
// architecture specific thread info // architecture specific thread info
struct arch_thread { struct arch_thread {
struct farcall current_stack; struct farcall current_stack;
struct farcall interrupt_stack; struct farcall interrupt_stack;
// used to track interrupts on this thread // used to track interrupts on this thread
struct iframe *iframes[IFRAME_TRACE_DEPTH]; struct iframe_stack iframes;
int iframe_ptr;
// 512 byte floating point save point // 512 byte floating point save point
uint8 fpu_state[512]; uint8 fpu_state[512];
+35 -23
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2004, Axel Dörfler, [email protected]. * Copyright 2002-2005, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001, Travis Geiselbrecht. All rights reserved. * Copyright 2001, Travis Geiselbrecht. All rights reserved.
@@ -11,13 +11,15 @@
#include <debug.h> #include <debug.h>
#include <thread.h> #include <thread.h>
#include <elf.h> #include <elf.h>
#include <arch/debug.h>
#include <arch/debug.h>
#include <arch_cpu.h> #include <arch_cpu.h>
#define NUM_PREVIOUS_LOCATIONS 16 #define NUM_PREVIOUS_LOCATIONS 16
extern struct iframe_stack gBootFrameStack;
static bool static bool
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp)
@@ -45,50 +47,60 @@ static int
dbg_stack_trace(int argc, char **argv) dbg_stack_trace(int argc, char **argv)
{ {
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
struct thread *t; struct iframe_stack *frameStack;
struct thread *thread;
uint32 ebp; uint32 ebp;
int32 i, num = 0, last = 0; int32 i, num = 0, last = 0;
if (argc < 2) if (argc < 2) {
t = thread_get_current_thread(); thread = thread_get_current_thread();
else { if (thread != NULL)
frameStack = &thread->arch_info.iframes;
else
frameStack = &gBootFrameStack;
} else {
dprintf("not supported\n"); dprintf("not supported\n");
return 0; return 0;
} }
for (i = 0; i < t->arch_info.iframe_ptr; i++) { for (i = 0; i < frameStack->index; i++) {
char *temp = (char *)t->arch_info.iframes[i]; dprintf("iframe %p (end = %p)\n",
dprintf("iframe %p %p %p\n", temp, temp + sizeof(struct iframe), temp + sizeof(struct iframe) - 8); 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", dprintf(" kernel stack: %p to %p\n",
(void *)t->kernel_stack_base, (void *)(t->kernel_stack_base + KERNEL_STACK_SIZE)); (void *)thread->kernel_stack_base, (void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE));
if (t->user_stack_base != 0) { if (thread->user_stack_base != 0) {
dprintf(" user stack: %p to %p\n", (void *)t->user_stack_base, dprintf(" user stack: %p to %p\n", (void *)thread->user_stack_base,
(void *)(t->user_stack_base + t->user_stack_size)); (void *)(thread->user_stack_base + thread->user_stack_size));
}
} }
dprintf("frame caller <image>:function + offset\n"); dprintf("frame caller <image>:function + offset\n");
read_ebp(ebp); read_ebp(ebp);
for (;;) { for (;;) {
bool is_iframe = false; bool isIFrame = false;
// see if the ebp matches the iframe // see if the ebp matches the iframe
for (i = 0; i < t->arch_info.iframe_ptr; i++) { for (i = 0; i < frameStack->index; i++) {
if (ebp == ((uint32)t->arch_info.iframes[i] - 8)) { if (ebp == ((uint32)frameStack->frames[i] - 8)) {
// it's an iframe // it's an iframe
is_iframe = true; isIFrame = true;
} }
} }
if (is_iframe) { if (isIFrame) {
struct iframe *frame = (struct iframe *)(ebp + 8); struct iframe *frame = (struct iframe *)(ebp + 8);
dprintf("iframe at %p\n", frame); 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(" eax 0x%-9x ebx 0x%-9x ecx 0x%-9x edx 0x%x\n",
dprintf(" esi 0x%-9x edi 0x%-9x ebp 0x%-9x esp 0x%x\n", frame->esi, frame->edi, frame->ebp, frame->esp); 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); dprintf(" eip 0x%-9x eflags 0x%-9x", frame->eip, frame->flags);
if ((frame->error_code & 0x4) != 0) { if ((frame->error_code & 0x4) != 0) {
// from user space // from user space
@@ -136,7 +148,7 @@ dbg_stack_trace(int argc, char **argv)
int int
arch_dbg_init(kernel_args *ka) arch_dbg_init(kernel_args *args)
{ {
// at this stage, the debugger command system is alive // at this stage, the debugger command system is alive
+8 -2
View File
@@ -56,6 +56,8 @@ typedef struct {
} desc_table; } desc_table;
static desc_table *idt = NULL; static desc_table *idt = NULL;
struct iframe_stack gBootFrameStack;
static void static void
interrupt_ack(int n) interrupt_ack(int n)
@@ -191,7 +193,9 @@ i386_handle_trap(struct iframe frame)
int ret = B_HANDLED_INTERRUPT; int ret = B_HANDLED_INTERRUPT;
if (thread) 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) { if (frame.cs == USER_CODE_SEG) {
i386_exit_user_debug_at_kernel_entry(); 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()); // dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu());
if (thread) if (thread)
i386_pop_iframe(thread); x86_pop_iframe(&thread->arch_info.iframes);
else
x86_pop_iframe(&gBootFrameStack);
} }
+11 -10
View File
@@ -58,18 +58,18 @@ arch_thread_init(struct kernel_args *args)
void 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); ASSERT(stack->index < IFRAME_TRACE_DEPTH);
thread->arch_info.iframes[thread->arch_info.iframe_ptr++] = frame; stack->frames[stack->index++] = frame;
} }
void void
i386_pop_iframe(struct thread *thread) x86_pop_iframe(struct iframe_stack *stack)
{ {
ASSERT(thread->arch_info.iframe_ptr > 0); ASSERT(stack->index > 0);
thread->arch_info.iframe_ptr--; stack->index--;
} }
@@ -84,8 +84,8 @@ i386_get_current_iframe(void)
{ {
struct thread *thread = thread_get_current_thread(); struct thread *thread = thread_get_current_thread();
ASSERT(thread->arch_info.iframe_ptr >= 0); ASSERT(thread->arch_info.iframes.index >= 0);
return thread->arch_info.iframes[thread->arch_info.iframe_ptr - 1]; return thread->arch_info.iframes.frames[thread->arch_info.iframes.index - 1];
} }
@@ -95,14 +95,15 @@ i386_get_current_iframe(void)
* \return The iframe, or \c NULL, if there is no such iframe (e.g. when * \return The iframe, or \c NULL, if there is no such iframe (e.g. when
* the thread is a kernel thread). * the thread is a kernel thread).
*/ */
struct iframe * struct iframe *
i386_get_user_iframe(void) i386_get_user_iframe(void)
{ {
struct thread *thread = thread_get_current_thread(); struct thread *thread = thread_get_current_thread();
int i; int i;
for (i = thread->arch_info.iframe_ptr - 1; i >= 0; i--) { for (i = thread->arch_info.iframes.index - 1; i >= 0; i--) {
struct iframe *frame = thread->arch_info.iframes[i]; struct iframe *frame = thread->arch_info.iframes.frames[i];
if (frame->cs == USER_CODE_SEG) if (frame->cs == USER_CODE_SEG)
return frame; return frame;
} }