1 /*
2 * Copyright (c) 2019 Intel Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/kernel.h>
7 #include <ksched.h>
8 #include <zephyr/kernel_structs.h>
9 #include <kernel_internal.h>
10 #include <offsets_short.h>
11 #include <x86_mmu.h>
12
13 extern void x86_sse_init(struct k_thread *thread); /* in locore.S */
14
15 /* FIXME: This exists to make space for a "return address" at the top
16 * of the stack. Obviously this is unused at runtime, but is required
17 * for alignment: stacks at runtime should be 16-byte aligned, and a
18 * CALL will therefore push a return address that leaves the stack
19 * misaligned. Effectively we're wasting 8 bytes here to undo (!) the
20 * alignment that the upper level code already tried to do for us. We
21 * should clean this up.
22 */
23 struct x86_initial_frame {
24 /* zeroed return address for ABI */
25 uint64_t rip;
26 };
27
arch_new_thread(struct k_thread * thread,k_thread_stack_t * stack,char * stack_ptr,k_thread_entry_t entry,void * p1,void * p2,void * p3)28 void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
29 char *stack_ptr, k_thread_entry_t entry,
30 void *p1, void *p2, void *p3)
31 {
32 void *switch_entry;
33 struct x86_initial_frame *iframe;
34
35 #if CONFIG_X86_STACK_PROTECTION
36 z_x86_set_stack_guard(stack);
37 #endif
38 #ifdef CONFIG_USERSPACE
39 switch_entry = z_x86_userspace_prepare_thread(thread);
40 thread->arch.cs = X86_KERNEL_CS;
41 thread->arch.ss = X86_KERNEL_DS;
42 #else
43 switch_entry = z_thread_entry;
44 #endif
45 iframe = Z_STACK_PTR_TO_FRAME(struct x86_initial_frame, stack_ptr);
46 iframe->rip = 0U;
47 thread->callee_saved.rsp = (long) iframe;
48 thread->callee_saved.rip = (long) switch_entry;
49 thread->callee_saved.rflags = EFLAGS_INITIAL;
50
51 /* Parameters to entry point, which is populated in
52 * thread->callee_saved.rip
53 */
54 thread->arch.rdi = (long) entry;
55 thread->arch.rsi = (long) p1;
56 thread->arch.rdx = (long) p2;
57 thread->arch.rcx = (long) p3;
58
59 x86_sse_init(thread);
60
61 thread->arch.flags = X86_THREAD_FLAG_ALL;
62 thread->switch_handle = thread;
63 }
64
arch_float_disable(struct k_thread * thread)65 int arch_float_disable(struct k_thread *thread)
66 {
67 /* x86-64 always has FP/SSE enabled so cannot be disabled */
68 return -ENOTSUP;
69 }
70
arch_float_enable(struct k_thread * thread,unsigned int options)71 int arch_float_enable(struct k_thread *thread, unsigned int options)
72 {
73 /* x86-64 always has FP/SSE enabled so nothing to do here */
74 return 0;
75 }
76