diff --git a/arch/x86/core/ia32/float.c b/arch/x86/core/ia32/float.c index c89bf7accd5..9b6f4daa18e 100644 --- a/arch/x86/core/ia32/float.c +++ b/arch/x86/core/ia32/float.c @@ -194,7 +194,7 @@ void z_float_enable(struct k_thread *thread, unsigned int options) * must be preserved). */ - fp_owner = _kernel.current_fp; + fp_owner = _kernel.cpus[0].arch.fpu_owner; if (fp_owner != NULL) { if ((fp_owner->arch.flags & X86_THREAD_FLAG_ALL) != 0) { FpCtxSave(fp_owner); @@ -215,7 +215,7 @@ void z_float_enable(struct k_thread *thread, unsigned int options) * (The FP context is "live" in hardware, not saved in TCS.) */ - _kernel.current_fp = thread; + _kernel.cpus[0].arch.fpu_owner = thread; } else { /* * When enabling FP support for someone else, assign ownership @@ -230,7 +230,7 @@ void z_float_enable(struct k_thread *thread, unsigned int options) * to its original state. */ - _kernel.current_fp = thread; + _kernel.cpus[0].arch.fpu_owner = thread; z_FpAccessDisable(); } else { /* @@ -280,10 +280,10 @@ int z_float_disable(struct k_thread *thread) if (thread == _current) { z_FpAccessDisable(); - _kernel.current_fp = (struct k_thread *)0; + _kernel.cpus[0].arch.fpu_owner = (struct k_thread *)0; } else { - if (_kernel.current_fp == thread) { - _kernel.current_fp = (struct k_thread *)0; + if (_kernel.cpus[0].arch.fpu_owner == thread) { + _kernel.cpus[0].arch.fpu_owner = (struct k_thread *)0; } } diff --git a/arch/x86/core/ia32/swap.S b/arch/x86/core/ia32/swap.S index af104fdff47..6103e4bbe53 100644 --- a/arch/x86/core/ia32/swap.S +++ b/arch/x86/core/ia32/swap.S @@ -50,7 +50,7 @@ * Floating point registers are handled using a lazy save/restore mechanism * since it's expected relatively few threads will be created with the * K_FP_REGS or K_SSE_REGS option bits. The kernel data structure maintains a - * 'current_fp' field to keep track of the thread that "owns" the floating + * 'fpu_owner' field to keep track of the thread that "owns" the floating * point registers. Floating point registers consist of ST0->ST7 (x87 FPU and * MMX registers) and XMM0 -> XMM7. * @@ -176,7 +176,7 @@ SECTION_FUNC(PINNED_TEXT, arch_swap) * If so, there there is no need to restore the floating point context. */ - movl _kernel_offset_to_current_fp(%edi), %ebx + movl _kernel_offset_to_fpu_owner(%edi), %ebx cmpl %ebx, %eax je restoreContext_NoFloatSwap @@ -265,7 +265,7 @@ restoreContext_NoFloatRestore: /* record that the incoming thread "owns" the floating point registers */ - movl %eax, _kernel_offset_to_current_fp(%edi) + movl %eax, _kernel_offset_to_fpu_owner(%edi) /* diff --git a/arch/x86/core/offsets/ia32_offsets.c b/arch/x86/core/offsets/ia32_offsets.c index 2dfbb5c38ef..dcbf3d7d680 100644 --- a/arch/x86/core/offsets/ia32_offsets.c +++ b/arch/x86/core/offsets/ia32_offsets.c @@ -33,6 +33,12 @@ GEN_OFFSET_SYM(_thread_arch_t, excNestCount); #endif +#if defined(CONFIG_FPU_SHARING) +GEN_OFFSET_SYM(_kernel_t, cpus); +GEN_OFFSET_SYM(_cpu_t, arch); +GEN_OFFSET_SYM(_cpu_arch_t, fpu_owner); +#endif + #ifdef CONFIG_USERSPACE GEN_OFFSET_SYM(_thread_arch_t, psp); #ifndef CONFIG_X86_COMMON_PAGE_TABLE diff --git a/arch/x86/include/ia32/offsets_short_arch.h b/arch/x86/include/ia32/offsets_short_arch.h index cb5cdb218f0..b818cf60b55 100644 --- a/arch/x86/include/ia32/offsets_short_arch.h +++ b/arch/x86/include/ia32/offsets_short_arch.h @@ -14,6 +14,9 @@ #define _kernel_offset_to_isf \ (___kernel_t_arch_OFFSET + ___kernel_arch_t_isf_OFFSET) +#define _kernel_offset_to_fpu_owner \ + (___kernel_t_cpus_OFFSET + ___cpu_t_arch_OFFSET + ___cpu_arch_t_fpu_owner_OFFSET) + /* end - kernel */ /* threads */ diff --git a/include/zephyr/arch/structs.h b/include/zephyr/arch/structs.h index 703ec81f889..dcd4406c1d8 100644 --- a/include/zephyr/arch/structs.h +++ b/include/zephyr/arch/structs.h @@ -29,6 +29,8 @@ #include #elif defined(CONFIG_ARM) #include +#elif defined(CONFIG_X86) && !defined(CONFIG_X86_64) +#include #else /* Default definitions when no architecture specific definitions exist. */ diff --git a/include/zephyr/arch/x86/ia32/structs.h b/include/zephyr/arch/x86/ia32/structs.h new file mode 100644 index 00000000000..91112a8578c --- /dev/null +++ b/include/zephyr/arch/x86/ia32/structs.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Intel + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_X86_STRUCTS_H_ +#define ZEPHYR_INCLUDE_X86_STRUCTS_H_ + +#include + +struct k_thread; + +/* Per CPU architecture specifics (empty) */ +struct _cpu_arch { + +#if defined(CONFIG_FPU_SHARING) + /* + * A 'sse_owner' field does not exist in addition to the 'fpu_owner' + * field since it's not possible to divide the IA-32 non-integer + * registers into 2 distinct blocks owned by differing threads. In + * other words, given that the 'fxnsave/fxrstor' instructions + * save/restore both the X87 FPU and XMM registers, it's not possible + * for a thread to only "own" the XMM registers. + */ + + struct k_thread *fpu_owner; +#elif defined(__cplusplus) + /* Ensure this struct does not have a size of 0 which is not allowed in C++. */ + uint8_t dummy; +#endif +}; + +#endif /* ZEPHYR_INCLUDE_X86_STRUCTS_H_ */ diff --git a/include/zephyr/kernel_structs.h b/include/zephyr/kernel_structs.h index 56df49dcb23..5fde0535822 100644 --- a/include/zephyr/kernel_structs.h +++ b/include/zephyr/kernel_structs.h @@ -217,20 +217,6 @@ struct z_kernel { struct _ready_q ready_q; #endif -#ifdef CONFIG_FPU_SHARING - /* - * A 'current_sse' field does not exist in addition to the 'current_fp' - * field since it's not possible to divide the IA-32 non-integer - * registers into 2 distinct blocks owned by differing threads. In - * other words, given that the 'fxnsave/fxrstor' instructions - * save/restore both the X87 FPU and XMM registers, it's not possible - * for a thread to only "own" the XMM registers. - */ - - /* thread that owns the FP regs */ - struct k_thread *current_fp; -#endif - #if defined(CONFIG_THREAD_MONITOR) struct k_thread *threads; /* singly linked list of ALL threads */ #endif diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index 3cadf7e12a0..1d560cb602f 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -48,10 +48,6 @@ GEN_OFFSET_SYM(_kernel_t, ready_q); GEN_OFFSET_SYM(_ready_q_t, cache); #endif /* CONFIG_SMP */ -#ifdef CONFIG_FPU_SHARING -GEN_OFFSET_SYM(_kernel_t, current_fp); -#endif /* CONFIG_FPU_SHARING */ - GEN_OFFSET_SYM(_thread_base_t, user_options); GEN_OFFSET_SYM(_thread_t, base); diff --git a/kernel/include/offsets_short.h b/kernel/include/offsets_short.h index 373d7e02ec9..c97ba15e562 100644 --- a/kernel/include/offsets_short.h +++ b/kernel/include/offsets_short.h @@ -34,9 +34,6 @@ #define _kernel_offset_to_idle \ (___kernel_t_idle_OFFSET) -#define _kernel_offset_to_current_fp \ - (___kernel_t_current_fp_OFFSET) - #define _kernel_offset_to_ready_q_cache \ (___kernel_t_ready_q_OFFSET + ___ready_q_t_cache_OFFSET)