/* * Copyright (c) 2010-2015 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Thread support primitives * * This module provides core thread related primitives for the IA-32 * processor architecture. */ #include #include #include #include #include /* forward declaration */ /* Initial thread stack frame, such that everything is laid out as expected * for when z_swap() switches to it for the first time. */ struct _x86_initial_frame { uint32_t swap_retval; uint32_t ebp; uint32_t ebx; uint32_t esi; uint32_t edi; void *thread_entry; uint32_t eflags; k_thread_entry_t entry; void *p1; void *p2; void *p3; }; #ifdef CONFIG_X86_USERSPACE /* Implemented in userspace.S */ extern void z_x86_syscall_entry_stub(void); /* Syscalls invoked by 'int 0x80'. Installed in the IDT at DPL=3 so that * userspace can invoke it. */ NANO_CPU_INT_REGISTER(z_x86_syscall_entry_stub, -1, -1, 0x80, 3); #endif /* CONFIG_X86_USERSPACE */ #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) extern int z_float_disable(struct k_thread *thread); int arch_float_disable(struct k_thread *thread) { #if defined(CONFIG_LAZY_FPU_SHARING) return z_float_disable(thread); #else return -ENOTSUP; #endif /* CONFIG_LAZY_FPU_SHARING */ } extern int z_float_enable(struct k_thread *thread, unsigned int options); int arch_float_enable(struct k_thread *thread, unsigned int options) { #if defined(CONFIG_LAZY_FPU_SHARING) return z_float_enable(thread, options); #else return -ENOTSUP; #endif /* CONFIG_LAZY_FPU_SHARING */ } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ void 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) { void *swap_entry; struct _x86_initial_frame *initial_frame; #if defined(CONFIG_X86_STACK_PROTECTION) && !defined(CONFIG_THREAD_STACK_MEM_MAPPED) /* This unconditionally set the first page of stack as guard page, * which is only needed if the stack is not memory mapped. */ z_x86_set_stack_guard(stack); #endif #ifdef CONFIG_USERSPACE swap_entry = z_x86_userspace_prepare_thread(thread); #else swap_entry = z_thread_entry; #endif /* Create an initial context on the stack expected by z_swap() */ initial_frame = Z_STACK_PTR_TO_FRAME(struct _x86_initial_frame, stack_ptr); /* z_thread_entry() arguments */ initial_frame->entry = entry; initial_frame->p1 = p1; initial_frame->p2 = p2; initial_frame->p3 = p3; initial_frame->eflags = EFLAGS_INITIAL; #ifdef _THREAD_WRAPPER_REQUIRED initial_frame->edi = (uint32_t)swap_entry; initial_frame->thread_entry = z_x86_thread_entry_wrapper; #else initial_frame->thread_entry = swap_entry; #endif /* _THREAD_WRAPPER_REQUIRED */ /* Remaining _x86_initial_frame members can be garbage, z_thread_entry() * doesn't care about their state when execution begins */ thread->callee_saved.esp = (unsigned long)initial_frame; #if defined(CONFIG_LAZY_FPU_SHARING) thread->arch.excNestCount = 0; #endif /* CONFIG_LAZY_FPU_SHARING */ thread->arch.flags = 0; /* * When "eager FPU sharing" mode is enabled, FPU registers must be * initialised at the time of thread creation because the floating-point * context is always active and no further FPU initialisation is performed * later. */ #if defined(CONFIG_EAGER_FPU_SHARING) thread->arch.preempFloatReg.floatRegsUnion.fpRegs.fcw = 0x037f; thread->arch.preempFloatReg.floatRegsUnion.fpRegs.ftw = 0xffff; #if defined(CONFIG_X86_SSE) thread->arch.preempFloatReg.floatRegsUnion.fpRegsEx.mxcsr = 0x1f80; #endif /* CONFIG_X86_SSE */ #endif /* CONFIG_EAGER_FPU_SHARING */ }