diff --git a/arch/Kconfig b/arch/Kconfig index b953b5f3029..75a43408942 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -130,6 +130,8 @@ config ARCH_X86 config ARCH_X86_64 bool "x86_64" select ARCH_HAVE_TCBINFO + select ARCH_HAVE_FPU + select ARCH_HAVE_DPFPU select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF ---help--- x86-64 architectures. diff --git a/arch/x86_64/include/intel64/irq.h b/arch/x86_64/include/intel64/irq.h index 55786caa509..02254b1c095 100644 --- a/arch/x86_64/include/intel64/irq.h +++ b/arch/x86_64/include/intel64/irq.h @@ -104,7 +104,7 @@ */ #define XCPTCONTEXT_XMM_AREA_SIZE 512 -#define XMMAREA_OFFSET XCPTCONTEXT_XMM_AREA_SIZE / 8 +#define XMMAREA_OFFSET (XCPTCONTEXT_XMM_AREA_SIZE / 8) /* Data segments */ diff --git a/arch/x86_64/src/intel64/CMakeLists.txt b/arch/x86_64/src/intel64/CMakeLists.txt index 3ad8426ae09..91829113c01 100644 --- a/arch/x86_64/src/intel64/CMakeLists.txt +++ b/arch/x86_64/src/intel64/CMakeLists.txt @@ -55,4 +55,8 @@ else() list(APPEND SRCS intel64_timerisr.c) endif() +if(CONFIG_ARCH_FPU) + list(APPEND SRCS intel64_fpucmp.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs index a37be230e00..c43a441de1d 100644 --- a/arch/x86_64/src/intel64/Make.defs +++ b/arch/x86_64/src/intel64/Make.defs @@ -52,3 +52,6 @@ ifeq ($(CONFIG_SCHED_TICKLESS),y) CHIP_CSRCS += intel64_tickless.c endif +ifeq ($(CONFIG_ARCH_FPU),y) +CHIP_CSRCS += intel64_fpucmp.c +endif \ No newline at end of file diff --git a/arch/x86_64/src/intel64/intel64_fpucmp.c b/arch/x86_64/src/intel64/intel64_fpucmp.c new file mode 100644 index 00000000000..3159284dacc --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_fpucmp.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_fpucmp.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "x86_64_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FPU + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_fpucmp + * + * Description: + * Compare FPU areas from thread context. + * + * Input Parameters: + * saveregs1 - Pointer to the saved FPU registers. + * saveregs2 - Pointer to the saved FPU registers. + * + * Returned Value: + * True if FPU areas compare equal, False otherwise. + * + ****************************************************************************/ + +bool up_fpucmp(const void *saveregs1, const void *saveregs2) +{ + const uint32_t *regs1 = saveregs1; + const uint32_t *regs2 = saveregs2; + + /* IMPORTANT: + * + * With aggresive optimization enabled (-O2/-O3), ostest FPU test will + * fail. This is because the compiler will generate additional vector + * instructions between subsequent up_fpucmp() calls (loop vectorization + * somewhere in usleep() call), which will consequently overwrite + * the expected FPU context (XMM registers). + */ + + /* XMM area starts from offset 0 */ + + return memcmp(®s1[0], ®s2[0], XCPTCONTEXT_XMM_AREA_SIZE) == 0; +} +#endif /* CONFIG_ARCH_FPU */ diff --git a/arch/x86_64/src/intel64/intel64_handlers.c b/arch/x86_64/src/intel64/intel64_handlers.c index 3c9b175d228..5b432edf574 100644 --- a/arch/x86_64/src/intel64/intel64_handlers.c +++ b/arch/x86_64/src/intel64/intel64_handlers.c @@ -86,12 +86,6 @@ static uint64_t *common_handler(int irq, uint64_t *regs) if (regs != g_current_regs) { -#ifdef CONFIG_ARCH_FPU - /* Restore floating point registers */ - - up_restorefpu((uint64_t *)g_current_regs); -#endif - #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously * running task is closed down gracefully (data caches dump,