diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9a7cd1fbc0cf..197826176e20 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2167,3 +2167,4 @@ source "arch/arm/crypto/Kconfig" endif source "arch/arm/kvm/Kconfig" +source "arch/arm/Kconfig.assembler" diff --git a/arch/arm/Kconfig.assembler b/arch/arm/Kconfig.assembler new file mode 100644 index 000000000000..5cb31aae1188 --- /dev/null +++ b/arch/arm/Kconfig.assembler @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +config AS_VFP_VMRS_FPINST + def_bool $(as-instr,.fpu vfpv2\nvmrs r0$(comma)FPINST) + help + Supported by binutils >= 2.24 and LLVM integrated assembler. diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h index 40e9034db601..316320684ea7 100644 --- a/arch/arm/include/asm/kvm_hyp.h +++ b/arch/arm/include/asm/kvm_hyp.h @@ -14,9 +14,6 @@ #define __hyp_text __section(.hyp.text) notrace -#define __ACCESS_VFP(CRn) \ - "mrc", "mcr", __stringify(p10, 7, %0, CRn, cr0, 0), u32 - #define write_special(v, r) \ asm volatile("msr " __stringify(r) ", %0" : : "r" (v)) #define read_special(r) ({ \ @@ -79,8 +76,6 @@ #define CNTV_CTL __ACCESS_CP15(c14, 0, c3, 1) #define CNTHCTL __ACCESS_CP15(c14, 4, c1, 0) -#define VFP_FPEXC __ACCESS_VFP(FPEXC) - /* AArch64 compatibility macros, only for the timer so far */ #define read_sysreg_el0(r) read_sysreg(r##_EL0) #define write_sysreg_el0(v, r) write_sysreg(v, r##_EL0) diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h index 7157d2a30a49..19928bfb4f9c 100644 --- a/arch/arm/include/asm/vfp.h +++ b/arch/arm/include/asm/vfp.h @@ -9,6 +9,7 @@ #ifndef __ASM_VFP_H #define __ASM_VFP_H +#ifndef CONFIG_AS_VFP_VMRS_FPINST #define FPSID cr0 #define FPSCR cr1 #define MVFR1 cr6 @@ -16,6 +17,7 @@ #define FPEXC cr8 #define FPINST cr9 #define FPINST2 cr10 +#endif /* FPSID bits */ #define FPSID_IMPLEMENTER_BIT (24) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 947ee5395e1f..ba0d4cb5377e 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -8,7 +8,16 @@ #include -@ Macros to allow building with old toolkits (with no VFP support) +#ifdef CONFIG_AS_VFP_VMRS_FPINST + .macro VFPFMRX, rd, sysreg, cond + vmrs\cond \rd, \sysreg + .endm + + .macro VFPFMXR, sysreg, rd, cond + vmsr\cond \sysreg, \rd + .endm +#else + @ Macros to allow building with old toolkits (with no VFP support) .macro VFPFMRX, rd, sysreg, cond MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg .endm @@ -16,6 +25,7 @@ .macro VFPFMXR, sysreg, rd, cond MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd .endm +#endif @ read all the working registers back into the VFP .macro VFPFLDMIA, base, tmp diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index b76b75bd9e00..5df9dbd5bf20 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -3,7 +3,7 @@ # Makefile for Kernel-based Virtual Machine module # -plus_virt := $(call as-instr,.arch_extension virt,+virt) +plus_virt := $(call as-instr,".cpu cortex-a7\n\n.arch_extension virt",+virt) ifeq ($(plus_virt),+virt) plus_virt_def := -DREQUIRES_VIRT=1 endif diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c index 1efeef3fd0ee..f5b27694ece2 100644 --- a/arch/arm/kvm/hyp/switch.c +++ b/arch/arm/kvm/hyp/switch.c @@ -8,6 +8,7 @@ #include #include #include +#include "../../vfp/vfpinstr.h" __asm__(".arch_extension virt"); @@ -26,10 +27,10 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host) * trap to SVC. Therefore, always make sure that for 32-bit guests, * we set FPEXC.EN to prevent traps to SVC, when setting the TCP bits. */ - val = read_sysreg(VFP_FPEXC); + val = fmrx(FPEXC); *fpexc_host = val; if (!(val & FPEXC_EN)) { - write_sysreg(val | FPEXC_EN, VFP_FPEXC); + fmxr(FPEXC, val | FPEXC_EN); isb(); } @@ -196,7 +197,7 @@ again: __vfp_restore_state(&host_ctxt->vfp); } - write_sysreg(fpexc, VFP_FPEXC); + fmxr(FPEXC, fpexc); return exit_code; } diff --git a/arch/arm/kvm/hyp/vfp.S b/arch/arm/kvm/hyp/vfp.S index 675a52348d8d..0870dfe93e93 100644 --- a/arch/arm/kvm/hyp/vfp.S +++ b/arch/arm/kvm/hyp/vfp.S @@ -8,6 +8,7 @@ #include .text + .fpu vfpv2 .pushsection .hyp.text, "ax" /* void __vfp_save_state(struct vfp_hard_struct *vfp); */ diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S index 33e34b6d24b2..4a8b25f3a6b6 100644 --- a/arch/arm/kvm/init.S +++ b/arch/arm/kvm/init.S @@ -35,6 +35,7 @@ */ .text + .arch_extension virt .pushsection .hyp.idmap.text,"ax" .align 5 __kvm_hyp_init: diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index 064f4f118ca7..76416521e06b 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -7,6 +7,7 @@ #include .text + .arch_extension virt /******************************************************************** * Call function in Hyp mode diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 772c6a3b1f72..d5837bf05a9a 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -78,6 +78,7 @@ ENTRY(vfp_support_entry) DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 + .fpu vfpv2 VFPFMRX r1, FPEXC @ Is the VFP enabled? DBGSTR1 "fpexc %08x", r1 tst r1, #FPEXC_EN diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h index 38dc154e39ff..3c7938fd40aa 100644 --- a/arch/arm/vfp/vfpinstr.h +++ b/arch/arm/vfp/vfpinstr.h @@ -62,10 +62,23 @@ #define FPSCR_C (1 << 29) #define FPSCR_V (1 << 28) -/* - * Since we aren't building with -mfpu=vfp, we need to code - * these instructions using their MRC/MCR equivalents. - */ +#ifdef CONFIG_AS_VFP_VMRS_FPINST + +#define fmrx(_vfp_) ({ \ + u32 __v; \ + asm(".fpu vfpv2\n" \ + "vmrs %0, " #_vfp_ \ + : "=r" (__v) : : "cc"); \ + __v; \ + }) + +#define fmxr(_vfp_,_var_) \ + asm(".fpu vfpv2\n" \ + "vmsr " #_vfp_ ", %0" \ + : : "r" (_var_) : "cc") + +#else + #define vfpreg(_vfp_) #_vfp_ #define fmrx(_vfp_) ({ \ @@ -79,6 +92,8 @@ asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \ : : "r" (_var_) : "cc") +#endif + u32 vfp_single_cpdo(u32 inst, u32 fpscr); u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);