Skip to content

Commit 1d07e56

Browse files
peter-mitsisnashif
authored andcommitted
arch: arc: add support for lock/unlock VPX
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 <[email protected]>
1 parent f629f1e commit 1d07e56

File tree

4 files changed

+151
-1
lines changed

4 files changed

+151
-1
lines changed

arch/arc/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ config ARC_NORMAL_FIRMWARE
343343
resources of the ARC processors, and, therefore, it shall avoid
344344
accessing them.
345345

346+
config ARC_VPX_COOPERATIVE_SHARING
347+
bool "Cooperative sharing of ARC VPX vector registers"
348+
select SCHED_CPU_MASK if MP_MAX_NUM_CPUS > 1
349+
help
350+
This option enables the cooperative sharing of the ARC VPX vector
351+
registers. Threads that want to use those registers must successfully
352+
call arc_vpx_lock() before using them, and call arc_vpx_unlock()
353+
when done using them.
354+
346355
source "arch/arc/core/dsp/Kconfig"
347356

348357
menu "ARC MPU Options"

arch/arc/core/thread.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@
1919
#include <zephyr/arch/arc/v2/mpu/arc_core_mpu.h>
2020
#endif
2121

22-
#if defined(CONFIG_ARC_DSP) && defined(CONFIG_DSP_SHARING)
22+
#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING) || defined(CONFIG_DSP_SHARING)
2323
#include <zephyr/arch/arc/v2/dsp/arc_dsp.h>
2424
static struct k_spinlock lock;
2525
#endif
26+
27+
#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING)
28+
static struct k_sem vpx_sem[CONFIG_MP_MAX_NUM_CPUS];
29+
#endif
30+
2631
/* initial stack frame */
2732
struct init_stack_frame {
2833
uintptr_t pc;
@@ -320,3 +325,65 @@ void arc_dsp_enable(struct k_thread *thread, unsigned int options)
320325
k_spin_unlock(&lock, key);
321326
}
322327
#endif /* CONFIG_ARC_DSP && CONFIG_DSP_SHARING */
328+
329+
#if defined(CONFIG_ARC_VPX_COOPERATIVE_SHARING)
330+
int arc_vpx_lock(k_timeout_t timeout)
331+
{
332+
k_spinlock_key_t key;
333+
unsigned int id;
334+
335+
key = k_spin_lock(&lock);
336+
337+
id = _current_cpu->id;
338+
#if (CONFIG_MP_MAX_NUM_CPUS > 1) && defined(CONFIG_SCHED_CPU_MASK)
339+
__ASSERT(!arch_is_in_isr() && (_current->base.cpu_mask == BIT(id)), "");
340+
#endif
341+
k_spin_unlock(&lock, key);
342+
343+
/*
344+
* It is assumed that the thread is (still) pinned to
345+
* the same CPU identified by <id>.
346+
*/
347+
348+
return k_sem_take(&vpx_sem[id], timeout);
349+
}
350+
351+
void arc_vpx_unlock(void)
352+
{
353+
k_spinlock_key_t key;
354+
unsigned int id;
355+
356+
key = k_spin_lock(&lock);
357+
#if (CONFIG_MP_MAX_NUM_CPUS > 1) && defined(CONFIG_SCHED_CPU_MASK)
358+
__ASSERT(!arch_is_in_isr() && (_current->base.cpu_mask == BIT(id)), "");
359+
#endif
360+
id = _current_cpu->id;
361+
k_spin_unlock(&lock, key);
362+
363+
/*
364+
* It is assumed that this thread is (still) pinned to
365+
* the CPU identified by <id>, and that it is the same CPU
366+
* used by arc_vpx_lock().
367+
*/
368+
369+
k_sem_give(&vpx_sem[id]);
370+
}
371+
372+
void arc_vpx_unlock_force(unsigned int id)
373+
{
374+
__ASSERT(id < CONFIG_MP_MAX_NUM_CPUS, "");
375+
376+
k_sem_give(&vpx_sem[id]);
377+
}
378+
379+
static int arc_vpx_sem_init(void)
380+
{
381+
for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
382+
k_sem_init(vpx_sem, 1, 1);
383+
}
384+
385+
return 0;
386+
}
387+
388+
SYS_INIT(arc_vpx_sem_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
389+
#endif

doc/hardware/arch/arc-support-status.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,23 @@ Notes
9292
.. [#f6] currently only ARC VPX scalar port is supported. The support of VPX vector pipeline, VCCM,
9393
STU is not included in this port, and require additional development and / or other runtime
9494
integration.
95+
96+
VPX Vector Registers
97+
--------------------
98+
Zephyr supports a limited form sharing of the VPX vector registers known as
99+
cooperative sharing. Threads that use these registers must bookend the relevant
100+
sections with calls to :c:func:`arc_vpx_lock` and :c:func:`arc_vpx_unlock` to
101+
control access to this resource.
102+
103+
.. note::
104+
If the system has multiple CPUs, then it is the responsibility of the
105+
application developer to both pin the thread to a single CPU before it
106+
attempts to get the cooperative lock, and not modify the CPU affinity
107+
while it is waiting for or holding that cooperative lock.
108+
109+
Configuration Options
110+
=====================
111+
112+
The cooperative sharing of the VPX vector registers is selected when
113+
configuration option :kconfig:option:`CONFIG_ARC_VPX_COOPERATIVE_SHARING`
114+
is enabled.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2024 Synopsys.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_
8+
#define ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_
9+
10+
#include <zephyr/sys_clock.h>
11+
12+
/**
13+
* @brief Obtain a cooperative lock on the VPX vector registers
14+
*
15+
* This function is used to obtain a cooperative lock on the current CPU's
16+
* VPX vector registers before the calling thread uses them. Callers
17+
* attempting to obtain the cooperative lock must be already restricted to
18+
* executing on a single CPU, and continue to execute on that same CPU while
19+
* both waiting and holding the lock.
20+
*
21+
* This routine is not callable from an ISR.
22+
*
23+
* @param timeout Waiting period to obtain the lock, or one of the special
24+
* values K_NO_WAIT and K_FOREVER.
25+
*
26+
* @return Zero on success, otherwise error code
27+
*/
28+
int arc_vpx_lock(k_timeout_t timeout);
29+
30+
/**
31+
* @brief Release cooperative lock on the VPX vector registers
32+
*
33+
* This function is used to release the cooperative lock on the current CPU's
34+
* VPX vector registers. It is called after the current thread no longer needs
35+
* to use the VPX vector registers, thereby allowing another thread to use them.
36+
*
37+
* This routine is not callable from an ISR.
38+
*/
39+
void arc_vpx_unlock(void);
40+
41+
/**
42+
* @brief Release cooperative lock on a CPU's VPX vector registers
43+
*
44+
* This function is used to release the cooperative lock on the specified CPU's
45+
* VPX vector registers. This routine should not be used except by a system
46+
* monitor to release the cooperative lock in case the locking thread where it
47+
* is known that the locking thread is unable to release it (e.g. it was
48+
* aborted while holding the lock).
49+
*
50+
* @param cpu_id CPU ID of the VPX vector register set to be unlocked
51+
*/
52+
void arc_vpx_unlock_force(unsigned int cpu_id);
53+
54+
#endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_VPX_ARC_VPX_H_ */

0 commit comments

Comments
 (0)