diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index a27b09659ac..e324c4064ab 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -343,6 +343,15 @@ config ARC_NORMAL_FIRMWARE resources of the ARC processors, and, therefore, it shall avoid accessing them. +config ARC_VPX_COOPERATIVE_SHARING + bool "Cooperative sharing of ARC VPX vector registers" + select SCHED_CPU_MASK if MP_MAX_NUM_CPUS > 1 + help + This option enables the cooperative sharing of the ARC VPX vector + registers. Threads that want to use those registers must successfully + call arc_vpx_lock() before using them, and call arc_vpx_unlock() + when done using them. + source "arch/arc/core/dsp/Kconfig" menu "ARC MPU Options" diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 1c85a416ca6..4b1d836103e 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -19,10 +19,15 @@ #include #endif -#if defined(CONFIG_ARC_DSP) && defined(CONFIG_DSP_SHARING) +#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) || defined(CONFIG_DSP_SHARING) #include static struct k_spinlock lock; #endif + +#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) +static struct k_sem vpx_sem[CONFIG_MP_MAX_NUM_CPUS]; +#endif + /* initial stack frame */ struct init_stack_frame { uintptr_t pc; @@ -320,3 +325,65 @@ void arc_dsp_enable(struct k_thread *thread, unsigned int options) k_spin_unlock(&lock, key); } #endif /* CONFIG_ARC_DSP && CONFIG_DSP_SHARING */ + +#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) +int arc_vpx_lock(k_timeout_t timeout) +{ + k_spinlock_key_t key; + unsigned int id; + + key = k_spin_lock(&lock); + + id = _current_cpu->id; +#if (CONFIG_MP_MAX_NUM_CPUS > 1) && defined(CONFIG_SCHED_CPU_MASK) + __ASSERT(!arch_is_in_isr() && (_current->base.cpu_mask == BIT(id)), ""); +#endif + k_spin_unlock(&lock, key); + + /* + * It is assumed that the thread is (still) pinned to + * the same CPU identified by . + */ + + return k_sem_take(&vpx_sem[id], timeout); +} + +void arc_vpx_unlock(void) +{ + k_spinlock_key_t key; + unsigned int id; + + key = k_spin_lock(&lock); +#if (CONFIG_MP_MAX_NUM_CPUS > 1) && defined(CONFIG_SCHED_CPU_MASK) + __ASSERT(!arch_is_in_isr() && (_current->base.cpu_mask == BIT(id)), ""); +#endif + id = _current_cpu->id; + k_spin_unlock(&lock, key); + + /* + * It is assumed that this thread is (still) pinned to + * the CPU identified by , and that it is the same CPU + * used by arc_vpx_lock(). + */ + + k_sem_give(&vpx_sem[id]); +} + +void arc_vpx_unlock_force(unsigned int id) +{ + __ASSERT(id < CONFIG_MP_MAX_NUM_CPUS, ""); + + k_sem_give(&vpx_sem[id]); +} + +static int arc_vpx_sem_init(void) +{ + for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + k_sem_init(vpx_sem, 1, 1); + } + + return 0; +} + +SYS_INIT(arc_vpx_sem_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); +#endif diff --git a/doc/hardware/arch/arc-support-status.rst b/doc/hardware/arch/arc-support-status.rst index 66d07771c66..2c364f8c798 100644 --- a/doc/hardware/arch/arc-support-status.rst +++ b/doc/hardware/arch/arc-support-status.rst @@ -92,3 +92,23 @@ Notes .. [#f6] currently only ARC VPX scalar port is supported. The support of VPX vector pipeline, VCCM, STU is not included in this port, and require additional development and / or other runtime integration. + +VPX Vector Registers +-------------------- +Zephyr supports a limited form sharing of the VPX vector registers known as +cooperative sharing. Threads that use these registers must bookend the relevant +sections with calls to :c:func:`arc_vpx_lock` and :c:func:`arc_vpx_unlock` to +control access to this resource. + +.. note:: + If the system has multiple CPUs, then it is the responsibility of the + application developer to both pin the thread to a single CPU before it + attempts to get the cooperative lock, and not modify the CPU affinity + while it is waiting for or holding that cooperative lock. + +Configuration Options +===================== + +The cooperative sharing of the VPX vector registers is selected when +configuration option :kconfig:option:`CONFIG_ARC_VPX_COOPERATIVE_SHARING` +is enabled. diff --git a/include/zephyr/arch/arc/v2/vpx/arc_vpx.h b/include/zephyr/arch/arc/v2/vpx/arc_vpx.h new file mode 100644 index 00000000000..904c44cd11c --- /dev/null +++ b/include/zephyr/arch/arc/v2/vpx/arc_vpx.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Synopsys. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_ +#define ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_ + +#include + +/** + * @brief Obtain a cooperative lock on the VPX vector registers + * + * This function is used to obtain a cooperative lock on the current CPU's + * VPX vector registers before the calling thread uses them. Callers + * attempting to obtain the cooperative lock must be already restricted to + * executing on a single CPU, and continue to execute on that same CPU while + * both waiting and holding the lock. + * + * This routine is not callable from an ISR. + * + * @param timeout Waiting period to obtain the lock, or one of the special + * values K_NO_WAIT and K_FOREVER. + * + * @return Zero on success, otherwise error code + */ +int arc_vpx_lock(k_timeout_t timeout); + +/** + * @brief Release cooperative lock on the VPX vector registers + * + * This function is used to release the cooperative lock on the current CPU's + * VPX vector registers. It is called after the current thread no longer needs + * to use the VPX vector registers, thereby allowing another thread to use them. + * + * This routine is not callable from an ISR. + */ +void arc_vpx_unlock(void); + +/** + * @brief Release cooperative lock on a CPU's VPX vector registers + * + * This function is used to release the cooperative lock on the specified CPU's + * VPX vector registers. This routine should not be used except by a system + * monitor to release the cooperative lock in case the locking thread where it + * is known that the locking thread is unable to release it (e.g. it was + * aborted while holding the lock). + * + * @param cpu_id CPU ID of the VPX vector register set to be unlocked + */ +void arc_vpx_unlock_force(unsigned int cpu_id); + +#endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_ */