mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
Merge tag 'kvm-x86-generic-7.3' of https://github.com/kvm-x86/linux into HEAD
KVM arch-neutral and documentation changes for 7.3 - Remove kvm_debugfs_dir if kvm_init() fails after creating KVM's debugfs. - Document some of the "fun" gotchas with the APIC base when creating IRQCHIPs on x86. - Add a per-VM bitmap to track which vCPU IDs have been "claimed" but for which the vCPU isn't yet online, and use the bitmap to reject duplicate IDs before calling into arch code. This allows arch code to consume vcpu_id without having to worry about cross-vCPU clobbering (at least s390 and x86 have had related bugs). - Zero a vCPU's entry in VMX's Posted Interrupt Descriptor table used for IPI virtualization when the vCPU is freed to fix a use-after-free where hardware will write to a freed vCPU's PID.
This commit is contained in:
@@ -856,12 +856,21 @@ Writes the floating point state to the vcpu.
|
||||
Creates an interrupt controller model in the kernel.
|
||||
On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up
|
||||
future vcpus to have a local APIC. IRQ routing for GSIs 0-15 is set to both
|
||||
PIC and IOAPIC; GSI 16-23 only go to the IOAPIC.
|
||||
PIC and IOAPIC; GSI 16-23 only go to the IOAPIC. This ioctl can only be
|
||||
called before creating any vcpus.
|
||||
On arm64, a GICv2 is created. Any other GIC versions require the usage of
|
||||
KVM_CREATE_DEVICE, which also supports creating a GICv2. Using
|
||||
KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2.
|
||||
On s390, a dummy irq routing table is created.
|
||||
|
||||
On x86, subsequent vcpu creation may install a private 4 KiB memory slot at the
|
||||
default APIC base address (0xfee00000). User memory regions must not overlap
|
||||
this address; doing so will cause vcpu creation to fail with ``EEXIST``, or the
|
||||
memory region to be rejected if created after the vcpu. This occurs when
|
||||
APIC access acceleration is enabled (APICv on Intel, AVIC on AMD), which is
|
||||
the default on supported hardware. The same constraint applies when using
|
||||
``KVM_CAP_SPLIT_IRQCHIP``.
|
||||
|
||||
Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
|
||||
before KVM_CREATE_IRQCHIP can be used.
|
||||
|
||||
@@ -7933,6 +7942,10 @@ used in the IRQ routing table. The first args[0] MSI routes are reserved
|
||||
for the IOAPIC pins. Whenever the LAPIC receives an EOI for these routes,
|
||||
a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
|
||||
|
||||
As with ``KVM_CREATE_IRQCHIP``, subsequent vcpu creation may install a private
|
||||
memory slot at the APIC base address (0xfee00000) that must not overlap user
|
||||
memory regions. See ``KVM_CREATE_IRQCHIP`` for details.
|
||||
|
||||
Fails if VCPU has already been created, or if the irqchip is already in the
|
||||
kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
|
||||
|
||||
|
||||
@@ -7681,6 +7681,9 @@ void vmx_vcpu_free(struct kvm_vcpu *vcpu)
|
||||
nested_vmx_free_vcpu(vcpu);
|
||||
free_loaded_vmcs(vmx->loaded_vmcs);
|
||||
free_page((unsigned long)vmx->ve_info);
|
||||
|
||||
if (vmx_can_use_ipiv(vcpu))
|
||||
WRITE_ONCE(to_kvm_vmx(vcpu->kvm)->pid_table[vcpu->vcpu_id], 0);
|
||||
}
|
||||
|
||||
int vmx_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -791,6 +791,7 @@ struct kvm {
|
||||
/* The current active memslot set for each address space */
|
||||
struct kvm_memslots __rcu *memslots[KVM_MAX_NR_ADDRESS_SPACES];
|
||||
struct xarray vcpu_array;
|
||||
DECLARE_BITMAP(vcpu_ids, KVM_MAX_VCPU_IDS);
|
||||
/*
|
||||
* Protected by slots_lock, but can be read outside if an
|
||||
* incorrect answer is acceptable.
|
||||
|
||||
+9
-1
@@ -4174,6 +4174,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (test_bit(id, kvm->vcpu_ids)) {
|
||||
mutex_unlock(&kvm->lock);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
r = kvm_arch_vcpu_precreate(kvm, id);
|
||||
if (r) {
|
||||
mutex_unlock(&kvm->lock);
|
||||
@@ -4181,6 +4186,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
|
||||
}
|
||||
|
||||
kvm->created_vcpus++;
|
||||
__set_bit(id, kvm->vcpu_ids);
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL_ACCOUNT);
|
||||
@@ -4212,7 +4218,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
|
||||
if (kvm_get_vcpu_by_id(kvm, id)) {
|
||||
if (WARN_ON_ONCE(kvm_get_vcpu_by_id(kvm, id))) {
|
||||
r = -EEXIST;
|
||||
goto unlock_vcpu_destroy;
|
||||
}
|
||||
@@ -4266,6 +4272,7 @@ vcpu_free:
|
||||
vcpu_decrement:
|
||||
mutex_lock(&kvm->lock);
|
||||
kvm->created_vcpus--;
|
||||
__clear_bit(id, kvm->vcpu_ids);
|
||||
mutex_unlock(&kvm->lock);
|
||||
return r;
|
||||
}
|
||||
@@ -6554,6 +6561,7 @@ err_virt:
|
||||
err_gmem:
|
||||
kvm_vfio_ops_exit();
|
||||
err_vfio:
|
||||
debugfs_remove_recursive(kvm_debugfs_dir);
|
||||
kvm_async_pf_deinit();
|
||||
err_async_pf:
|
||||
kvm_irqfd_exit();
|
||||
|
||||
Reference in New Issue
Block a user