From cc77aba1013a9d850fdf17c5a4338c3ad65c98b7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 31 Jul 2009 16:14:18 +0000 Subject: [PATCH] * Allocate a separate double fault stack for each CPU. * Added x86_double_fault_get_cpu(), a save way to get the CPU index when in the double fault handler. smp_get_current_cpu() requires at least a somewhat intact thread structure, so we rather want to avoid it when handling a double fault. There are a lot more of those dependencies in the KDL entry code. Working on it... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32028 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_cpu.h | 1 + src/system/kernel/arch/x86/arch_cpu.cpp | 28 +++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 5b34644279..f65b9b59b7 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -281,6 +281,7 @@ void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); status_t x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type); bool x86_check_feature(uint32 feature, enum x86_feature_type type); void* x86_get_double_fault_stack(int32 cpu, size_t* _size); +int x86_double_fault_get_cpu(); #define read_cr3(value) \ diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 83d50b7f85..ca18cb683a 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -83,8 +83,8 @@ static vint32 sTSCSyncRendezvous; segment_descriptor *gGDT = NULL; /* Some specials for the double fault handler */ -//static struct tss sDoubleFaultTSS; -static uint32 sDoubleFaultStack[10240]; +static uint8* sDoubleFaultStacks; +static const size_t kDoubleFaultStackSize = 4096; // size per CPU static x86_cpu_module_info *sCpuModule; @@ -251,7 +251,9 @@ init_double_fault(int cpuNum) struct tss *tss = &gCPU[cpuNum].arch.double_fault_tss; memset(tss, 0, sizeof(struct tss)); - tss->sp0 = (uint32)sDoubleFaultStack + sizeof(sDoubleFaultStack); + size_t stackSize; + tss->sp0 = (uint32)x86_get_double_fault_stack(cpuNum, &stackSize); + tss->sp0 += stackSize; tss->ss0 = KERNEL_DATA_SEG; read_cr3(tss->cr3); // copy the current cr3 to the double fault cr3 @@ -501,8 +503,19 @@ x86_check_feature(uint32 feature, enum x86_feature_type type) void* x86_get_double_fault_stack(int32 cpu, size_t* _size) { - *_size = sizeof(sDoubleFaultStack); - return sDoubleFaultStack; + *_size = kDoubleFaultStackSize; + return sDoubleFaultStacks + kDoubleFaultStackSize * cpu; +} + + +/*! Returns the index of the current CPU. Can only be called from the double + fault handler. +*/ +int +x86_double_fault_get_cpu() +{ + uint32 stack = x86_read_ebp(); + return (stack - (uint32)sDoubleFaultStacks) / kDoubleFaultStackSize; } @@ -569,7 +582,6 @@ arch_cpu_init_post_vm(kernel_args *args) uint32 i; // account for the segment descriptors - gGDT = (segment_descriptor *)args->arch_args.vir_gdt; create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); @@ -578,6 +590,10 @@ arch_cpu_init_post_vm(kernel_args *args) // (a fixed number of used GDT entries) //i386_selector_init(gGDT); // pass the new gdt + // allocate an area for the double fault stacks + create_area("double fault stacks", (void**)&sDoubleFaultStacks, + B_ANY_KERNEL_ADDRESS, kDoubleFaultStackSize * smp_get_num_cpus(), + B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); vm_translation_map_arch_info* kernelArchTranslationMap = vm_kernel_address_space()->translation_map.arch_data;