Skip to content

Commit e1914ad

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini: "arm64: - Add the pKVM side of the workaround for ARM's erratum 4193714, provided that the EL3 firmware does its part of the job. KVM will refuse to initialise otherwise - Correctly handle 52bit VAs for guest EL2 stage-1 translations when running under NV with E2H==0 - Correctly deal with permission faults in guest_memfd memslots - Fix the steal-time selftest after the infrastructure was reworked - Make sure the host cannot pass a non-sensical clock update to the EL2 tracing infrastructure - Appoint Steffen Eiden as a reviewer in anticipation of the KVM/s390 ability to run arm64 guests, which will inevitably lead to arm64 code being directly used on s390 - Make sure that EL2 is configured with both exception entry and exit being Context Synchronization Events - Handle the current vcpu being NULL on EL2 panic - Fix the selftest_vcpu memcache being empty at the point of donation or sharing - Check that the memcache has enough capacity before engaging on the share/donate path - Fix __deactivate_fgt() to use its parameter rather than a variable in the macro context s390: - Fix array overrun with large amounts of PCI devices x86: - Never use L0's PAUSE loop exiting while L2 is running, since it's unlikely that a nested guest will help solving the hypervisor's spinlock contention - Fix emulation of MOVNTDQA - Fix typo in Xen hypercall tracepoint - Add back an optimization that was left behind when recently fixing a bug - Add module parameter to disable CET, whose implementation seems to have issues. For now it remains enabled by default Generic: - Reject offset causing an unsigned overflow in kvm_reset_dirty_gfn() Documentation: - Update stale links Selftests: - Fix guest_memfd_test with host page size > guest page size" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (22 commits) KVM: VMX: introduce module parameter to disable CET KVM: x86: Swap the dst and src operand for MOVNTDQA KVM: x86: use again the flush argument of __link_shadow_page() KVM: selftests: Ensure gmem file sizes are multiple of host page size Documentation: kvm: update links in the references section of AMD Memory Encryption KVM: nSVM: Never use L0's PAUSE loop exiting while L2 is running KVM: x86: Fix Xen hypercall tracepoint argument assignment KVM: Reject wrapped offset in kvm_reset_dirty_gfn() KVM: arm64: Pre-check vcpu memcache for host->guest donate KVM: arm64: Pre-check vcpu memcache for host->guest share KVM: arm64: Seed pkvm_ownership_selftest vcpu memcache KVM: arm64: Fix __deactivate_fgt macro parameter typo KVM: arm64: Guard against NULL vcpu on VHE hyp panic path KVM: arm64: Make EL2 exception entry and exit context-synchronization events MAINTAINERS: Add Steffen as reviewer for KVM/arm64 KVM: arm64: Remove potential UB on nvhe tracing clock update KVM: selftests: arm64: Fix steal_time test after UAPI refactoring KVM: arm64: Handle permission faults with guest_memfd KVM: arm64: nv: Consider the DS bit when translating TCR_EL2 KVM: arm64: Work around C1-Pro erratum 4193714 for protected guests ...
2 parents 1f63dd8 + 2d5d3fc commit e1914ad

24 files changed

Lines changed: 204 additions & 65 deletions

File tree

Documentation/virt/kvm/x86/amd-memory-encryption.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,8 @@ References
656656
See [white-paper]_, [api-spec]_, [amd-apm]_, [kvm-forum]_, and [snp-fw-abi]_
657657
for more info.
658658

659-
.. [white-paper] https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
660-
.. [api-spec] https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
661-
.. [amd-apm] https://support.amd.com/TechDocs/24593.pdf (section 15.34)
659+
.. [white-paper] https://docs.amd.com/v/u/en-US/memory-encryption-white-paper
660+
.. [api-spec] https://docs.amd.com/v/u/en-US/55766_PUB_3.24_SEV_API
661+
.. [amd-apm] https://docs.amd.com/v/u/en-US/24593_3.44_APM_Vol2 (section 15.34)
662662
.. [kvm-forum] https://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
663-
.. [snp-fw-abi] https://www.amd.com/system/files/TechDocs/56860.pdf
663+
.. [snp-fw-abi] https://www.amd.com/content/dam/amd/en/documents/developer/56860.pdf

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14055,6 +14055,7 @@ KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
1405514055
M: Marc Zyngier <maz@kernel.org>
1405614056
M: Oliver Upton <oupton@kernel.org>
1405714057
R: Joey Gouly <joey.gouly@arm.com>
14058+
R: Steffen Eiden <seiden@linux.ibm.com>
1405814059
R: Suzuki K Poulose <suzuki.poulose@arm.com>
1405914060
R: Zenghui Yu <yuzenghui@huawei.com>
1406014061
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)

arch/arm64/include/asm/kvm_nested.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static inline u64 tcr_el2_ps_to_tcr_el1_ips(u64 tcr_el2)
2323
static inline u64 translate_tcr_el2_to_tcr_el1(u64 tcr)
2424
{
2525
return TCR_EPD1_MASK | /* disable TTBR1_EL1 */
26+
((tcr & TCR_EL2_DS) ? TCR_DS : 0) |
2627
((tcr & TCR_EL2_TBI) ? TCR_TBI0 : 0) |
2728
tcr_el2_ps_to_tcr_el1_ips(tcr) |
2829
(tcr & TCR_EL2_TG0_MASK) |

arch/arm64/include/asm/sysreg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@
844844
#define INIT_SCTLR_EL2_MMU_ON \
845845
(SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA | SCTLR_ELx_I | \
846846
SCTLR_ELx_IESB | SCTLR_ELx_WXN | ENDIAN_SET_EL2 | \
847-
SCTLR_ELx_ITFSB | SCTLR_EL2_RES1)
847+
SCTLR_ELx_ITFSB | SCTLR_ELx_EIS | SCTLR_ELx_EOS | SCTLR_EL2_RES1)
848848

849849
#define INIT_SCTLR_EL2_MMU_OFF \
850850
(SCTLR_EL2_RES1 | ENDIAN_SET_EL2)

arch/arm64/kvm/arm.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Author: Christoffer Dall <c.dall@virtualopensystems.com>
55
*/
66

7+
#include <linux/arm-smccc.h>
78
#include <linux/bug.h>
89
#include <linux/cpu_pm.h>
910
#include <linux/errno.h>
@@ -2638,6 +2639,22 @@ static int init_pkvm_host_sve_state(void)
26382639
return 0;
26392640
}
26402641

2642+
static int pkvm_check_sme_dvmsync_fw_call(void)
2643+
{
2644+
struct arm_smccc_res res;
2645+
2646+
if (!cpus_have_final_cap(ARM64_WORKAROUND_4193714))
2647+
return 0;
2648+
2649+
arm_smccc_1_1_smc(ARM_SMCCC_CPU_WORKAROUND_4193714, &res);
2650+
if (res.a0) {
2651+
kvm_err("pKVM requires firmware support for C1-Pro erratum 4193714\n");
2652+
return -ENODEV;
2653+
}
2654+
2655+
return 0;
2656+
}
2657+
26412658
/*
26422659
* Finalizes the initialization of hyp mode, once everything else is initialized
26432660
* and the initialziation process cannot fail.
@@ -2838,6 +2855,10 @@ static int __init init_hyp_mode(void)
28382855
if (err)
28392856
goto out_err;
28402857

2858+
err = pkvm_check_sme_dvmsync_fw_call();
2859+
if (err)
2860+
goto out_err;
2861+
28412862
err = kvm_hyp_init_protection(hyp_va_bits);
28422863
if (err) {
28432864
kvm_err("Failed to init hyp memory protection\n");

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static inline void __activate_traps_ich_hfgxtr(struct kvm_vcpu *vcpu)
245245
__activate_fgt(hctxt, vcpu, ICH_HFGITR_EL2);
246246
}
247247

248-
#define __deactivate_fgt(htcxt, vcpu, reg) \
248+
#define __deactivate_fgt(hctxt, vcpu, reg) \
249249
do { \
250250
write_sysreg_s(ctxt_sys_reg(hctxt, reg), \
251251
SYS_ ## reg); \

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ void trace_clock_update(u32 mult, u32 shift, u64 epoch_ns, u64 epoch_cyc)
3535
struct clock_data *clock = &trace_clock_data;
3636
u64 bank = clock->cur ^ 1;
3737

38+
if (!mult || shift >= 64)
39+
return;
40+
3841
clock->data[bank].mult = mult;
3942
clock->data[bank].shift = shift;
4043
clock->data[bank].epoch_ns = epoch_ns;

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <linux/kvm_host.h>
8+
89
#include <asm/kvm_emulate.h>
910
#include <asm/kvm_hyp.h>
1011
#include <asm/kvm_mmu.h>
@@ -14,6 +15,7 @@
1415

1516
#include <hyp/fault.h>
1617

18+
#include <nvhe/arm-smccc.h>
1719
#include <nvhe/gfp.h>
1820
#include <nvhe/memory.h>
1921
#include <nvhe/mem_protect.h>
@@ -29,6 +31,19 @@ static struct hyp_pool host_s2_pool;
2931
static DEFINE_PER_CPU(struct pkvm_hyp_vm *, __current_vm);
3032
#define current_vm (*this_cpu_ptr(&__current_vm))
3133

34+
static void pkvm_sme_dvmsync_fw_call(void)
35+
{
36+
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) {
37+
struct arm_smccc_res res;
38+
39+
/*
40+
* Ignore the return value. Probing for the workaround
41+
* availability took place in init_hyp_mode().
42+
*/
43+
hyp_smccc_1_1_smc(ARM_SMCCC_CPU_WORKAROUND_4193714, &res);
44+
}
45+
}
46+
3247
static void guest_lock_component(struct pkvm_hyp_vm *vm)
3348
{
3449
hyp_spin_lock(&vm->lock);
@@ -574,8 +589,14 @@ static int host_stage2_set_owner_metadata_locked(phys_addr_t addr, u64 size,
574589
ret = host_stage2_try(kvm_pgtable_stage2_annotate, &host_mmu.pgt,
575590
addr, size, &host_s2_pool,
576591
KVM_HOST_INVALID_PTE_TYPE_DONATION, annotation);
577-
if (!ret)
592+
if (!ret) {
593+
/*
594+
* After stage2 maintenance has happened, but before the page
595+
* owner has changed.
596+
*/
597+
pkvm_sme_dvmsync_fw_call();
578598
__host_update_page_state(addr, size, PKVM_NOPAGE);
599+
}
579600

580601
return ret;
581602
}
@@ -1369,6 +1390,22 @@ int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm)
13691390
return ret && ret != -EHWPOISON ? ret : 0;
13701391
}
13711392

1393+
/*
1394+
* share/donate install at most one stage-2 leaf (PAGE_SIZE, or one
1395+
* KVM_PGTABLE_LAST_LEVEL - 1 block for share). kvm_mmu_cache_min_pages()
1396+
* bounds the worst-case allocation: exact for the PAGE_SIZE leaf,
1397+
* conservative by one for the block.
1398+
*/
1399+
static int __guest_check_pgtable_memcache(struct pkvm_hyp_vcpu *vcpu)
1400+
{
1401+
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
1402+
1403+
if (vcpu->vcpu.arch.pkvm_memcache.nr_pages < kvm_mmu_cache_min_pages(vm->pgt.mmu))
1404+
return -ENOMEM;
1405+
1406+
return 0;
1407+
}
1408+
13721409
int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
13731410
{
13741411
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
@@ -1388,6 +1425,10 @@ int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
13881425
if (ret)
13891426
goto unlock;
13901427

1428+
ret = __guest_check_pgtable_memcache(vcpu);
1429+
if (ret)
1430+
goto unlock;
1431+
13911432
meta = host_stage2_encode_gfn_meta(vm, gfn);
13921433
WARN_ON(host_stage2_set_owner_metadata_locked(phys, PAGE_SIZE,
13931434
PKVM_ID_GUEST, meta));
@@ -1453,6 +1494,10 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu
14531494
}
14541495
}
14551496

1497+
ret = __guest_check_pgtable_memcache(vcpu);
1498+
if (ret)
1499+
goto unlock;
1500+
14561501
for_each_hyp_page(page, phys, size) {
14571502
set_host_state(page, PKVM_PAGE_SHARED_OWNED);
14581503
page->host_share_guest_count++;

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,16 +752,30 @@ static struct pkvm_hyp_vcpu selftest_vcpu = {
752752
struct pkvm_hyp_vcpu *init_selftest_vm(void *virt)
753753
{
754754
struct hyp_page *p = hyp_virt_to_page(virt);
755+
unsigned long min_pages, seeded = 0;
755756
int i;
756757

757758
selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
758759
WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
759760

761+
/*
762+
* Mirror pkvm_refill_memcache() for the share/donate pre-checks;
763+
* the selftest invokes those functions directly and would
764+
* otherwise see an empty memcache.
765+
*/
766+
min_pages = kvm_mmu_cache_min_pages(&selftest_vm.kvm.arch.mmu);
767+
760768
for (i = 0; i < pkvm_selftest_pages(); i++) {
761769
if (p[i].refcount)
762770
continue;
763771
p[i].refcount = 1;
764-
hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
772+
if (seeded < min_pages) {
773+
push_hyp_memcache(&selftest_vcpu.vcpu.arch.pkvm_memcache,
774+
hyp_page_to_virt(&p[i]), hyp_virt_to_phys);
775+
seeded++;
776+
} else {
777+
hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
778+
}
765779
}
766780

767781
selftest_vm.kvm.arch.pkvm.handle = __pkvm_reserve_vm();

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,8 @@ static void __noreturn __hyp_call_panic(u64 spsr, u64 elr, u64 par)
663663
host_ctxt = host_data_ptr(host_ctxt);
664664
vcpu = host_ctxt->__hyp_running_vcpu;
665665

666-
__deactivate_traps(vcpu);
666+
if (vcpu)
667+
__deactivate_traps(vcpu);
667668
sysreg_restore_host_state_vhe(host_ctxt);
668669

669670
panic("HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n",

0 commit comments

Comments
 (0)