Skip to content

Commit a027b2e

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini: "x86: - Fix SEV race condition ARM: - Fixes for the configuration of SVE/SME traps when hVHE mode is in use - Allow use of pKVM on systems with FF-A implementations that are v1.0 compatible - Request/release percpu IRQs (arch timer, vGIC maintenance) correctly when pKVM is in use - Fix function prototype after __kvm_host_psci_cpu_entry() rename - Skip to the next instruction when emulating writes to TCR_EL1 on AmpereOne systems Selftests: - Fix missing include" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: selftests/rseq: Fix build with undefined __weak KVM: SEV: remove ghcb variable declarations KVM: SEV: only access GHCB fields once KVM: SEV: snapshot the GHCB before accessing it KVM: arm64: Skip instruction after emulating write to TCR_EL1 KVM: arm64: fix __kvm_host_psci_cpu_entry() prototype KVM: arm64: Fix resetting SME trap values on reset for (h)VHE KVM: arm64: Fix resetting SVE trap values on reset for hVHE KVM: arm64: Use the appropriate feature trap register when activating traps KVM: arm64: Helper to write to appropriate feature trap register based on mode KVM: arm64: Disable SME traps for (h)VHE at setup KVM: arm64: Use the appropriate feature trap register for SVE at EL2 setup KVM: arm64: Factor out code for checking (h)VHE mode into a macro KVM: arm64: Rephrase percpu enable/disable tracking in terms of hyp KVM: arm64: Fix hardware enable/disable flows for pKVM KVM: arm64: Allow pKVM on v1.0 compatible FF-A implementations
2 parents 016ce29 + d5ad9aa commit a027b2e

File tree

11 files changed

+182
-120
lines changed

11 files changed

+182
-120
lines changed

arch/arm64/include/asm/el2_setup.h

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131
.Lskip_hcrx_\@:
3232
.endm
3333

34+
/* Check if running in host at EL2 mode, i.e., (h)VHE. Jump to fail if not. */
35+
.macro __check_hvhe fail, tmp
36+
mrs \tmp, hcr_el2
37+
and \tmp, \tmp, #HCR_E2H
38+
cbz \tmp, \fail
39+
.endm
40+
3441
/*
3542
* Allow Non-secure EL1 and EL0 to access physical timer and counter.
3643
* This is not necessary for VHE, since the host kernel runs in EL2,
@@ -43,9 +50,7 @@
4350
*/
4451
.macro __init_el2_timers
4552
mov x0, #3 // Enable EL1 physical timers
46-
mrs x1, hcr_el2
47-
and x1, x1, #HCR_E2H
48-
cbz x1, .LnVHE_\@
53+
__check_hvhe .LnVHE_\@, x1
4954
lsl x0, x0, #10
5055
.LnVHE_\@:
5156
msr cnthctl_el2, x0
@@ -139,15 +144,14 @@
139144

140145
/* Coprocessor traps */
141146
.macro __init_el2_cptr
142-
mrs x1, hcr_el2
143-
and x1, x1, #HCR_E2H
144-
cbz x1, .LnVHE_\@
147+
__check_hvhe .LnVHE_\@, x1
145148
mov x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN)
146-
b .Lset_cptr_\@
149+
msr cpacr_el1, x0
150+
b .Lskip_set_cptr_\@
147151
.LnVHE_\@:
148152
mov x0, #0x33ff
149-
.Lset_cptr_\@:
150153
msr cptr_el2, x0 // Disable copro. traps to EL2
154+
.Lskip_set_cptr_\@:
151155
.endm
152156

153157
/* Disable any fine grained traps */
@@ -268,19 +272,19 @@
268272
check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2
269273

270274
.Linit_sve_\@: /* SVE register access */
271-
mrs x0, cptr_el2 // Disable SVE traps
272-
mrs x1, hcr_el2
273-
and x1, x1, #HCR_E2H
274-
cbz x1, .Lcptr_nvhe_\@
275+
__check_hvhe .Lcptr_nvhe_\@, x1
275276

276-
// VHE case
277+
// (h)VHE case
278+
mrs x0, cpacr_el1 // Disable SVE traps
277279
orr x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN)
278-
b .Lset_cptr_\@
280+
msr cpacr_el1, x0
281+
b .Lskip_set_cptr_\@
279282

280283
.Lcptr_nvhe_\@: // nVHE case
284+
mrs x0, cptr_el2 // Disable SVE traps
281285
bic x0, x0, #CPTR_EL2_TZ
282-
.Lset_cptr_\@:
283286
msr cptr_el2, x0
287+
.Lskip_set_cptr_\@:
284288
isb
285289
mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector
286290
msr_s SYS_ZCR_EL2, x1 // length for EL1.
@@ -289,9 +293,19 @@
289293
check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2
290294

291295
.Linit_sme_\@: /* SME register access and priority mapping */
296+
__check_hvhe .Lcptr_nvhe_sme_\@, x1
297+
298+
// (h)VHE case
299+
mrs x0, cpacr_el1 // Disable SME traps
300+
orr x0, x0, #(CPACR_EL1_SMEN_EL0EN | CPACR_EL1_SMEN_EL1EN)
301+
msr cpacr_el1, x0
302+
b .Lskip_set_cptr_sme_\@
303+
304+
.Lcptr_nvhe_sme_\@: // nVHE case
292305
mrs x0, cptr_el2 // Disable SME traps
293306
bic x0, x0, #CPTR_EL2_TSM
294307
msr cptr_el2, x0
308+
.Lskip_set_cptr_sme_\@:
295309
isb
296310

297311
mrs x1, sctlr_el2

arch/arm64/include/asm/kvm_asm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ asmlinkage void __noreturn hyp_panic_bad_stack(void);
278278
asmlinkage void kvm_unexpected_el2_exception(void);
279279
struct kvm_cpu_context;
280280
void handle_trap(struct kvm_cpu_context *host_ctxt);
281-
asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on);
281+
asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on);
282282
void __noreturn __pkvm_init_finalise(void);
283283
void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
284284
void kvm_patch_vector_branch(struct alt_instr *alt,

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,15 +571,31 @@ static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature)
571571
return test_bit(feature, vcpu->arch.features);
572572
}
573573

574+
static __always_inline void kvm_write_cptr_el2(u64 val)
575+
{
576+
if (has_vhe() || has_hvhe())
577+
write_sysreg(val, cpacr_el1);
578+
else
579+
write_sysreg(val, cptr_el2);
580+
}
581+
574582
static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
575583
{
576584
u64 val;
577585

578586
if (has_vhe()) {
579587
val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN |
580588
CPACR_EL1_ZEN_EL1EN);
589+
if (cpus_have_final_cap(ARM64_SME))
590+
val |= CPACR_EL1_SMEN_EL1EN;
581591
} else if (has_hvhe()) {
582592
val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN);
593+
594+
if (!vcpu_has_sve(vcpu) ||
595+
(vcpu->arch.fp_state != FP_STATE_GUEST_OWNED))
596+
val |= CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN;
597+
if (cpus_have_final_cap(ARM64_SME))
598+
val |= CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN;
583599
} else {
584600
val = CPTR_NVHE_EL2_RES1;
585601

@@ -597,9 +613,6 @@ static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu)
597613
{
598614
u64 val = kvm_get_reset_cptr_el2(vcpu);
599615

600-
if (has_vhe() || has_hvhe())
601-
write_sysreg(val, cpacr_el1);
602-
else
603-
write_sysreg(val, cptr_el2);
616+
kvm_write_cptr_el2(val);
604617
}
605618
#endif /* __ARM64_KVM_EMULATE_H__ */

arch/arm64/kvm/arm.c

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
5555

5656
static bool vgic_present, kvm_arm_initialised;
5757

58-
static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
58+
static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
5959
DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
6060

6161
bool is_kvm_arm_initialised(void)
@@ -1864,18 +1864,24 @@ static void cpu_hyp_reinit(void)
18641864
cpu_hyp_init_features();
18651865
}
18661866

1867-
static void _kvm_arch_hardware_enable(void *discard)
1867+
static void cpu_hyp_init(void *discard)
18681868
{
1869-
if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
1869+
if (!__this_cpu_read(kvm_hyp_initialized)) {
18701870
cpu_hyp_reinit();
1871-
__this_cpu_write(kvm_arm_hardware_enabled, 1);
1871+
__this_cpu_write(kvm_hyp_initialized, 1);
18721872
}
18731873
}
18741874

1875-
int kvm_arch_hardware_enable(void)
1875+
static void cpu_hyp_uninit(void *discard)
18761876
{
1877-
int was_enabled;
1877+
if (__this_cpu_read(kvm_hyp_initialized)) {
1878+
cpu_hyp_reset();
1879+
__this_cpu_write(kvm_hyp_initialized, 0);
1880+
}
1881+
}
18781882

1883+
int kvm_arch_hardware_enable(void)
1884+
{
18791885
/*
18801886
* Most calls to this function are made with migration
18811887
* disabled, but not with preemption disabled. The former is
@@ -1884,36 +1890,23 @@ int kvm_arch_hardware_enable(void)
18841890
*/
18851891
preempt_disable();
18861892

1887-
was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
1888-
_kvm_arch_hardware_enable(NULL);
1893+
cpu_hyp_init(NULL);
18891894

1890-
if (!was_enabled) {
1891-
kvm_vgic_cpu_up();
1892-
kvm_timer_cpu_up();
1893-
}
1895+
kvm_vgic_cpu_up();
1896+
kvm_timer_cpu_up();
18941897

18951898
preempt_enable();
18961899

18971900
return 0;
18981901
}
18991902

1900-
static void _kvm_arch_hardware_disable(void *discard)
1901-
{
1902-
if (__this_cpu_read(kvm_arm_hardware_enabled)) {
1903-
cpu_hyp_reset();
1904-
__this_cpu_write(kvm_arm_hardware_enabled, 0);
1905-
}
1906-
}
1907-
19081903
void kvm_arch_hardware_disable(void)
19091904
{
1910-
if (__this_cpu_read(kvm_arm_hardware_enabled)) {
1911-
kvm_timer_cpu_down();
1912-
kvm_vgic_cpu_down();
1913-
}
1905+
kvm_timer_cpu_down();
1906+
kvm_vgic_cpu_down();
19141907

19151908
if (!is_protected_kvm_enabled())
1916-
_kvm_arch_hardware_disable(NULL);
1909+
cpu_hyp_uninit(NULL);
19171910
}
19181911

19191912
#ifdef CONFIG_CPU_PM
@@ -1922,25 +1915,25 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
19221915
void *v)
19231916
{
19241917
/*
1925-
* kvm_arm_hardware_enabled is left with its old value over
1918+
* kvm_hyp_initialized is left with its old value over
19261919
* PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should
19271920
* re-enable hyp.
19281921
*/
19291922
switch (cmd) {
19301923
case CPU_PM_ENTER:
1931-
if (__this_cpu_read(kvm_arm_hardware_enabled))
1924+
if (__this_cpu_read(kvm_hyp_initialized))
19321925
/*
1933-
* don't update kvm_arm_hardware_enabled here
1934-
* so that the hardware will be re-enabled
1926+
* don't update kvm_hyp_initialized here
1927+
* so that the hyp will be re-enabled
19351928
* when we resume. See below.
19361929
*/
19371930
cpu_hyp_reset();
19381931

19391932
return NOTIFY_OK;
19401933
case CPU_PM_ENTER_FAILED:
19411934
case CPU_PM_EXIT:
1942-
if (__this_cpu_read(kvm_arm_hardware_enabled))
1943-
/* The hardware was enabled before suspend. */
1935+
if (__this_cpu_read(kvm_hyp_initialized))
1936+
/* The hyp was enabled before suspend. */
19441937
cpu_hyp_reinit();
19451938

19461939
return NOTIFY_OK;
@@ -2021,7 +2014,7 @@ static int __init init_subsystems(void)
20212014
/*
20222015
* Enable hardware so that subsystem initialisation can access EL2.
20232016
*/
2024-
on_each_cpu(_kvm_arch_hardware_enable, NULL, 1);
2017+
on_each_cpu(cpu_hyp_init, NULL, 1);
20252018

20262019
/*
20272020
* Register CPU lower-power notifier
@@ -2059,7 +2052,7 @@ static int __init init_subsystems(void)
20592052
hyp_cpu_pm_exit();
20602053

20612054
if (err || !is_protected_kvm_enabled())
2062-
on_each_cpu(_kvm_arch_hardware_disable, NULL, 1);
2055+
on_each_cpu(cpu_hyp_uninit, NULL, 1);
20632056

20642057
return err;
20652058
}
@@ -2097,7 +2090,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits)
20972090
* The stub hypercalls are now disabled, so set our local flag to
20982091
* prevent a later re-init attempt in kvm_arch_hardware_enable().
20992092
*/
2100-
__this_cpu_write(kvm_arm_hardware_enabled, 1);
2093+
__this_cpu_write(kvm_hyp_initialized, 1);
21012094
preempt_enable();
21022095

21032096
return ret;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu)
457457
*/
458458
val &= ~(TCR_HD | TCR_HA);
459459
write_sysreg_el1(val, SYS_TCR);
460+
__kvm_skip_instr(vcpu);
460461
return true;
461462
}
462463

arch/arm64/kvm/hyp/nvhe/ffa.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,20 @@ int hyp_ffa_init(void *pages)
705705
if (res.a0 == FFA_RET_NOT_SUPPORTED)
706706
return 0;
707707

708-
if (res.a0 != FFA_VERSION_1_0)
708+
/*
709+
* Firmware returns the maximum supported version of the FF-A
710+
* implementation. Check that the returned version is
711+
* backwards-compatible with the hyp according to the rules in DEN0077A
712+
* v1.1 REL0 13.2.1.
713+
*
714+
* Of course, things are never simple when dealing with firmware. v1.1
715+
* broke ABI with v1.0 on several structures, which is itself
716+
* incompatible with the aforementioned versioning scheme. The
717+
* expectation is that v1.x implementations that do not support the v1.0
718+
* ABI return NOT_SUPPORTED rather than a version number, according to
719+
* DEN0077A v1.1 REL0 18.6.4.
720+
*/
721+
if (FFA_MAJOR_VERSION(res.a0) != 1)
709722
return -EOPNOTSUPP;
710723

711724
arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);

arch/arm64/kvm/hyp/nvhe/switch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
6363
__activate_traps_fpsimd32(vcpu);
6464
}
6565

66-
write_sysreg(val, cptr_el2);
66+
kvm_write_cptr_el2(val);
6767
write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
6868

6969
if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {

0 commit comments

Comments
 (0)