Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'arc-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

Pull ARC updates from Vineet Gupta:

- Support for DSP enabled userspace (save/restore regs)

- Misc other platform fixes

* tag 'arc-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
ARC: allow userspace DSP applications to use AGU extensions
ARC: add support for DSP-enabled userspace applications
ARC: handle DSP presence in HW
ARC: add helpers to sanitize config options
ARC: [plat-axs10x]: PGU: remove unused encoder-slave property

+332 -15
+49 -1
arch/arc/Kconfig
··· 401 401 default y 402 402 403 403 config ARC_HAS_ACCL_REGS 404 - bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)" 404 + bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6 and/or DSP)" 405 405 default y 406 406 help 407 407 Depending on the configuration, CPU can contain accumulator reg-pair 408 408 (also referred to as r58:r59). These can also be used by gcc as GPR so 409 409 kernel needs to save/restore per process 410 + 411 + config ARC_DSP_HANDLED 412 + def_bool n 413 + 414 + config ARC_DSP_SAVE_RESTORE_REGS 415 + def_bool n 416 + 417 + choice 418 + prompt "DSP support" 419 + default ARC_DSP_NONE 420 + help 421 + Depending on the configuration, CPU can contain DSP registers 422 + (ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_CTRL, DSP_FFT_CTRL). 423 + Bellow is options describing how to handle these registers in 424 + interrupt entry / exit and in context switch. 425 + 426 + config ARC_DSP_NONE 427 + bool "No DSP extension presence in HW" 428 + help 429 + No DSP extension presence in HW 430 + 431 + config ARC_DSP_KERNEL 432 + bool "DSP extension in HW, no support for userspace" 433 + select ARC_HAS_ACCL_REGS 434 + select ARC_DSP_HANDLED 435 + help 436 + DSP extension presence in HW, no support for DSP-enabled userspace 437 + applications. We don't save / restore DSP registers and only do 438 + some minimal preparations so userspace won't be able to break kernel 439 + 440 + config ARC_DSP_USERSPACE 441 + bool "Support DSP for userspace apps" 442 + select ARC_HAS_ACCL_REGS 443 + select ARC_DSP_HANDLED 444 + select ARC_DSP_SAVE_RESTORE_REGS 445 + help 446 + DSP extension presence in HW, support save / restore DSP registers to 447 + run DSP-enabled userspace applications 448 + 449 + config ARC_DSP_AGU_USERSPACE 450 + bool "Support DSP with AGU for userspace apps" 451 + select ARC_HAS_ACCL_REGS 452 + select ARC_DSP_HANDLED 453 + select ARC_DSP_SAVE_RESTORE_REGS 454 + help 455 + DSP and AGU extensions presence in HW, support save / restore DSP 456 + and AGU registers to run DSP-enabled userspace applications 457 + endchoice 410 458 411 459 config ARC_IRQ_NO_AUTOSAVE 412 460 bool "Disable hardware autosave regfile on interrupts"
-1
arch/arc/boot/dts/axs10x_mb.dtsi
··· 305 305 pgu@17000 { 306 306 compatible = "snps,arcpgu"; 307 307 reg = <0x17000 0x400>; 308 - encoder-slave = <&adv7511>; 309 308 clocks = <&pguclk>; 310 309 clock-names = "pxlclk"; 311 310 memory-region = <&frame_buffer>;
+26
arch/arc/include/asm/arcregs.h
··· 118 118 #define ARC_AUX_DPFP_2H 0x304 119 119 #define ARC_AUX_DPFP_STAT 0x305 120 120 121 + /* 122 + * DSP-related registers 123 + * Registers names must correspond to dsp_callee_regs structure fields names 124 + * for automatic offset calculation in DSP_AUX_SAVE_RESTORE macros. 125 + */ 126 + #define ARC_AUX_DSP_BUILD 0x7A 127 + #define ARC_AUX_ACC0_LO 0x580 128 + #define ARC_AUX_ACC0_GLO 0x581 129 + #define ARC_AUX_ACC0_HI 0x582 130 + #define ARC_AUX_ACC0_GHI 0x583 131 + #define ARC_AUX_DSP_BFLY0 0x598 132 + #define ARC_AUX_DSP_CTRL 0x59F 133 + #define ARC_AUX_DSP_FFT_CTRL 0x59E 134 + 135 + #define ARC_AUX_AGU_BUILD 0xCC 136 + #define ARC_AUX_AGU_AP0 0x5C0 137 + #define ARC_AUX_AGU_AP1 0x5C1 138 + #define ARC_AUX_AGU_AP2 0x5C2 139 + #define ARC_AUX_AGU_AP3 0x5C3 140 + #define ARC_AUX_AGU_OS0 0x5D0 141 + #define ARC_AUX_AGU_OS1 0x5D1 142 + #define ARC_AUX_AGU_MOD0 0x5E0 143 + #define ARC_AUX_AGU_MOD1 0x5E1 144 + #define ARC_AUX_AGU_MOD2 0x5E2 145 + #define ARC_AUX_AGU_MOD3 0x5E3 146 + 121 147 #ifndef __ASSEMBLY__ 122 148 123 149 #include <soc/arc/aux.h>
+34
arch/arc/include/asm/asserts.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com) 4 + * 5 + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> 6 + */ 7 + #ifndef __ASM_ARC_ASSERTS_H 8 + #define __ASM_ARC_ASSERTS_H 9 + 10 + /* Helpers to sanitize config options. */ 11 + 12 + void chk_opt_strict(char *opt_name, bool hw_exists, bool opt_ena); 13 + void chk_opt_weak(char *opt_name, bool hw_exists, bool opt_ena); 14 + 15 + /* 16 + * Check required config option: 17 + * - panic in case of OPT enabled but corresponding HW absent. 18 + * - warn in case of OPT disabled but corresponding HW exists. 19 + */ 20 + #define CHK_OPT_STRICT(opt_name, hw_exists) \ 21 + ({ \ 22 + chk_opt_strict(#opt_name, hw_exists, IS_ENABLED(opt_name)); \ 23 + }) 24 + 25 + /* 26 + * Check optional config option: 27 + * - panic in case of OPT enabled but corresponding HW absent. 28 + */ 29 + #define CHK_OPT_WEAK(opt_name, hw_exists) \ 30 + ({ \ 31 + chk_opt_weak(#opt_name, hw_exists, IS_ENABLED(opt_name)); \ 32 + }) 33 + 34 + #endif /* __ASM_ARC_ASSERTS_H */
+150
arch/arc/include/asm/dsp-impl.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com) 4 + * 5 + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> 6 + */ 7 + #ifndef __ASM_ARC_DSP_IMPL_H 8 + #define __ASM_ARC_DSP_IMPL_H 9 + 10 + #include <asm/dsp.h> 11 + 12 + #define DSP_CTRL_DISABLED_ALL 0 13 + 14 + #ifdef __ASSEMBLY__ 15 + 16 + /* clobbers r5 register */ 17 + .macro DSP_EARLY_INIT 18 + lr r5, [ARC_AUX_DSP_BUILD] 19 + bmsk r5, r5, 7 20 + breq r5, 0, 1f 21 + mov r5, DSP_CTRL_DISABLED_ALL 22 + sr r5, [ARC_AUX_DSP_CTRL] 23 + 1: 24 + .endm 25 + 26 + /* clobbers r10, r11 registers pair */ 27 + .macro DSP_SAVE_REGFILE_IRQ 28 + #if defined(CONFIG_ARC_DSP_KERNEL) 29 + /* 30 + * Drop any changes to DSP_CTRL made by userspace so userspace won't be 31 + * able to break kernel - reset it to DSP_CTRL_DISABLED_ALL value 32 + */ 33 + mov r10, DSP_CTRL_DISABLED_ALL 34 + sr r10, [ARC_AUX_DSP_CTRL] 35 + 36 + #elif defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS) 37 + /* 38 + * Save DSP_CTRL register and reset it to value suitable for kernel 39 + * (DSP_CTRL_DISABLED_ALL) 40 + */ 41 + mov r10, DSP_CTRL_DISABLED_ALL 42 + aex r10, [ARC_AUX_DSP_CTRL] 43 + st r10, [sp, PT_DSP_CTRL] 44 + 45 + #endif 46 + .endm 47 + 48 + /* clobbers r10, r11 registers pair */ 49 + .macro DSP_RESTORE_REGFILE_IRQ 50 + #if defined(CONFIG_ARC_DSP_SAVE_RESTORE_REGS) 51 + ld r10, [sp, PT_DSP_CTRL] 52 + sr r10, [ARC_AUX_DSP_CTRL] 53 + 54 + #endif 55 + .endm 56 + 57 + #else /* __ASEMBLY__ */ 58 + 59 + #include <linux/sched.h> 60 + #include <asm/asserts.h> 61 + #include <asm/switch_to.h> 62 + 63 + #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 64 + 65 + /* 66 + * As we save new and restore old AUX register value in the same place we 67 + * can optimize a bit and use AEX instruction (swap contents of an auxiliary 68 + * register with a core register) instead of LR + SR pair. 69 + */ 70 + #define AUX_SAVE_RESTORE(_saveto, _readfrom, _offt, _aux) \ 71 + do { \ 72 + long unsigned int _scratch; \ 73 + \ 74 + __asm__ __volatile__( \ 75 + "ld %0, [%2, %4] \n" \ 76 + "aex %0, [%3] \n" \ 77 + "st %0, [%1, %4] \n" \ 78 + : \ 79 + "=&r" (_scratch) /* must be early clobber */ \ 80 + : \ 81 + "r" (_saveto), \ 82 + "r" (_readfrom), \ 83 + "Ir" (_aux), \ 84 + "Ir" (_offt) \ 85 + : \ 86 + "memory" \ 87 + ); \ 88 + } while (0) 89 + 90 + #define DSP_AUX_SAVE_RESTORE(_saveto, _readfrom, _aux) \ 91 + AUX_SAVE_RESTORE(_saveto, _readfrom, \ 92 + offsetof(struct dsp_callee_regs, _aux), \ 93 + ARC_AUX_##_aux) 94 + 95 + static inline void dsp_save_restore(struct task_struct *prev, 96 + struct task_struct *next) 97 + { 98 + long unsigned int *saveto = &prev->thread.dsp.ACC0_GLO; 99 + long unsigned int *readfrom = &next->thread.dsp.ACC0_GLO; 100 + 101 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GLO); 102 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, ACC0_GHI); 103 + 104 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_BFLY0); 105 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, DSP_FFT_CTRL); 106 + 107 + #ifdef CONFIG_ARC_DSP_AGU_USERSPACE 108 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP0); 109 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP1); 110 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP2); 111 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_AP3); 112 + 113 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS0); 114 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_OS1); 115 + 116 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD0); 117 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD1); 118 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD2); 119 + DSP_AUX_SAVE_RESTORE(saveto, readfrom, AGU_MOD3); 120 + #endif /* CONFIG_ARC_DSP_AGU_USERSPACE */ 121 + } 122 + 123 + #else /* !CONFIG_ARC_DSP_SAVE_RESTORE_REGS */ 124 + #define dsp_save_restore(p, n) 125 + #endif /* CONFIG_ARC_DSP_SAVE_RESTORE_REGS */ 126 + 127 + static inline bool dsp_exist(void) 128 + { 129 + struct bcr_generic bcr; 130 + 131 + READ_BCR(ARC_AUX_DSP_BUILD, bcr); 132 + return !!bcr.ver; 133 + } 134 + 135 + static inline bool agu_exist(void) 136 + { 137 + struct bcr_generic bcr; 138 + 139 + READ_BCR(ARC_AUX_AGU_BUILD, bcr); 140 + return !!bcr.ver; 141 + } 142 + 143 + static inline void dsp_config_check(void) 144 + { 145 + CHK_OPT_STRICT(CONFIG_ARC_DSP_HANDLED, dsp_exist()); 146 + CHK_OPT_WEAK(CONFIG_ARC_DSP_AGU_USERSPACE, agu_exist()); 147 + } 148 + 149 + #endif /* __ASEMBLY__ */ 150 + #endif /* __ASM_ARC_DSP_IMPL_H */
+29
arch/arc/include/asm/dsp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com) 4 + * 5 + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> 6 + */ 7 + #ifndef __ASM_ARC_DSP_H 8 + #define __ASM_ARC_DSP_H 9 + 10 + #ifndef __ASSEMBLY__ 11 + 12 + /* 13 + * DSP-related saved registers - need to be saved only when you are 14 + * scheduled out. 15 + * structure fields name must correspond to aux register defenitions for 16 + * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros 17 + */ 18 + struct dsp_callee_regs { 19 + unsigned long ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_FFT_CTRL; 20 + #ifdef CONFIG_ARC_DSP_AGU_USERSPACE 21 + unsigned long AGU_AP0, AGU_AP1, AGU_AP2, AGU_AP3; 22 + unsigned long AGU_OS0, AGU_OS1; 23 + unsigned long AGU_MOD0, AGU_MOD1, AGU_MOD2, AGU_MOD3; 24 + #endif 25 + }; 26 + 27 + #endif /* !__ASSEMBLY__ */ 28 + 29 + #endif /* __ASM_ARC_DSP_H */
+6
arch/arc/include/asm/entry-arcv2.h
··· 4 4 #define __ASM_ARC_ENTRY_ARCV2_H 5 5 6 6 #include <asm/asm-offsets.h> 7 + #include <asm/dsp-impl.h> 7 8 #include <asm/irqflags-arcv2.h> 8 9 #include <asm/thread_info.h> /* For THREAD_SIZE */ 9 10 ··· 166 165 ST2 r58, r59, PT_r58 167 166 #endif 168 167 168 + /* clobbers r10, r11 registers pair */ 169 + DSP_SAVE_REGFILE_IRQ 169 170 .endm 170 171 171 172 /*------------------------------------------------------------------------*/ ··· 191 188 #ifdef CONFIG_ARC_CURR_IN_REG 192 189 ld r25, [sp, PT_user_r25] 193 190 #endif 191 + 192 + /* clobbers r10, r11 registers pair */ 193 + DSP_RESTORE_REGFILE_IRQ 194 194 195 195 #ifdef CONFIG_ARC_HAS_ACCL_REGS 196 196 LD2 r58, r59, PT_r58
+4
arch/arc/include/asm/processor.h
··· 14 14 #ifndef __ASSEMBLY__ 15 15 16 16 #include <asm/ptrace.h> 17 + #include <asm/dsp.h> 17 18 #include <asm/fpu.h> 18 19 19 20 #ifdef CONFIG_ARC_PLAT_EZNPS ··· 32 31 unsigned long ksp; /* kernel mode stack pointer */ 33 32 unsigned long callee_reg; /* pointer to callee regs */ 34 33 unsigned long fault_address; /* dbls as brkpt holder as well */ 34 + #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 35 + struct dsp_callee_regs dsp; 36 + #endif 35 37 #ifdef CONFIG_ARC_FPU_SAVE_RESTORE 36 38 struct arc_fpu fpu; 37 39 #endif
+3
arch/arc/include/asm/ptrace.h
··· 91 91 #ifdef CONFIG_ARC_HAS_ACCL_REGS 92 92 unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */ 93 93 #endif 94 + #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 95 + unsigned long DSP_CTRL; 96 + #endif 94 97 95 98 /*------- Below list auto saved by h/w -----------*/ 96 99 unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
+2
arch/arc/include/asm/switch_to.h
··· 9 9 #ifndef __ASSEMBLY__ 10 10 11 11 #include <linux/sched.h> 12 + #include <asm/dsp-impl.h> 12 13 #include <asm/fpu.h> 13 14 14 15 #ifdef CONFIG_ARC_PLAT_EZNPS ··· 25 24 #define switch_to(prev, next, last) \ 26 25 do { \ 27 26 ARC_EZNPS_DP_PREV(prev, next); \ 27 + dsp_save_restore(prev, next); \ 28 28 fpu_save_restore(prev, next); \ 29 29 last = __switch_to(prev, next);\ 30 30 mb(); \
+4
arch/arc/kernel/asm-offsets.c
··· 12 12 #include <asm/hardirq.h> 13 13 #include <asm/page.h> 14 14 15 + 15 16 int main(void) 16 17 { 17 18 DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); ··· 75 74 #ifdef CONFIG_ARC_HAS_ACCL_REGS 76 75 OFFSET(PT_r58, pt_regs, r58); 77 76 OFFSET(PT_r59, pt_regs, r59); 77 + #endif 78 + #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS 79 + OFFSET(PT_DSP_CTRL, pt_regs, DSP_CTRL); 78 80 #endif 79 81 80 82 return 0;
+4
arch/arc/kernel/head.S
··· 14 14 #include <asm/entry.h> 15 15 #include <asm/arcregs.h> 16 16 #include <asm/cache.h> 17 + #include <asm/dsp-impl.h> 17 18 #include <asm/irqflags.h> 18 19 19 20 .macro CPU_EARLY_SETUP ··· 60 59 #endif 61 60 kflag r5 62 61 #endif 62 + ; Config DSP_CTRL properly, so kernel may use integer multiply, 63 + ; multiply-accumulate, and divide operations 64 + DSP_EARLY_INIT 63 65 .endm 64 66 65 67 .section .init.text, "ax",@progbits
+21 -13
arch/arc/kernel/setup.c
··· 19 19 #include <uapi/linux/mount.h> 20 20 #include <asm/sections.h> 21 21 #include <asm/arcregs.h> 22 + #include <asm/asserts.h> 22 23 #include <asm/tlb.h> 23 24 #include <asm/setup.h> 24 25 #include <asm/page.h> ··· 27 26 #include <asm/unwind.h> 28 27 #include <asm/mach_desc.h> 29 28 #include <asm/smp.h> 29 + #include <asm/dsp-impl.h> 30 30 31 31 #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) 32 32 ··· 391 389 return buf; 392 390 } 393 391 392 + void chk_opt_strict(char *opt_name, bool hw_exists, bool opt_ena) 393 + { 394 + if (hw_exists && !opt_ena) 395 + pr_warn(" ! Enable %s for working apps\n", opt_name); 396 + else if (!hw_exists && opt_ena) 397 + panic("Disable %s, hardware NOT present\n", opt_name); 398 + } 399 + 400 + void chk_opt_weak(char *opt_name, bool hw_exists, bool opt_ena) 401 + { 402 + if (!hw_exists && opt_ena) 403 + panic("Disable %s, hardware NOT present\n", opt_name); 404 + } 405 + 394 406 static void arc_chk_core_config(void) 395 407 { 396 408 struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; 397 - int saved = 0, present = 0; 398 - char *opt_nm = NULL; 409 + int present = 0; 399 410 400 411 if (!cpu->extn.timer0) 401 412 panic("Timer0 is not present!\n"); ··· 440 425 */ 441 426 442 427 if (is_isa_arcompact()) { 443 - opt_nm = "CONFIG_ARC_FPU_SAVE_RESTORE"; 444 - saved = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE); 445 - 446 428 /* only DPDP checked since SP has no arch visible regs */ 447 429 present = cpu->extn.fpu_dp; 430 + CHK_OPT_STRICT(CONFIG_ARC_FPU_SAVE_RESTORE, present); 448 431 } else { 449 - opt_nm = "CONFIG_ARC_HAS_ACCL_REGS"; 450 - saved = IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS); 451 - 452 432 /* Accumulator Low:High pair (r58:59) present if DSP MPY or FPU */ 453 433 present = cpu->extn_mpy.dsp | cpu->extn.fpu_sp | cpu->extn.fpu_dp; 454 - } 434 + CHK_OPT_STRICT(CONFIG_ARC_HAS_ACCL_REGS, present); 455 435 456 - if (present && !saved) 457 - pr_warn("Enable %s for working apps\n", opt_nm); 458 - else if (!present && saved) 459 - panic("Disable %s, hardware NOT present\n", opt_nm); 436 + dsp_config_check(); 437 + } 460 438 } 461 439 462 440 /*