From cdfce8a055cb9bbd47674ba74c3ee087eb704159 Mon Sep 17 00:00:00 2001 From: p-szafonimateusz Date: Fri, 23 Feb 2024 14:27:23 +0100 Subject: [PATCH] arch/x86_64: add spinlock support Add spinlock support for x86_64, needed for SMP Signed-off-by: p-szafonimateusz --- arch/Kconfig | 1 + arch/x86_64/include/spinlock.h | 98 +++++++++++++++++++++++ arch/x86_64/src/intel64/CMakeLists.txt | 4 + arch/x86_64/src/intel64/Make.defs | 4 + arch/x86_64/src/intel64/intel64_testset.S | 71 ++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 arch/x86_64/include/spinlock.h create mode 100644 arch/x86_64/src/intel64/intel64_testset.S diff --git a/arch/Kconfig b/arch/Kconfig index 75a43408942..664a80b569c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -132,6 +132,7 @@ config ARCH_X86_64 select ARCH_HAVE_TCBINFO select ARCH_HAVE_FPU select ARCH_HAVE_DPFPU + select ARCH_HAVE_TESTSET select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF ---help--- x86-64 architectures. diff --git a/arch/x86_64/include/spinlock.h b/arch/x86_64/include/spinlock.h new file mode 100644 index 00000000000..ac5b7d8b4f5 --- /dev/null +++ b/arch/x86_64/include/spinlock.h @@ -0,0 +1,98 @@ +/**************************************************************************** + * arch/x86_64/include/spinlock.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_X86_64_INCLUDE_SPINLOCK_H +#define __ARCH_X86_64_INCLUDE_SPINLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Spinlock states */ + +#define SP_UNLOCKED 0 /* The Un-locked state */ +#define SP_LOCKED 1 /* The Locked state */ + +/* Memory barriers for use with NuttX spinlock logic + * + * Data Memory Barrier (DMB) acts as a memory barrier. It ensures that all + * explicit memory accesses that appear in program order before the DMB + * instruction are observed before any explicit memory accesses that appear + * in program order after the DMB instruction. It does not affect the + * ordering of any other instructions executing on the processor + * + * Data Synchronization Barrier (DSB) acts as a special kind of memory + * barrier. No instruction in program order after this instruction executes + * until this instruction completes. This instruction completes when: (1) All + * explicit memory accesses before this instruction complete, and (2) all + * Cache, Branch predictor and TLB maintenance operations before this + * instruction complete. + * + */ + +#define SP_DSB(n) __asm__ __volatile__ ("mfence") +#define SP_DMB(n) __asm__ __volatile__ ("mfence") + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* The Type of a spinlock */ + +typedef uintptr_t spinlock_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: up_testset + * + * Description: + * Perform an atomic test and set operation on the provided spinlock. + * + * This function must be provided via the architecture-specific logic. + * + * Input Parameters: + * lock - The address of spinlock object. + * + * Returned Value: + * The spinlock is always locked upon return. The value of previous value + * of the spinlock variable is returned, either SP_LOCKED if the spinlock + * as previously locked (meaning that the test-and-set operation failed to + * obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked + * (meaning that we successfully obtained the lock) + * + ****************************************************************************/ + +/* See prototype in nuttx/include/nuttx/spinlock.h */ + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_64_INCLUDE_SPINLOCK_H */ diff --git a/arch/x86_64/src/intel64/CMakeLists.txt b/arch/x86_64/src/intel64/CMakeLists.txt index 91829113c01..e1738080d36 100644 --- a/arch/x86_64/src/intel64/CMakeLists.txt +++ b/arch/x86_64/src/intel64/CMakeLists.txt @@ -45,6 +45,10 @@ set(SRCS intel64_rng.c intel64_check_capability.c) +if(CONFIG_ARCH_HAVE_TESTSET) + list(APPEND SRCS intel64_testset.S) +endif() + if(CONFIG_MULTBOOT2_FB_TERM) list(APPEND SRCS intel64_mbfb.c) endif() diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs index c43a441de1d..599320c0c1f 100644 --- a/arch/x86_64/src/intel64/Make.defs +++ b/arch/x86_64/src/intel64/Make.defs @@ -38,6 +38,10 @@ CHIP_ASRCS = intel64_saveusercontext.S intel64_fullcontextrestore.S intel64_vec CHIP_CSRCS = intel64_start.c intel64_handlers.c intel64_idle.c intel64_lowsetup.c CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c +ifeq ($(CONFIG_ARCH_HAVE_TESTSET), y) +CHIP_ASRCS += intel64_testset.S +endif + # Configuration-dependent intel64 files ifeq ($(CONFIG_MULTBOOT2_FB_TERM),y) diff --git a/arch/x86_64/src/intel64/intel64_testset.S b/arch/x86_64/src/intel64/intel64_testset.S new file mode 100644 index 00000000000..77dde153a3f --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_testset.S @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/x86/src/intel64/intel64_testset.S + * + * 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 + + .file "intel64_head.S" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/************************************************************************** + * .text + **************************************************************************/ + + .text + .code64 + +/**************************************************************************** + * Name: up_testset + * + * Description: + * Perform an atomic test and set operation on the provided spinlock. + * + * This function must be provided via the architecture-specific logic. + * + * Input Parameters: + * lock - A reference to the spinlock object. + * + * Returned Value: + * The spinlock is always locked upon return. The previous value of the + * spinlock variable is returned, either SP_LOCKED if the spinlock was + * previously locked (meaning that the test-and-set operation failed to + * obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked + * (meaning that we successfully obtained the lock). + * + ****************************************************************************/ + + .globl up_testset + .type up_testset, @function +up_testset: + /* Set the value to be written (SP_LOCKED for test-and-set) */ + + movq $SP_LOCKED, %rax + + /* Atomic exchange, the old value is returned in rax */ + + xchg %rax, (%rdi) + ret