1 /* 2 * Copyright (c) 2019 Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #ifndef ZEPHYR_INCLUDE_ARCH_X86_THREAD_STACK_H 7 #define ZEPHYR_INCLUDE_ARCH_X86_THREAD_STACK_H 8 9 #include <zephyr/arch/x86/mmustructs.h> 10 11 #ifdef CONFIG_X86_64 12 #define ARCH_STACK_PTR_ALIGN 16UL 13 #else 14 #define ARCH_STACK_PTR_ALIGN 4UL 15 #endif 16 17 #if defined(CONFIG_HW_STACK_PROTECTION) || defined(CONFIG_USERSPACE) 18 #define Z_X86_STACK_BASE_ALIGN CONFIG_MMU_PAGE_SIZE 19 #else 20 #define Z_X86_STACK_BASE_ALIGN ARCH_STACK_PTR_ALIGN 21 #endif 22 23 #ifdef CONFIG_USERSPACE 24 /* If user mode enabled, expand any stack size to fill a page since that is 25 * the access control granularity and we don't want other kernel data to 26 * unintentionally fall in the latter part of the page 27 */ 28 #define Z_X86_STACK_SIZE_ALIGN CONFIG_MMU_PAGE_SIZE 29 #else 30 #define Z_X86_STACK_SIZE_ALIGN ARCH_STACK_PTR_ALIGN 31 #endif 32 33 #ifndef _ASMLANGUAGE 34 /* With both hardware stack protection and userspace enabled, stacks are 35 * arranged as follows: 36 * 37 * High memory addresses 38 * +-----------------------------------------+ 39 * | Thread stack (varies) | 40 * +-----------------------------------------+ 41 * | Privilege elevation stack | 42 * | (4096 bytes) | 43 * +-----------------------------------------+ 44 * | Guard page (4096 bytes) | 45 * +-----------------------------------------+ 46 * Low Memory addresses 47 * 48 * Privilege elevation stacks are fixed-size. All the pages containing the 49 * thread stack are marked as user-accessible. The guard page is marked 50 * read-only to catch stack overflows in supervisor mode. 51 * 52 * If a thread starts in supervisor mode, the page containing the 53 * privilege elevation stack is also marked read-only. 54 * 55 * If a thread starts in, or drops down to user mode, the privilege stack page 56 * will be marked as present, supervisor-only. 57 * 58 * If KPTI is not enabled, the _main_tss.esp0 field will always be updated 59 * updated to point to the top of the privilege elevation stack. Otherwise 60 * _main_tss.esp0 always points to the trampoline stack, which handles the 61 * page table switch to the kernel PDPT and transplants context to the 62 * privileged mode stack. 63 */ 64 struct z_x86_thread_stack_header { 65 #ifdef CONFIG_HW_STACK_PROTECTION 66 char guard_page[CONFIG_MMU_PAGE_SIZE]; 67 #endif 68 #ifdef CONFIG_USERSPACE 69 char privilege_stack[CONFIG_MMU_PAGE_SIZE]; 70 #endif /* CONFIG_USERSPACE */ 71 } __packed __aligned(Z_X86_STACK_BASE_ALIGN); 72 73 #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_X86_STACK_BASE_ALIGN 74 75 #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ 76 ROUND_UP((size), Z_X86_STACK_SIZE_ALIGN) 77 78 #define ARCH_THREAD_STACK_RESERVED \ 79 sizeof(struct z_x86_thread_stack_header) 80 81 #ifdef CONFIG_HW_STACK_PROTECTION 82 #define ARCH_KERNEL_STACK_RESERVED CONFIG_MMU_PAGE_SIZE 83 #define ARCH_KERNEL_STACK_OBJ_ALIGN CONFIG_MMU_PAGE_SIZE 84 #else 85 #define ARCH_KERNEL_STACK_RESERVED 0 86 #define ARCH_KERNEL_STACK_OBJ_ALIGN ARCH_STACK_PTR_ALIGN 87 #endif 88 89 #endif /* !_ASMLANGUAGE */ 90 #endif /* ZEPHYR_INCLUDE_ARCH_X86_THREAD_STACK_H */ 91