x86: implement hw-based oops for both variants
We use a fixed value of 32 as the way interrupts/exceptions are setup in x86_64's locore.S do not lend themselves to Kconfig configuration of the vector to use. HW-based kernel oops is now permanently on, there's no reason to make it optional that I can see. Default vectors for IPI and irq offload adjusted to not collide. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
708d5f7922
commit
077b587447
14 changed files with 63 additions and 50 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
#include <generated_dts_board.h>
|
||||
|
||||
/* 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 <sys/sys_io.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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue