x86: page-aligned stacks with guard page
Subsequent patches will set this guard page as unmapped, triggering a page fault on access. If this is due to stack overflow, a double fault will be triggered, which we are now capable of handling with a switch to a know good stack. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
befb0695ba
commit
0fab8a6dc5
4 changed files with 35 additions and 14 deletions
|
@ -204,6 +204,9 @@ void _new_thread(struct k_thread *thread, char *pStackMem, size_t stackSize,
|
||||||
|
|
||||||
unsigned long *pInitialThread;
|
unsigned long *pInitialThread;
|
||||||
|
|
||||||
|
#if _STACK_GUARD_SIZE
|
||||||
|
pStackMem += _STACK_GUARD_SIZE;
|
||||||
|
#endif
|
||||||
_new_thread_init(thread, pStackMem, stackSize, priority, options);
|
_new_thread_init(thread, pStackMem, stackSize, priority, options);
|
||||||
|
|
||||||
/* carve the thread entry struct from the "base" of the stack */
|
/* carve the thread entry struct from the "base" of the stack */
|
||||||
|
|
|
@ -20,6 +20,8 @@ extern "C" {
|
||||||
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
||||||
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
||||||
|
|
||||||
|
extern K_THREAD_STACK_DEFINE(_interrupt_stack, CONFIG_ISR_STACK_SIZE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Performs architecture-specific initialization
|
* @brief Performs architecture-specific initialization
|
||||||
|
@ -32,10 +34,9 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
static inline void kernel_arch_init(void)
|
static inline void kernel_arch_init(void)
|
||||||
{
|
{
|
||||||
extern char _interrupt_stack[CONFIG_ISR_STACK_SIZE];
|
|
||||||
|
|
||||||
_kernel.nested = 0;
|
_kernel.nested = 0;
|
||||||
_kernel.irq_stack = _interrupt_stack + CONFIG_ISR_STACK_SIZE;
|
_kernel.irq_stack = K_THREAD_STACK_BUFFER(_interrupt_stack) +
|
||||||
|
CONFIG_ISR_STACK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <arch/x86/irq_controller.h>
|
#include <arch/x86/irq_controller.h>
|
||||||
#include <kernel_arch_thread.h>
|
#include <kernel_arch_thread.h>
|
||||||
#include <generated_dts_board.h>
|
#include <generated_dts_board.h>
|
||||||
|
#include <mmustructs.h>
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE
|
#ifndef _ASMLANGUAGE
|
||||||
#include <arch/x86/asm_inline.h>
|
#include <arch/x86/asm_inline.h>
|
||||||
|
@ -530,25 +531,38 @@ extern FUNC_NORETURN void _SysFatalErrorHandler(unsigned int reason,
|
||||||
const NANO_ESF * pEsf);
|
const NANO_ESF * pEsf);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_STACK_PROTECTION
|
||||||
|
#define _STACK_GUARD_SIZE MMU_PAGE_SIZE
|
||||||
|
#define _STACK_BASE_ALIGN MMU_PAGE_SIZE
|
||||||
|
#else
|
||||||
|
#define _STACK_GUARD_SIZE 0
|
||||||
|
#define _STACK_BASE_ALIGN STACK_ALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* All thread stacks, regardless of whether owned by application or kernel,
|
/* All thread stacks, regardless of whether owned by application or kernel,
|
||||||
* go in the .stacks input section, which will end up in the kernel's
|
* go in the .stacks input section, which will end up in the kernel's
|
||||||
* noinit.
|
* noinit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _ARCH_THREAD_STACK_DEFINE(sym, size) \
|
#define _ARCH_THREAD_STACK_DEFINE(sym, size) \
|
||||||
char _GENERIC_SECTION(.stacks) __aligned(STACK_ALIGN) sym[size]
|
char _GENERIC_SECTION(.stacks) __aligned(_STACK_BASE_ALIGN) \
|
||||||
|
sym[size + _STACK_GUARD_SIZE]
|
||||||
|
|
||||||
#define _ARCH_THREAD_STACK_ARRAY_DEFINE(sym, nmemb, size) \
|
#define _ARCH_THREAD_STACK_ARRAY_DEFINE(sym, nmemb, size) \
|
||||||
char _GENERIC_SECTION(.stacks) __aligned(STACK_ALIGN) sym[nmemb][size]
|
char _GENERIC_SECTION(.stacks) __aligned(_STACK_BASE_ALIGN) \
|
||||||
|
sym[nmemb][ROUND_UP(size, _STACK_BASE_ALIGN) + \
|
||||||
|
_STACK_GUARD_SIZE]
|
||||||
|
|
||||||
#define _ARCH_THREAD_STACK_MEMBER(sym, size) \
|
#define _ARCH_THREAD_STACK_MEMBER(sym, size) \
|
||||||
char __aligned(STACK_ALIGN) sym[size]
|
char __aligned(_STACK_BASE_ALIGN) sym[size + _STACK_GUARD_SIZE]
|
||||||
|
|
||||||
#define _ARCH_THREAD_STACK_SIZEOF(sym) \
|
#define _ARCH_THREAD_STACK_SIZEOF(sym) \
|
||||||
sizeof(sym)
|
(sizeof(sym) - _STACK_GUARD_SIZE)
|
||||||
|
|
||||||
#define _ARCH_THREAD_STACK_BUFFER(sym) \
|
#define _ARCH_THREAD_STACK_BUFFER(sym) \
|
||||||
sym
|
(sym + _STACK_GUARD_SIZE)
|
||||||
|
|
||||||
#if CONFIG_X86_KERNEL_OOPS
|
#if CONFIG_X86_KERNEL_OOPS
|
||||||
#define _ARCH_EXCEPT(reason_p) do { \
|
#define _ARCH_EXCEPT(reason_p) do { \
|
||||||
|
|
|
@ -121,14 +121,16 @@ K_THREAD_STACK_DEFINE(_interrupt_stack, CONFIG_ISR_STACK_SIZE);
|
||||||
|
|
||||||
extern void idle(void *unused1, void *unused2, void *unused3);
|
extern void idle(void *unused1, void *unused2, void *unused3);
|
||||||
|
|
||||||
void k_call_stacks_analyze(void)
|
|
||||||
{
|
|
||||||
#if defined(CONFIG_INIT_STACKS) && defined(CONFIG_PRINTK)
|
#if defined(CONFIG_INIT_STACKS) && defined(CONFIG_PRINTK)
|
||||||
extern char sys_work_q_stack[CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE];
|
extern K_THREAD_STACK_DEFINE(sys_work_q_stack,
|
||||||
|
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE);
|
||||||
#if defined(CONFIG_ARC) && CONFIG_RGF_NUM_BANKS != 1
|
#if defined(CONFIG_ARC) && CONFIG_RGF_NUM_BANKS != 1
|
||||||
extern char _firq_stack[CONFIG_FIRQ_STACK_SIZE];
|
extern K_THREAD_STACK_DEFINE(_firq_stack, CONFIG_FIRQ_STACK_SIZE);
|
||||||
#endif /* CONFIG_ARC */
|
#endif /* CONFIG_ARC */
|
||||||
|
|
||||||
|
|
||||||
|
void k_call_stacks_analyze(void)
|
||||||
|
{
|
||||||
printk("Kernel stacks:\n");
|
printk("Kernel stacks:\n");
|
||||||
STACK_ANALYZE("main ", _main_stack);
|
STACK_ANALYZE("main ", _main_stack);
|
||||||
STACK_ANALYZE("idle ", _idle_stack);
|
STACK_ANALYZE("idle ", _idle_stack);
|
||||||
|
@ -137,9 +139,10 @@ void k_call_stacks_analyze(void)
|
||||||
#endif /* CONFIG_ARC */
|
#endif /* CONFIG_ARC */
|
||||||
STACK_ANALYZE("interrupt", _interrupt_stack);
|
STACK_ANALYZE("interrupt", _interrupt_stack);
|
||||||
STACK_ANALYZE("workqueue", sys_work_q_stack);
|
STACK_ANALYZE("workqueue", sys_work_q_stack);
|
||||||
|
|
||||||
#endif /* CONFIG_INIT_STACKS && CONFIG_PRINTK */
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void k_call_stacks_analyze(void) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue