Line data Source code
1 0 : /*
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 0 : #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 0 : #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_X86_STACK_BASE_ALIGN
99 :
100 0 : #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \
101 : ROUND_UP((size), Z_X86_STACK_SIZE_ALIGN)
102 :
103 0 : #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 0 : #define ARCH_KERNEL_STACK_OBJ_ALIGN ARCH_STACK_PTR_ALIGN
111 : #endif
112 :
113 : #endif /* !_ASMLANGUAGE */
114 : #endif /* ZEPHYR_INCLUDE_ARCH_X86_THREAD_STACK_H */
|