diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 38e1c272d57..a33d3ca2f33 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -58,7 +58,7 @@ config MAX_IRQ_LINES config IRQ_OFFLOAD_VECTOR int "IDT vector to use for IRQ offload" - default 32 + default 33 range 32 255 depends on IRQ_OFFLOAD diff --git a/arch/x86/core/Kconfig.ia32 b/arch/x86/core/Kconfig.ia32 index ecd6ce45301..221f9fa68ae 100644 --- a/arch/x86/core/Kconfig.ia32 +++ b/arch/x86/core/Kconfig.ia32 @@ -197,22 +197,6 @@ config CACHE_FLUSHING cache must be selected as well. By default, that mechanism is discovered at runtime. -config X86_KERNEL_OOPS - bool "Enable handling of kernel oops as an exception" - default y - help - Enable handling of k_oops() API as a CPU exception, which will provide - extra debugging information such as program counter and register - values when the oops is triggered. Requires an entry in the IDT. - -config X86_KERNEL_OOPS_VECTOR - int "IDT vector to use for kernel oops" - default 33 - range 32 255 - depends on X86_KERNEL_OOPS - help - Specify the IDT vector to use for the kernel oops exception handler. - config X86_DYNAMIC_IRQ_STUBS int "Number of dynamic interrupt stubs" depends on DYNAMIC_INTERRUPTS diff --git a/arch/x86/core/Kconfig.intel64 b/arch/x86/core/Kconfig.intel64 index 51ae7a31cb6..44755bfed59 100644 --- a/arch/x86/core/Kconfig.intel64 +++ b/arch/x86/core/Kconfig.intel64 @@ -42,7 +42,7 @@ config X86_EXCEPTION_STACK_TRACE config SCHED_IPI_VECTOR int "IDT vector to use for scheduler IPI" - default 33 + default 34 range 33 255 depends on SMP diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index ae521d185f6..a1217ddbfc4 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -342,3 +342,28 @@ void z_x86_page_fault_handler(z_arch_esf_t *esf) z_x86_fatal_error(K_ERR_CPU_EXCEPTION, esf); CODE_UNREACHABLE; } + +void z_x86_do_kernel_oops(const z_arch_esf_t *esf) +{ + uintptr_t reason; + +#ifdef CONFIG_X86_64 + reason = esf->rax; +#else + uintptr_t *stack_ptr = (uintptr_t *)esf->esp; + + reason = *stack_ptr; +#endif + +#ifdef CONFIG_USERSPACE + /* User mode is only allowed to induce oopses and stack check + * failures via this software interrupt + */ + if ((esf->cs & 0x3) != 0 && !(reason == K_ERR_KERNEL_OOPS || + reason == K_ERR_STACK_CHK_FAIL)) { + reason = K_ERR_KERNEL_OOPS; + } +#endif + + z_x86_fatal_error(reason, esf); +} diff --git a/arch/x86/core/ia32/excstub.S b/arch/x86/core/ia32/excstub.S index 4082abc4795..4ecea506871 100644 --- a/arch/x86/core/ia32/excstub.S +++ b/arch/x86/core/ia32/excstub.S @@ -25,7 +25,7 @@ GTEXT(_kernel_oops_handler) /* externs (internal APIs) */ - GTEXT(z_do_kernel_oops) + GTEXT(z_x86_do_kernel_oops) /** * @@ -219,9 +219,7 @@ nestedException: /* Pop of EFLAGS will re-enable interrupts and restore direction flag */ KPTI_IRET -#if CONFIG_X86_KERNEL_OOPS SECTION_FUNC(TEXT, _kernel_oops_handler) push $0 /* dummy error code */ - push $z_do_kernel_oops + push $z_x86_do_kernel_oops jmp _exception_enter -#endif diff --git a/arch/x86/core/ia32/fatal.c b/arch/x86/core/ia32/fatal.c index c05f6647cdf..0d4fdbace0c 100644 --- a/arch/x86/core/ia32/fatal.c +++ b/arch/x86/core/ia32/fatal.c @@ -50,30 +50,9 @@ void arch_syscall_oops(void *ssf_ptr) z_x86_fatal_error(K_ERR_KERNEL_OOPS, &oops); } -#ifdef CONFIG_X86_KERNEL_OOPS -void z_do_kernel_oops(const z_arch_esf_t *esf) -{ - u32_t *stack_ptr = (u32_t *)esf->esp; - u32_t reason = *stack_ptr; - -#ifdef CONFIG_USERSPACE - /* User mode is only allowed to induce oopses and stack check - * failures via this software interrupt - */ - if (esf->cs == USER_CODE_SEG && !(reason == K_ERR_KERNEL_OOPS || - reason == K_ERR_STACK_CHK_FAIL)) { - reason = K_ERR_KERNEL_OOPS; - } -#endif - - z_x86_fatal_error(reason, esf); -} - extern void (*_kernel_oops_handler)(void); NANO_CPU_INT_REGISTER(_kernel_oops_handler, NANO_SOFT_IRQ, - CONFIG_X86_KERNEL_OOPS_VECTOR / 16, - CONFIG_X86_KERNEL_OOPS_VECTOR, 3); -#endif + Z_X86_OOPS_VECTOR / 16, Z_X86_OOPS_VECTOR, 3); #if CONFIG_EXCEPTION_DEBUG FUNC_NORETURN static void generic_exc_handle(unsigned int vector, diff --git a/arch/x86/core/intel64/fatal.c b/arch/x86/core/intel64/fatal.c index 2f355e9afc0..7310b979edc 100644 --- a/arch/x86/core/intel64/fatal.c +++ b/arch/x86/core/intel64/fatal.c @@ -13,6 +13,9 @@ LOG_MODULE_DECLARE(os); void z_x86_exception(z_arch_esf_t *esf) { switch (esf->vector) { + case Z_X86_OOPS_VECTOR: + z_x86_do_kernel_oops(esf); + break; case IV_PAGE_FAULT: z_x86_page_fault_handler(esf); break; diff --git a/arch/x86/core/intel64/irq.c b/arch/x86/core/intel64/irq.c index dd01d9cffec..9077906542a 100644 --- a/arch/x86/core/intel64/irq.c +++ b/arch/x86/core/intel64/irq.c @@ -52,6 +52,9 @@ static int allocate_vector(unsigned int priority) continue; } #endif + if (vector == Z_X86_OOPS_VECTOR) { + continue; + } if (x86_irq_funcs[vector - IV_IRQS] == NULL) { return vector; } diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index b9eb640e752..3df456f048a 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -334,6 +334,11 @@ EXCEPT (20); EXCEPT (21); EXCEPT (22); EXCEPT (23) EXCEPT (24); EXCEPT (25); EXCEPT (26); EXCEPT (27) EXCEPT (28); EXCEPT (29); EXCEPT (30); EXCEPT (31) +/* Vector reserved for handling a kernel oops; treat as an exception + * and not an interrupt + */ +EXCEPT(Z_X86_OOPS_VECTOR); + /* * When we arrive at 'irq' from one of the IRQ(X) stubs, * we're on the "freshest" IRQ stack and it contains: @@ -467,7 +472,7 @@ irq_exit_nested: #define IRQ(nr) vector_ ## nr: pushq $(nr - IV_IRQS); jmp irq -IRQ( 32); IRQ( 33); IRQ( 34); IRQ( 35); IRQ( 36); IRQ( 37); IRQ( 38); IRQ( 39) +IRQ( 33); IRQ( 34); IRQ( 35); IRQ( 36); IRQ( 37); IRQ( 38); IRQ( 39) IRQ( 40); IRQ( 41); IRQ( 42); IRQ( 43); IRQ( 44); IRQ( 45); IRQ( 46); IRQ( 47) IRQ( 48); IRQ( 49); IRQ( 50); IRQ( 51); IRQ( 52); IRQ( 53); IRQ( 54); IRQ( 55) IRQ( 56); IRQ( 57); IRQ( 58); IRQ( 59); IRQ( 60); IRQ( 61); IRQ( 62); IRQ( 63) @@ -504,6 +509,7 @@ IRQ(248); IRQ(249); IRQ(250); IRQ(251); IRQ(252); IRQ(253); IRQ(254); IRQ(255) #define TRAP 0x8f #define INTR 0x8e +#define USER_INTR 0xee #define IDT(nr, type, ist) \ .word vector_ ## nr, X86_KERNEL_CS; \ @@ -521,7 +527,9 @@ idt: IDT( 24, TRAP, 7); IDT( 25, TRAP, 7); IDT( 26, TRAP, 7); IDT( 27, TRAP, 7) IDT( 28, TRAP, 7); IDT( 29, TRAP, 7); IDT( 30, TRAP, 7); IDT( 31, TRAP, 7) - IDT( 32, INTR, 1); IDT( 33, INTR, 1); IDT( 34, INTR, 1); IDT( 35, INTR, 1) + /* Oops vector can be invoked from Ring 3 and runs on exception stack */ + IDT(Z_X86_OOPS_VECTOR, USER_INTR, 7); + IDT( 33, INTR, 1); IDT( 34, INTR, 1); IDT( 35, INTR, 1) IDT( 36, INTR, 1); IDT( 37, INTR, 1); IDT( 38, INTR, 1); IDT( 39, INTR, 1) IDT( 40, INTR, 1); IDT( 41, INTR, 1); IDT( 42, INTR, 1); IDT( 43, INTR, 1) IDT( 44, INTR, 1); IDT( 45, INTR, 1); IDT( 46, INTR, 1); IDT( 47, INTR, 1) diff --git a/arch/x86/include/kernel_arch_func.h b/arch/x86/include/kernel_arch_func.h index 7a702d91a6d..3191e79d298 100644 --- a/arch/x86/include/kernel_arch_func.h +++ b/arch/x86/include/kernel_arch_func.h @@ -108,6 +108,8 @@ void z_x86_apply_mem_domain(struct x86_page_tables *ptables, #endif /* CONFIG_USERSPACE */ +void z_x86_do_kernel_oops(const z_arch_esf_t *esf); + #endif /* !_ASMLANGUAGE */ #endif /* ZEPHYR_ARCH_X86_INCLUDE_KERNEL_ARCH_FUNC_H_ */ diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index 57ae8875af2..7d4e6d5cc9f 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -8,6 +8,11 @@ #include +/* Changing this value will require manual changes to exception and IDT setup + * in locore.S for intel64 + */ +#define Z_X86_OOPS_VECTOR 32 + #if !defined(_ASMLANGUAGE) #include diff --git a/include/arch/x86/ia32/arch.h b/include/arch/x86/ia32/arch.h index c5caf07cac4..f200396125f 100644 --- a/include/arch/x86/ia32/arch.h +++ b/include/arch/x86/ia32/arch.h @@ -410,17 +410,15 @@ extern void k_float_enable(struct k_thread *thread, unsigned int options); extern struct task_state_segment _main_tss; #endif -#if CONFIG_X86_KERNEL_OOPS #define ARCH_EXCEPT(reason_p) do { \ __asm__ volatile( \ "push %[reason]\n\t" \ "int %[vector]\n\t" \ : \ - : [vector] "i" (CONFIG_X86_KERNEL_OOPS_VECTOR), \ + : [vector] "i" (Z_X86_OOPS_VECTOR), \ [reason] "i" (reason_p)); \ CODE_UNREACHABLE; \ } while (false) -#endif #ifdef __cplusplus } diff --git a/include/arch/x86/intel64/arch.h b/include/arch/x86/intel64/arch.h index 6630700609c..78e23d6fefa 100644 --- a/include/arch/x86/intel64/arch.h +++ b/include/arch/x86/intel64/arch.h @@ -59,6 +59,15 @@ struct x86_esf { typedef struct x86_esf z_arch_esf_t; +#define ARCH_EXCEPT(reason_p) do { \ + __asm__ volatile( \ + "movq %[reason], %%rax\n\t" \ + "int $32\n\t" \ + : \ + : [reason] "i" (reason_p)); \ + CODE_UNREACHABLE; \ +} while (false) + #endif /* _ASMLANGUAGE */ /* diff --git a/tests/drivers/build_all/drivers.conf b/tests/drivers/build_all/drivers.conf index 2e271d7c005..f0e1e2ad9a6 100644 --- a/tests/drivers/build_all/drivers.conf +++ b/tests/drivers/build_all/drivers.conf @@ -10,5 +10,4 @@ CONFIG_PWM=y CONFIG_SERIAL=y CONFIG_SPI=y CONFIG_WATCHDOG=y -CONFIG_X86_KERNEL_OOPS=n CONFIG_TEST_USERSPACE=y