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_X86_STACK_PROTECTION) || defined(CONFIG_USERSPACE) \ 18 || defined(CONFIG_THREAD_STACK_MEM_MAPPED) 19 #define Z_X86_STACK_BASE_ALIGN CONFIG_MMU_PAGE_SIZE 20 #else 21 #define Z_X86_STACK_BASE_ALIGN ARCH_STACK_PTR_ALIGN 22 #endif 23 24 #if defined(CONFIG_USERSPACE) || defined(CONFIG_THREAD_STACK_MEM_MAPPED) 25 /* If user mode enabled, expand any stack size to fill a page since that is 26 * the access control granularity and we don't want other kernel data to 27 * unintentionally fall in the latter part of the page 28 * 29 * This is also true when memory mapped stacks are used with since 30 * access control applies to one page at a time. 31 */ 32 #define Z_X86_STACK_SIZE_ALIGN CONFIG_MMU_PAGE_SIZE 33 #else 34 #define Z_X86_STACK_SIZE_ALIGN ARCH_STACK_PTR_ALIGN 35 #endif 36 37 #ifndef _ASMLANGUAGE 38 /* With both hardware stack protection and userspace enabled, stacks are 39 * arranged as follows: 40 * 41 * --- Without stack being memory mapped: 42 * High memory addresses 43 * +-----------------------------------------+ 44 * | Thread stack (varies) | 45 * +-----------------------------------------+ 46 * | Privilege elevation stack | 47 * | (CONFIG_PRIVILEGED_STACK_SIZE) | 48 * +-----------------------------------------+ 49 * | Guard page (4096 bytes) | 50 * | - 'guard_page' in struct | 51 * | z_x86_thread_stack_header | 52 * +-----------------------------------------+ 53 * Low Memory addresses 54 * 55 * --- With stack being memory mapped: 56 * High memory addresses 57 * +-----------------------------------------+ 58 * | Guard page (empty page) | 59 * +-----------------------------------------+ 60 * | Thread stack (varies) | 61 * +-----------------------------------------+ 62 * | Privilege elevation stack | 63 * | (CONFIG_PRIVILEGED_STACK_SIZE) | 64 * +-----------------------------------------+ 65 * | Guard page (empty page) | 66 * +-----------------------------------------+ 67 * Low Memory addresses 68 * 69 * Without memory mapped stacks, the guard page is actually allocated 70 * as part of the stack struct, which takes up physical memory during 71 * linking. 72 * 73 * Privilege elevation stacks are fixed-size. All the pages containing the 74 * thread stack are marked as user-accessible. The guard page is marked 75 * read-only to catch stack overflows in supervisor mode. 76 * 77 * If a thread starts in supervisor mode, the page containing the 78 * privilege elevation stack is also marked read-only. 79 * 80 * If a thread starts in, or drops down to user mode, the privilege stack page 81 * will be marked as present, supervisor-only. 82 * 83 * If KPTI is not enabled, the _main_tss.esp0 field will always be updated 84 * updated to point to the top of the privilege elevation stack. Otherwise 85 * _main_tss.esp0 always points to the trampoline stack, which handles the 86 * page table switch to the kernel PDPT and transplants context to the 87 * privileged mode stack. 88 */ 89 struct z_x86_thread_stack_header { 90 #if defined(CONFIG_X86_STACK_PROTECTION) && !defined(CONFIG_THREAD_STACK_MEM_MAPPED) 91 char guard_page[CONFIG_MMU_PAGE_SIZE]; 92 #endif 93 #ifdef CONFIG_USERSPACE 94 char privilege_stack[CONFIG_PRIVILEGED_STACK_SIZE]; 95 #endif /* CONFIG_USERSPACE */ 96 } __packed __aligned(Z_X86_STACK_BASE_ALIGN); 97 98 #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_X86_STACK_BASE_ALIGN 99 100 #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ 101 ROUND_UP((size), Z_X86_STACK_SIZE_ALIGN) 102 103 #define ARCH_THREAD_STACK_RESERVED \ 104 sizeof(struct z_x86_thread_stack_header) 105 106 #ifdef CONFIG_X86_STACK_PROTECTION 107 #define ARCH_KERNEL_STACK_RESERVED CONFIG_MMU_PAGE_SIZE 108 #define ARCH_KERNEL_STACK_OBJ_ALIGN CONFIG_MMU_PAGE_SIZE 109 #else 110 #define ARCH_KERNEL_STACK_RESERVED 0 111 #define ARCH_KERNEL_STACK_OBJ_ALIGN ARCH_STACK_PTR_ALIGN 112 #endif 113 114 #endif /* !_ASMLANGUAGE */ 115 #endif /* ZEPHYR_INCLUDE_ARCH_X86_THREAD_STACK_H */ 116