diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index e2fed3613311e..095b097504f65 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -233,6 +233,10 @@ config ARCH_MPU_HAS_NAPOT bool "PMP supports NAPOT" default y if !PMP_HAS_LIMITED_FEATURES +config ARCH_CPU_COUNT + int "Amount of CPUs in SoC" + default 5 if ARCH_CHIP_MPFS + source "arch/risc-v/src/opensbi/Kconfig" source "arch/risc-v/src/common/Kconfig" diff --git a/arch/risc-v/src/common/riscv_cpuindex.c b/arch/risc-v/src/common/riscv_cpuindex.c index 201fa0639a1c6..f07c6d5be3817 100644 --- a/arch/risc-v/src/common/riscv_cpuindex.c +++ b/arch/risc-v/src/common/riscv_cpuindex.c @@ -29,6 +29,7 @@ #include #include "riscv_internal.h" +#include "riscv_percpu.h" /**************************************************************************** * Public Functions @@ -50,7 +51,7 @@ uintptr_t riscv_mhartid(void) #ifdef CONFIG_ARCH_USE_S_MODE /* Kernel is in S-mode */ -#error "Missing functionality..." + return riscv_percpu_get_hartid(); #else /* Kernel is in M-mode */ diff --git a/arch/risc-v/src/common/riscv_percpu.c b/arch/risc-v/src/common/riscv_percpu.c new file mode 100644 index 0000000000000..488e82db4bf29 --- /dev/null +++ b/arch/risc-v/src/common/riscv_percpu.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_percpu.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 "riscv_percpu.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define HART_CNT (CONFIG_ARCH_CPU_COUNT) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct riscv_percpu_s g_scratch[HART_CNT]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: riscv_percpu_init + * + * Description: + * Initialize the per CPU structures, should only be done on the boot + * hart. + * + ****************************************************************************/ + +void riscv_percpu_init(void) +{ + int i; + + for (i = 0; i < HART_CNT; i++) + { + g_scratch[i].hartid = i; + } +} + +/**************************************************************************** + * Name: riscv_percpu_get_addr + * + * Description: + * Get add a hart to the per CPU area + * + * Input Parameters: + * hartid - Hart number + * + ****************************************************************************/ + +void riscv_percpu_add_hart(uintptr_t hartid) +{ + /* Hart IDs go from 0...4 */ + + DEBUGASSERT(hartid < HART_CNT); + + /* Set the scratch register value to point to the scratch area */ + + WRITE_CSR(sscratch, &g_scratch[hartid]); + + /* Make sure it sticks */ + + __DMB(); +} + +/**************************************************************************** + * Name: riscv_percpu_get_hartid + * + * Description: + * Get harts own hartid by reading it from the per CPU area. This is safe + * to use from lower privilege modes (than M-mode). + * + * Returned Value: + * Hart id + * + ****************************************************************************/ + +uintptr_t riscv_percpu_get_hartid(void) +{ + uintptr_t scratch = READ_CSR(sscratch); + + DEBUGASSERT(scratch >= (uintptr_t) &g_scratch && + scratch <= (uintptr_t) &g_scratch + sizeof(g_scratch)); + + return ((struct riscv_percpu_s *)scratch)->hartid; +} diff --git a/arch/risc-v/src/common/riscv_percpu.h b/arch/risc-v/src/common/riscv_percpu.h new file mode 100644 index 0000000000000..4db5cc23171bd --- /dev/null +++ b/arch/risc-v/src/common/riscv_percpu.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_percu.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_RISC_V_SRC_COMMON_RISCV_PERCPU_H +#define __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H + +#include + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef __ASSEMBLY__ +#define SCRATCH_HARTID_OFFSET (0 * INT_REG_SIZE) +#else +#define SCRATCH_HARTID_OFFSET offsetof(riscv_percpu_s, hartid) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Per CPU save area. Access to this structure can be gained via the + * supervisor scratch (sscratch) register. Prior to this, every CPU that + * wishes to access this information must call riscv_percpu_add_hart() which + * will set up sscratch to point to the CPUs own area + */ + +struct riscv_percpu_s +{ + uintptr_t hartid; /* Hart ID */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: riscv_percpu_init + * + * Description: + * Initialize the per CPU structures, should only be done on the boot + * hart. + * + ****************************************************************************/ + +void riscv_percpu_init(void); + +/**************************************************************************** + * Name: riscv_percpu_get_addr + * + * Description: + * Get add a hart to the per CPU area + * + * Input Parameters: + * hartid - Hart number + * + ****************************************************************************/ + +void riscv_percpu_add_hart(uintptr_t hartid); + +/**************************************************************************** + * Name: riscv_percpu_get_hartid + * + * Description: + * Get harts own hartid by reading it from the per CPU area. This is safe + * to use from lower privilege modes than M-mode. + * + * Returned Value: + * Hart id + * + ****************************************************************************/ + +uintptr_t riscv_percpu_get_hartid(void); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISC_V_SRC_COMMON_RISCV_PERCPU_H */