Skip to content

Commit 1b85d92

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/misc-6.16 into kvmarm-master/next
* kvm-arm64/misc-6.16: : . : Misc changes and improvements for 6.16: : : - Add a new selftest for the SVE host state being corrupted by a guest : : - Keep HCR_EL2.xMO set at all times for systems running with the kernel at EL2, : ensuring that the window for interrupts is slightly bigger, and avoiding : a pretty bad erratum on the AmpereOne HW : : - Replace a couple of open-coded on/off strings with str_on_off() : : - Get rid of the pKVM memblock sorting, which now appears to be superflous : : - Drop superflous clearing of ICH_LR_EOI in the LR when nesting : : - Add workaround for AmpereOne's erratum AC04_CPU_23, which suffers from : a pretty bad case of TLB corruption unless accesses to HCR_EL2 are : heavily synchronised : : - Add a per-VM, per-ITS debugfs entry to dump the state of the ITS tables : in a human-friendly fashion : . KVM: arm64: Fix documentation for vgic_its_iter_next() KVM: arm64: vgic-its: Add debugfs interface to expose ITS tables arm64: errata: Work around AmpereOne's erratum AC04_CPU_23 KVM: arm64: nv: Remove clearing of ICH_LR<n>.EOI if ICH_LR<n>.HW == 1 KVM: arm64: Drop sort_memblock_regions() KVM: arm64: selftests: Add test for SVE host corruption KVM: arm64: Force HCR_EL2.xMO to 1 at all times in VHE mode KVM: arm64: Replace ternary flags with str_on_off() helper Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 7f3225f + bf809a0 commit 1b85d92

File tree

26 files changed

+496
-89
lines changed

26 files changed

+496
-89
lines changed

Documentation/arch/arm64/silicon-errata.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ stable kernels.
5757
+----------------+-----------------+-----------------+-----------------------------+
5858
| Ampere | AmpereOne AC04 | AC04_CPU_10 | AMPERE_ERRATUM_AC03_CPU_38 |
5959
+----------------+-----------------+-----------------+-----------------------------+
60+
| Ampere | AmpereOne AC04 | AC04_CPU_23 | AMPERE_ERRATUM_AC04_CPU_23 |
61+
+----------------+-----------------+-----------------+-----------------------------+
6062
+----------------+-----------------+-----------------+-----------------------------+
6163
| ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 |
6264
+----------------+-----------------+-----------------+-----------------------------+

arch/arm64/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,23 @@ config AMPERE_ERRATUM_AC03_CPU_38
464464

465465
If unsure, say Y.
466466

467+
config AMPERE_ERRATUM_AC04_CPU_23
468+
bool "AmpereOne: AC04_CPU_23: Failure to synchronize writes to HCR_EL2 may corrupt address translations."
469+
default y
470+
help
471+
This option adds an alternative code sequence to work around Ampere
472+
errata AC04_CPU_23 on AmpereOne.
473+
474+
Updates to HCR_EL2 can rarely corrupt simultaneous translations for
475+
data addresses initiated by load/store instructions. Only
476+
instruction initiated translations are vulnerable, not translations
477+
from prefetches for example. A DSB before the store to HCR_EL2 is
478+
sufficient to prevent older instructions from hitting the window
479+
for corruption, and an ISB after is sufficient to prevent younger
480+
instructions from hitting the window for corruption.
481+
482+
If unsure, say Y.
483+
467484
config ARM64_WORKAROUND_CLEAN_CACHE
468485
bool
469486

arch/arm64/include/asm/el2_setup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
orr x0, x0, #HCR_E2H
4040
.LnVHE_\@:
41-
msr hcr_el2, x0
41+
msr_hcr_el2 x0
4242
isb
4343
.endm
4444

arch/arm64/include/asm/hardirq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ do { \
4141
\
4242
___hcr = read_sysreg(hcr_el2); \
4343
if (!(___hcr & HCR_TGE)) { \
44-
write_sysreg(___hcr | HCR_TGE, hcr_el2); \
44+
write_sysreg_hcr(___hcr | HCR_TGE); \
4545
isb(); \
4646
} \
4747
/* \
@@ -82,7 +82,7 @@ do { \
8282
*/ \
8383
barrier(); \
8484
if (!___ctx->cnt && !(___hcr & HCR_TGE)) \
85-
write_sysreg(___hcr, hcr_el2); \
85+
write_sysreg_hcr(___hcr); \
8686
} while (0)
8787

8888
static inline void ack_bad_irq(unsigned int irq)

arch/arm64/include/asm/kvm_arm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3 | HCR_TID1)
104104
#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)
105105
#define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
106-
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
106+
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H | HCR_AMO | HCR_IMO | HCR_FMO)
107107

108108
#define HCRX_HOST_FLAGS (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En | HCRX_EL2_EnFPM)
109109
#define MPAMHCR_HOST_FLAGS 0

arch/arm64/include/asm/sysreg.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,15 @@
10931093
__emit_inst(0xd5000000|(\sreg)|(.L__gpr_num_\rt))
10941094
.endm
10951095

1096+
.macro msr_hcr_el2, reg
1097+
#if IS_ENABLED(CONFIG_AMPERE_ERRATUM_AC04_CPU_23)
1098+
dsb nsh
1099+
msr hcr_el2, \reg
1100+
isb
1101+
#else
1102+
msr hcr_el2, \reg
1103+
#endif
1104+
.endm
10961105
#else
10971106

10981107
#include <linux/bitfield.h>
@@ -1180,13 +1189,31 @@
11801189
write_sysreg(__scs_new, sysreg); \
11811190
} while (0)
11821191

1192+
#define sysreg_clear_set_hcr(clear, set) do { \
1193+
u64 __scs_val = read_sysreg(hcr_el2); \
1194+
u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
1195+
if (__scs_new != __scs_val) \
1196+
write_sysreg_hcr(__scs_new); \
1197+
} while (0)
1198+
11831199
#define sysreg_clear_set_s(sysreg, clear, set) do { \
11841200
u64 __scs_val = read_sysreg_s(sysreg); \
11851201
u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
11861202
if (__scs_new != __scs_val) \
11871203
write_sysreg_s(__scs_new, sysreg); \
11881204
} while (0)
11891205

1206+
#define write_sysreg_hcr(__val) do { \
1207+
if (IS_ENABLED(CONFIG_AMPERE_ERRATUM_AC04_CPU_23) && \
1208+
(!system_capabilities_finalized() || \
1209+
alternative_has_cap_unlikely(ARM64_WORKAROUND_AMPERE_AC04_CPU_23))) \
1210+
asm volatile("dsb nsh; msr hcr_el2, %x0; isb" \
1211+
: : "rZ" (__val)); \
1212+
else \
1213+
asm volatile("msr hcr_el2, %x0" \
1214+
: : "rZ" (__val)); \
1215+
} while (0)
1216+
11901217
#define read_sysreg_par() ({ \
11911218
u64 par; \
11921219
asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412)); \

arch/arm64/kernel/cpu_errata.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,13 @@ static const struct midr_range erratum_ac03_cpu_38_list[] = {
557557
};
558558
#endif
559559

560+
#ifdef CONFIG_AMPERE_ERRATUM_AC04_CPU_23
561+
static const struct midr_range erratum_ac04_cpu_23_list[] = {
562+
MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
563+
{},
564+
};
565+
#endif
566+
560567
const struct arm64_cpu_capabilities arm64_errata[] = {
561568
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
562569
{
@@ -875,6 +882,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
875882
.capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38,
876883
ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_38_list),
877884
},
885+
#endif
886+
#ifdef CONFIG_AMPERE_ERRATUM_AC04_CPU_23
887+
{
888+
.desc = "AmpereOne erratum AC04_CPU_23",
889+
.capability = ARM64_WORKAROUND_AMPERE_AC04_CPU_23,
890+
ERRATA_MIDR_RANGE_LIST(erratum_ac04_cpu_23_list),
891+
},
878892
#endif
879893
{
880894
.desc = "Broken CNTVOFF_EL2",

arch/arm64/kernel/hyp-stub.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ SYM_CODE_START_LOCAL(__finalise_el2)
9797
2:
9898
// Engage the VHE magic!
9999
mov_q x0, HCR_HOST_VHE_FLAGS
100-
msr hcr_el2, x0
100+
msr_hcr_el2 x0
101101
isb
102102

103103
// Use the EL1 allocated stack, per-cpu offset

arch/arm64/kvm/at.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,7 +1245,7 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
12451245

12461246
skip_mmu_switch:
12471247
/* Temporarily switch back to guest context */
1248-
write_sysreg(vcpu->arch.hcr_el2, hcr_el2);
1248+
write_sysreg_hcr(vcpu->arch.hcr_el2);
12491249
isb();
12501250

12511251
switch (op) {
@@ -1277,7 +1277,7 @@ static u64 __kvm_at_s1e01_fast(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
12771277
if (!fail)
12781278
par = read_sysreg_par();
12791279

1280-
write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
1280+
write_sysreg_hcr(HCR_HOST_VHE_FLAGS);
12811281

12821282
if (!(vcpu_el2_e2h_is_set(vcpu) && vcpu_el2_tge_is_set(vcpu)))
12831283
__mmu_config_restore(&config);
@@ -1340,7 +1340,7 @@ void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
13401340
if (!vcpu_el2_e2h_is_set(vcpu))
13411341
val |= HCR_NV | HCR_NV1;
13421342

1343-
write_sysreg(val, hcr_el2);
1343+
write_sysreg_hcr(val);
13441344
isb();
13451345

13461346
par = SYS_PAR_EL1_F;
@@ -1365,7 +1365,7 @@ void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
13651365
if (!fail)
13661366
par = read_sysreg_par();
13671367

1368-
write_sysreg(hcr, hcr_el2);
1368+
write_sysreg_hcr(hcr);
13691369
isb();
13701370
}
13711371

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ static inline void ___activate_traps(struct kvm_vcpu *vcpu, u64 hcr)
345345
if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM))
346346
hcr |= HCR_TVM;
347347

348-
write_sysreg(hcr, hcr_el2);
348+
write_sysreg_hcr(hcr);
349349

350350
if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE))
351351
write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2);

0 commit comments

Comments
 (0)