Implement a set of per-cpu trampoline stacks which all interrupts and exceptions will initially land on, and also as an intermediate stack for privilege changes as we need some stack space to swap page tables. Set up the special trampoline page which contains all the trampoline stacks, TSS, and GDT. This page needs to be present in the user page tables or interrupts don't work. CPU exceptions, with KPTI turned on, are treated as interrupts and not traps so that we have IRQs locked on exception entry. Add some additional macros for defining IDT entries. Add special handling of locore text/rodata sections when creating user mode page tables on x86-64. Restore qemu_x86_64 to use KPTI, and remove restrictions on enabling user mode on x86-64. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
59 lines
1.7 KiB
C
59 lines
1.7 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <ksched.h>
|
|
#include <kernel_structs.h>
|
|
#include <kernel_internal.h>
|
|
#include <offsets_short.h>
|
|
|
|
extern void x86_sse_init(struct k_thread *); /* in locore.S */
|
|
|
|
void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|
size_t stack_size, k_thread_entry_t entry,
|
|
void *parameter1, void *parameter2, void *parameter3,
|
|
int priority, unsigned int options)
|
|
{
|
|
void *switch_entry;
|
|
|
|
Z_ASSERT_VALID_PRIO(priority, entry);
|
|
z_new_thread_init(thread, Z_THREAD_STACK_BUFFER(stack),
|
|
stack_size, priority, options);
|
|
|
|
#if CONFIG_X86_STACK_PROTECTION
|
|
struct z_x86_thread_stack_header *header =
|
|
(struct z_x86_thread_stack_header *)stack;
|
|
|
|
/* Set guard area to read-only to catch stack overflows */
|
|
z_x86_mmu_set_flags(&z_x86_kernel_ptables, &header->guard_page,
|
|
MMU_PAGE_SIZE, MMU_ENTRY_READ, Z_X86_MMU_RW,
|
|
true);
|
|
#endif
|
|
#ifdef CONFIG_USERSPACE
|
|
switch_entry = z_x86_userspace_prepare_thread(thread);
|
|
thread->arch.cs = X86_KERNEL_CS;
|
|
thread->arch.ss = X86_KERNEL_DS;
|
|
#else
|
|
switch_entry = z_thread_entry;
|
|
#endif
|
|
thread->callee_saved.rsp = (long) Z_THREAD_STACK_BUFFER(stack);
|
|
thread->callee_saved.rsp += (stack_size - 8); /* fake RIP for ABI */
|
|
thread->callee_saved.rip = (long) switch_entry;
|
|
thread->callee_saved.rflags = EFLAGS_INITIAL;
|
|
|
|
/* Parameters to entry point, which is populated in
|
|
* thread->callee_saved.rip
|
|
*/
|
|
thread->arch.rdi = (long) entry;
|
|
thread->arch.rsi = (long) parameter1;
|
|
thread->arch.rdx = (long) parameter2;
|
|
thread->arch.rcx = (long) parameter3;
|
|
|
|
x86_sse_init(thread);
|
|
|
|
thread->arch.flags = X86_THREAD_FLAG_ALL;
|
|
thread->switch_handle = thread;
|
|
}
|