Commit 4361f5aa authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-fixes-6.18-rc2' of https://github.com/kvm-x86/linux into HEAD

KVM x86 fixes for 6.18:

 - Expand the KVM_PRE_FAULT_MEMORY selftest to add a regression test for the
   bug fixed by commit 3ccbf6f4 ("KVM: x86/mmu: Return -EAGAIN if userspace
   deletes/moves memslot during prefault")

 - Don't try to get PMU capabbilities from perf when running a CPU with hybrid
   CPUs/PMUs, as perf will rightly WARN.

 - Rework KVM_CAP_GUEST_MEMFD_MMAP (newly introduced in 6.18) into a more
   generic KVM_CAP_GUEST_MEMFD_FLAGS

 - Add a guest_memfd INIT_SHARED flag and require userspace to explicitly set
   said flag to initialize memory as SHARED, irrespective of MMAP.  The
   behavior merged in 6.18 is that enabling mmap() implicitly initializes
   memory as SHARED, which would result in an ABI collision for x86 CoCo VMs
   as their memory is currently always initialized PRIVATE.

 - Allow mmap() on guest_memfd for x86 CoCo VMs, i.e. on VMs with private
   memory, to enable testing such setups, i.e. to hopefully flush out any
   other lurking ABI issues before 6.18 is officially released.

 - Add testcases to the guest_memfd selftest to cover guest_memfd without MMAP,
   and host userspace accesses to mmap()'d private memory.
parents 5d26eaae 505f5224
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -6437,9 +6437,18 @@ most one mapping per page, i.e. binding multiple memory regions to a single
guest_memfd range is not allowed (any number of memory regions can be bound to
a single guest_memfd file, but the bound ranges must not overlap).

When the capability KVM_CAP_GUEST_MEMFD_MMAP is supported, the 'flags' field
supports GUEST_MEMFD_FLAG_MMAP.  Setting this flag on guest_memfd creation
enables mmap() and faulting of guest_memfd memory to host userspace.
The capability KVM_CAP_GUEST_MEMFD_FLAGS enumerates the `flags` that can be
specified via KVM_CREATE_GUEST_MEMFD.  Currently defined flags:

  ============================ ================================================
  GUEST_MEMFD_FLAG_MMAP        Enable using mmap() on the guest_memfd file
                               descriptor.
  GUEST_MEMFD_FLAG_INIT_SHARED Make all memory in the file shared during
                               KVM_CREATE_GUEST_MEMFD (memory files created
                               without INIT_SHARED will be marked private).
                               Shared memory can be faulted into host userspace
                               page tables. Private memory cannot.
  ============================ ================================================

When the KVM MMU performs a PFN lookup to service a guest fault and the backing
guest_memfd has the GUEST_MEMFD_FLAG_MMAP set, then the fault will always be
+5 −3
Original line number Diff line number Diff line
@@ -108,16 +108,18 @@ void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops)
	bool is_intel = boot_cpu_data.x86_vendor == X86_VENDOR_INTEL;
	int min_nr_gp_ctrs = pmu_ops->MIN_NR_GP_COUNTERS;

	perf_get_x86_pmu_capability(&kvm_host_pmu);

	/*
	 * Hybrid PMUs don't play nice with virtualization without careful
	 * configuration by userspace, and KVM's APIs for reporting supported
	 * vPMU features do not account for hybrid PMUs.  Disable vPMU support
	 * for hybrid PMUs until KVM gains a way to let userspace opt-in.
	 */
	if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
	if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
		enable_pmu = false;
		memset(&kvm_host_pmu, 0, sizeof(kvm_host_pmu));
	} else {
		perf_get_x86_pmu_capability(&kvm_host_pmu);
	}

	if (enable_pmu) {
		/*
+4 −3
Original line number Diff line number Diff line
@@ -13941,10 +13941,11 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)

#ifdef CONFIG_KVM_GUEST_MEMFD
/*
 * KVM doesn't yet support mmap() on guest_memfd for VMs with private memory
 * (the private vs. shared tracking needs to be moved into guest_memfd).
 * KVM doesn't yet support initializing guest_memfd memory as shared for VMs
 * with private memory (the private vs. shared tracking needs to be moved into
 * guest_memfd).
 */
bool kvm_arch_supports_gmem_mmap(struct kvm *kvm)
bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
{
	return !kvm_arch_has_private_mem(kvm);
}
+11 −1
Original line number Diff line number Diff line
@@ -729,7 +729,17 @@ static inline bool kvm_arch_has_private_mem(struct kvm *kvm)
#endif

#ifdef CONFIG_KVM_GUEST_MEMFD
bool kvm_arch_supports_gmem_mmap(struct kvm *kvm);
bool kvm_arch_supports_gmem_init_shared(struct kvm *kvm);

static inline u64 kvm_gmem_get_supported_flags(struct kvm *kvm)
{
	u64 flags = GUEST_MEMFD_FLAG_MMAP;

	if (!kvm || kvm_arch_supports_gmem_init_shared(kvm))
		flags |= GUEST_MEMFD_FLAG_INIT_SHARED;

	return flags;
}
#endif

#ifndef kvm_arch_has_readonly_mem
+3 −2
Original line number Diff line number Diff line
@@ -962,7 +962,7 @@ struct kvm_enable_cap {
#define KVM_CAP_ARM_EL2_E2H0 241
#define KVM_CAP_RISCV_MP_STATE_RESET 242
#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
#define KVM_CAP_GUEST_MEMFD_MMAP 244
#define KVM_CAP_GUEST_MEMFD_FLAGS 244

struct kvm_irq_routing_irqchip {
	__u32 irqchip;
@@ -1600,6 +1600,7 @@ struct kvm_memory_attributes {

#define KVM_CREATE_GUEST_MEMFD	_IOWR(KVMIO,  0xd4, struct kvm_create_guest_memfd)
#define GUEST_MEMFD_FLAG_MMAP		(1ULL << 0)
#define GUEST_MEMFD_FLAG_INIT_SHARED	(1ULL << 1)

struct kvm_create_guest_memfd {
	__u64 size;
Loading