diff --git a/arch/x64/arch-cpu.cc b/arch/x64/arch-cpu.cc index 2d5c916bdd41479007ed0c40287f9adf24bb9aed..2f4601b175f0b7a29c22133df86f9b133864f6e6 100644 --- a/arch/x64/arch-cpu.cc +++ b/arch/x64/arch-cpu.cc @@ -11,22 +11,25 @@ namespace sched { -__thread bool in_exception = false; +__thread unsigned exception_depth = 0; inline void arch_cpu::enter_exception() { - if (in_exception) { - abort("nested exception"); + if (exception_depth == nr_exception_stacks - 1) { + abort("exception nested too deeply"); } - in_exception = true; - auto& s = percpu_exception_stack; + auto& s = percpu_exception_stack[exception_depth++]; set_exception_stack(s, sizeof(s)); } inline void arch_cpu::exit_exception() { - set_exception_stack(&thread::current()->_arch); - in_exception = false; + if (--exception_depth == 0) { + set_exception_stack(&thread::current()->_arch); + } else { + auto& s = percpu_exception_stack[exception_depth]; + set_exception_stack(s, sizeof(s)); + } } exception_guard::exception_guard() diff --git a/arch/x64/arch-cpu.hh b/arch/x64/arch-cpu.hh index c33813eef55378ebf862d536740ddb7a8551aed3..644bfcca1c5d5dd2b41fe32c6044343b91cb9aef 100644 --- a/arch/x64/arch-cpu.hh +++ b/arch/x64/arch-cpu.hh @@ -41,7 +41,8 @@ struct arch_cpu { processor::aligned_task_state_segment atss; init_stack initstack; // The per-CPU exception stack is used for nested exceptions. - char percpu_exception_stack[4096] __attribute__((aligned(16))); + static constexpr unsigned nr_exception_stacks = 2; + char percpu_exception_stack[nr_exception_stacks][4096] __attribute__((aligned(16))); u32 apic_id; u32 acpi_id; u64 gdt[nr_gdt]; @@ -94,7 +95,7 @@ inline arch_cpu::arch_cpu() gdt[gdt_tss] |= (tss_addr & 0xff000000) << 32; gdt[gdt_tssx] = tss_addr >> 32; // Use the per-CPU stack for early boot faults. - set_exception_stack(percpu_exception_stack, sizeof(percpu_exception_stack)); + set_exception_stack(percpu_exception_stack[0], sizeof(percpu_exception_stack[0])); } inline void arch_cpu::set_ist_entry(unsigned ist, char* base, size_t size)