Skip to content

Commit 6aa94b1

Browse files
agnerssonglongdaiduong
authored andcommitted
BACKPORT: ARM: 8991/1: use VFP assembler mnemonics if available
commit 2cbd1cc3dcd3e84be1fc1987da24b190ddf24a70 upstream. The integrated assembler of Clang 10 and earlier do not allow to access the VFP registers through the coprocessor load/store instructions: arch/arm/vfp/vfpmodule.c:342:2: error: invalid operand for instruction fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_DEX|FPEXC_FP2V|FPEXC_VV|FPEXC_TRAP_MASK)); ^ arch/arm/vfp/vfpinstr.h:79:6: note: expanded from macro 'fmxr' asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" ^ <inline asm>:1:6: note: instantiated into assembly here mcr p10, 7, r0, cr8, cr0, 0 @ fmxr FPEXC, r0 ^ This has been addressed with Clang 11 [0]. However, to support earlier versions of Clang and for better readability use of VFP assembler mnemonics still is preferred. Ideally we would replace this code with the unified assembler language mnemonics vmrs/vmsr on call sites along with .fpu assembler directives. The GNU assembler supports the .fpu directive at least since 2.17 (when documentation has been added). Since Linux requires binutils 2.21 it is safe to use .fpu directive. However, binutils does not allow to use FPINST or FPINST2 as an argument to vmrs/vmsr instructions up to binutils 2.24 (see binutils commit 16d02dc907c5): arch/arm/vfp/vfphw.S: Assembler messages: arch/arm/vfp/vfphw.S:162: Error: operand 0 must be FPSID or FPSCR pr FPEXC -- `vmsr FPINST,r6' arch/arm/vfp/vfphw.S:165: Error: operand 0 must be FPSID or FPSCR pr FPEXC -- `vmsr FPINST2,r8' arch/arm/vfp/vfphw.S:235: Error: operand 1 must be a VFP extension System Register -- `vmrs r3,FPINST' arch/arm/vfp/vfphw.S:238: Error: operand 1 must be a VFP extension System Register -- `vmrs r12,FPINST2' Use as-instr in Kconfig to check if FPINST/FPINST2 can be used. If they can be used make use of .fpu directives and UAL VFP mnemonics for register access. This allows to build vfpmodule.c with Clang and its integrated assembler. [0] https://reviews.llvm.org/D59733 Link: ClangBuiltLinux/linux#905 Signed-off-by: Stefan Agner <[email protected]> Signed-off-by: Russell King <[email protected]> [nd: Adjusted hunk from arch/arm/Kconfig due to missing commit 8a90a3228b6a ("arm: Unplug KVM from the build system"). Replace __ACCESS_VFP with fmrx/fmxr for arch/arm/kvm/switch.c. CONFIG_KVM was removed in commit 541ad0150ca4 ("arm: Remove 32bit KVM host support") in v5.7.1. CONFIG_KVM is not enabled as part of allmodconfig or alldefconfig, but axm55xx_defconfig explicitly does enable it. Adjusted arch/arm/vfp/vfphw.S due to conflict with commit a47b395 ("ARM: 9030/1: entry: omit FP emulation for UND exceptions taken in kernel mode").] Bug: 141693040 Signed-off-by: Nick Desaulniers <[email protected]> Change-Id: I84733bd8649784e1e636e107c1dac03ef7d48136
1 parent da5beb9 commit 6aa94b1

File tree

12 files changed

+48
-14
lines changed

12 files changed

+48
-14
lines changed

arch/arm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,3 +2167,4 @@ source "arch/arm/crypto/Kconfig"
21672167
endif
21682168

21692169
source "arch/arm/kvm/Kconfig"
2170+
source "arch/arm/Kconfig.assembler"

arch/arm/Kconfig.assembler

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
config AS_VFP_VMRS_FPINST
4+
def_bool $(as-instr,.fpu vfpv2\nvmrs r0$(comma)FPINST)
5+
help
6+
Supported by binutils >= 2.24 and LLVM integrated assembler.

arch/arm/include/asm/kvm_hyp.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414

1515
#define __hyp_text __section(.hyp.text) notrace
1616

17-
#define __ACCESS_VFP(CRn) \
18-
"mrc", "mcr", __stringify(p10, 7, %0, CRn, cr0, 0), u32
19-
2017
#define write_special(v, r) \
2118
asm volatile("msr " __stringify(r) ", %0" : : "r" (v))
2219
#define read_special(r) ({ \
@@ -79,8 +76,6 @@
7976
#define CNTV_CTL __ACCESS_CP15(c14, 0, c3, 1)
8077
#define CNTHCTL __ACCESS_CP15(c14, 4, c1, 0)
8178

82-
#define VFP_FPEXC __ACCESS_VFP(FPEXC)
83-
8479
/* AArch64 compatibility macros, only for the timer so far */
8580
#define read_sysreg_el0(r) read_sysreg(r##_EL0)
8681
#define write_sysreg_el0(v, r) write_sysreg(v, r##_EL0)

arch/arm/include/asm/vfp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
#ifndef __ASM_VFP_H
1010
#define __ASM_VFP_H
1111

12+
#ifndef CONFIG_AS_VFP_VMRS_FPINST
1213
#define FPSID cr0
1314
#define FPSCR cr1
1415
#define MVFR1 cr6
1516
#define MVFR0 cr7
1617
#define FPEXC cr8
1718
#define FPINST cr9
1819
#define FPINST2 cr10
20+
#endif
1921

2022
/* FPSID bits */
2123
#define FPSID_IMPLEMENTER_BIT (24)

arch/arm/include/asm/vfpmacros.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,24 @@
88

99
#include <asm/vfp.h>
1010

11-
@ Macros to allow building with old toolkits (with no VFP support)
11+
#ifdef CONFIG_AS_VFP_VMRS_FPINST
12+
.macro VFPFMRX, rd, sysreg, cond
13+
vmrs\cond \rd, \sysreg
14+
.endm
15+
16+
.macro VFPFMXR, sysreg, rd, cond
17+
vmsr\cond \sysreg, \rd
18+
.endm
19+
#else
20+
@ Macros to allow building with old toolkits (with no VFP support)
1221
.macro VFPFMRX, rd, sysreg, cond
1322
MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg
1423
.endm
1524

1625
.macro VFPFMXR, sysreg, rd, cond
1726
MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd
1827
.endm
28+
#endif
1929

2030
@ read all the working registers back into the VFP
2131
.macro VFPFLDMIA, base, tmp

arch/arm/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Makefile for Kernel-based Virtual Machine module
44
#
55

6-
plus_virt := $(call as-instr,.arch_extension virt,+virt)
6+
plus_virt := $(call as-instr,".cpu cortex-a7\n\n.arch_extension virt",+virt)
77
ifeq ($(plus_virt),+virt)
88
plus_virt_def := -DREQUIRES_VIRT=1
99
endif

arch/arm/kvm/hyp/switch.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <asm/kvm_asm.h>
99
#include <asm/kvm_hyp.h>
1010
#include <asm/kvm_mmu.h>
11+
#include "../../vfp/vfpinstr.h"
1112

1213
__asm__(".arch_extension virt");
1314

@@ -26,10 +27,10 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
2627
* trap to SVC. Therefore, always make sure that for 32-bit guests,
2728
* we set FPEXC.EN to prevent traps to SVC, when setting the TCP bits.
2829
*/
29-
val = read_sysreg(VFP_FPEXC);
30+
val = fmrx(FPEXC);
3031
*fpexc_host = val;
3132
if (!(val & FPEXC_EN)) {
32-
write_sysreg(val | FPEXC_EN, VFP_FPEXC);
33+
fmxr(FPEXC, val | FPEXC_EN);
3334
isb();
3435
}
3536

@@ -196,7 +197,7 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
196197
__vfp_restore_state(&host_ctxt->vfp);
197198
}
198199

199-
write_sysreg(fpexc, VFP_FPEXC);
200+
fmxr(FPEXC, fpexc);
200201

201202
return exit_code;
202203
}

arch/arm/kvm/hyp/vfp.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <asm/vfpmacros.h>
99

1010
.text
11+
.fpu vfpv2
1112
.pushsection .hyp.text, "ax"
1213

1314
/* void __vfp_save_state(struct vfp_hard_struct *vfp); */

arch/arm/kvm/init.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
*/
3636

3737
.text
38+
.arch_extension virt
3839
.pushsection .hyp.idmap.text,"ax"
3940
.align 5
4041
__kvm_hyp_init:

arch/arm/kvm/interrupts.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/linkage.h>
88

99
.text
10+
.arch_extension virt
1011

1112
/********************************************************************
1213
* Call function in Hyp mode

0 commit comments

Comments
 (0)