Skip to content

Commit

Permalink
arch: arc: add support for lock/unlock VPX
Browse files Browse the repository at this point in the history
Adds support for cooperative locking/unlocking the VPX vector registers.
Provided that all VPX enabled threads use these routines to control
access to the VPX vector registers, it will allow multiple threads to
safely use them without the need for saving/restoring them upon each
context switch.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
  • Loading branch information
peter-mitsis authored and nashif committed Oct 17, 2024
1 parent f629f1e commit 1d07e56
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 1 deletion.
9 changes: 9 additions & 0 deletions arch/arc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
69 changes: 68 additions & 1 deletion arch/arc/core/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
#include <zephyr/arch/arc/v2/mpu/arc_core_mpu.h>
#endif

#if defined(CONFIG_ARC_DSP) && defined(CONFIG_DSP_SHARING)
#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) || defined(CONFIG_DSP_SHARING)
#include <zephyr/arch/arc/v2/dsp/arc_dsp.h>
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;
Expand Down Expand Up @@ -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 <id>.
*/

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 <id>, 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
20 changes: 20 additions & 0 deletions doc/hardware/arch/arc-support-status.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
54 changes: 54 additions & 0 deletions include/zephyr/arch/arc/v2/vpx/arc_vpx.h
Original file line number Diff line number Diff line change
@@ -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 <zephyr/sys_clock.h>

/**
* @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_ */

0 comments on commit 1d07e56

Please sign in to comment.