Commit 7321e2ea authored by Eugeniy Paltsev's avatar Eugeniy Paltsev Committed by Vineet Gupta
Browse files

ARC: add support for DSP-enabled userspace applications



To be able to run DSP-enabled userspace applications we need to
save and restore following DSP-related registers:
At IRQ/exception entry/exit:
 * DSP_CTRL (save it and reset to value suitable for kernel)
 * ACC0_LO, ACC0_HI (we already save them as r58, r59 pair)
At context switch:
 * ACC0_GLO, ACC0_GHI
 * DSP_BFLY0, DSP_FFT_CTRL

Reviewed-by: default avatarVineet Gupta <vgupta@synopsys.com>
Signed-off-by: default avatarEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 4827d0cf
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -411,6 +411,9 @@ config ARC_HAS_ACCL_REGS
config ARC_DSP_HANDLED
	def_bool n

config ARC_DSP_SAVE_RESTORE_REGS
	def_bool n

choice
	prompt "DSP support"
	default ARC_DSP_NONE
@@ -433,6 +436,15 @@ config ARC_DSP_KERNEL
	  DSP extension presence in HW, no support for DSP-enabled userspace
	  applications. We don't save / restore DSP registers and only do
	  some minimal preparations so userspace won't be able to break kernel

config ARC_DSP_USERSPACE
	bool "Support DSP for userspace apps"
	select ARC_HAS_ACCL_REGS
	select ARC_DSP_HANDLED
	select ARC_DSP_SAVE_RESTORE_REGS
	help
	  DSP extension presence in HW, support save / restore DSP registers to
	  run DSP-enabled userspace applications
endchoice

config ARC_IRQ_NO_AUTOSAVE
+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@

/*
 * DSP-related registers
 * Registers names must correspond to dsp_callee_regs structure fields names
 * for automatic offset calculation in DSP_AUX_SAVE_RESTORE macros.
 */
#define ARC_AUX_DSP_BUILD	0x7A
#define ARC_AUX_ACC0_LO		0x580
+73 −1
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
#ifndef __ASM_ARC_DSP_IMPL_H
#define __ASM_ARC_DSP_IMPL_H

#include <asm/dsp.h>

#define DSP_CTRL_DISABLED_ALL		0

#ifdef __ASSEMBLY__
@@ -30,12 +32,82 @@
	 */
	mov	r10, DSP_CTRL_DISABLED_ALL
	sr	r10, [ARC_AUX_DSP_CTRL]
#endif /* ARC_DSP_KERNEL */

#elif defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
	/*
	 * Save DSP_CTRL register and reset it to value suitable for kernel
	 * (DSP_CTRL_DISABLED_ALL)
	 */
	mov	r10, DSP_CTRL_DISABLED_ALL
	aex	r10, [ARC_AUX_DSP_CTRL]
	st	r10, [sp, PT_DSP_CTRL]

#endif
.endm

/* clobbers r10, r11 registers pair */
.macro DSP_RESTORE_REGFILE_IRQ
#if defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS)
	ld	r10, [sp, PT_DSP_CTRL]
	sr	r10, [ARC_AUX_DSP_CTRL]

#endif
.endm

#else /* __ASEMBLY__ */

#include <linux/sched.h>
#include <asm/asserts.h>
#include <asm/switch_to.h>

#ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS

/*
 * As we save new and restore old AUX register value in the same place we
 * can optimize a bit and use AEX instruction (swap contents of an auxiliary
 * register with a core register) instead of LR + SR pair.
 */
#define AUX_SAVE_RESTORE(_saveto, _readfrom, _offt, _aux)		\
do {									\
	long unsigned int _scratch;					\
									\
	__asm__ __volatile__(						\
		"ld	%0, [%2, %4]			\n"		\
		"aex	%0, [%3]			\n"		\
		"st	%0, [%1, %4]			\n"		\
		:							\
		  "=&r" (_scratch)	/* must be early clobber */	\
		:							\
		   "r" (_saveto),					\
		   "r" (_readfrom),					\
		   "Ir" (_aux),						\
		   "Ir" (_offt)						\
		:							\
		  "memory"						\
	);								\
} while (0)

#define DSP_AUX_SAVE_RESTORE(_saveto, _readfrom, _aux)			\
	AUX_SAVE_RESTORE(_saveto, _readfrom,				\
		offsetof(struct dsp_callee_regs, _aux),			\
		ARC_AUX_##_aux)

static inline void dsp_save_restore(struct task_struct *prev,
					struct task_struct *next)
{
	long unsigned int *saveto = &prev->thread.dsp.ACC0_GLO;
	long unsigned int *readfrom = &next->thread.dsp.ACC0_GLO;

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GLO);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GHI);

	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_BFLY0);
	DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_FFT_CTRL);
}

#else /* !CONFIG_ARC_DSP_SAVE_RESTORE_REGS */
#define dsp_save_restore(p, n)
#endif /* CONFIG_ARC_DSP_SAVE_RESTORE_REGS */

static inline bool dsp_exist(void)
{
+24 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
 *
 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 */
#ifndef __ASM_ARC_DSP_H
#define __ASM_ARC_DSP_H

#ifndef __ASSEMBLY__

/*
 * DSP-related saved registers - need to be saved only when you are
 * scheduled out.
 * structure fields name must correspond to aux register defenitions for
 * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros
 */
struct dsp_callee_regs {
	unsigned long ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_FFT_CTRL;
};

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_ARC_DSP_H */
+3 −0
Original line number Diff line number Diff line
@@ -192,6 +192,9 @@
	ld	r25, [sp, PT_user_r25]
#endif

	/* clobbers r10, r11 registers pair */
	DSP_RESTORE_REGFILE_IRQ

#ifdef CONFIG_ARC_HAS_ACCL_REGS
	LD2	r58, r59, PT_r58
#endif
Loading