Commit edd731d7 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge branch 'kvm-hw-enable-refactor' into HEAD



The main theme of this series is to kill off kvm_arch_init(),
kvm_arch_hardware_(un)setup(), and kvm_arch_check_processor_compat(), which
all originated in x86 code from way back when, and needlessly complicate
both common KVM code and architecture code.  E.g. many architectures don't
mark functions/data as __init/__ro_after_init purely because kvm_init()
isn't marked __init to support x86's separate vendor modules.

The idea/hope is that with those hooks gone (moved to arch code), it will
be easier for x86 (and other architectures) to modify their module init
sequences as needed without having to fight common KVM code.  E.g. I'm
hoping that ARM can build on this to simplify its hardware enabling logic,
especially the pKVM side of things.

There are bug fixes throughout this series.  They are more scattered than
I would usually prefer, but getting the sequencing correct was a gigantic
pain for many of the x86 fixes due to needing to fix common code in order
for the x86 fix to have any meaning.  And while the bugs are often fatal,
they aren't all that interesting for most users as they either require a
malicious admin or broken hardware, i.e. aren't likely to be encountered
by the vast majority of KVM users.  So unless someone _really_ wants a
particular fix isolated for backporting, I'm not planning on shuffling
patches.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parents fc471e83 9f1a4c00
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ KVM Lock Overview

The acquisition orders for mutexes are as follows:

- cpus_read_lock() is taken outside kvm_lock

- kvm->lock is taken outside vcpu->mutex

- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
@@ -225,15 +227,10 @@ time it will be set using the Dirty tracking mechanism described above.
:Type:		mutex
:Arch:		any
:Protects:	- vm_list

``kvm_count_lock``
^^^^^^^^^^^^^^^^^^

:Type:		raw_spinlock_t
:Arch:		any
:Protects:	- hardware virtualization enable/disable
:Comment:	'raw' because hardware enabling/disabling must be atomic /wrt
		migration.
		- kvm_usage_count
		- hardware virtualization enable/disable
:Comment:	KVM also disables CPU hotplug via cpus_read_lock() during
		enable/disable.

``kvm->mn_invalidate_lock``
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -291,3 +288,13 @@ time it will be set using the Dirty tracking mechanism described above.
		wakeup notification event since external interrupts from the
		assigned devices happens, we will find the vCPU on the list to
		wakeup.

``vendor_module_lock``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:Type:		mutex
:Arch:		x86
:Protects:	loading a vendor module (kvm_amd or kvm_intel)
:Comment:	Exists because using kvm_lock leads to deadlock.  cpu_hotplug_lock is
    taken outside of kvm_lock, e.g. in KVM's CPU online/offline callbacks, and
    many operations need to take cpu_hotplug_lock when loading a vendor module,
    e.g. updating static calls.
+7 −8
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@ enum kvm_mode kvm_get_mode(void);

DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);

extern unsigned int kvm_sve_max_vl;
int kvm_arm_init_sve(void);
extern unsigned int __ro_after_init kvm_sve_max_vl;
int __init kvm_arm_init_sve(void);

u32 __attribute_const__ kvm_target_cpu(void);
int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -877,7 +877,7 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu);

void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);

int kvm_sys_reg_table_init(void);
int __init kvm_sys_reg_table_init(void);

/* MMIO helpers */
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
@@ -908,9 +908,9 @@ int kvm_arm_pvtime_get_attr(struct kvm_vcpu *vcpu,
int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
			    struct kvm_device_attr *attr);

extern unsigned int kvm_arm_vmid_bits;
int kvm_arm_vmid_alloc_init(void);
void kvm_arm_vmid_alloc_free(void);
extern unsigned int __ro_after_init kvm_arm_vmid_bits;
int __init kvm_arm_vmid_alloc_init(void);
void __init kvm_arm_vmid_alloc_free(void);
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
void kvm_arm_vmid_clear_active(void);

@@ -943,7 +943,6 @@ static inline bool kvm_system_needs_idmapped_vectors(void)

void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu);

static inline void kvm_arch_hardware_unsetup(void) {}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}

@@ -994,7 +993,7 @@ static inline void kvm_clr_pmu_events(u32 clr) {}
void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);

int kvm_set_ipa_limit(void);
int __init kvm_set_ipa_limit(void);

#define __KVM_HAVE_ARCH_VM_ALLOC
struct kvm *kvm_arch_alloc_vm(void);
+2 −2
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
			   void __iomem **haddr);
int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
			     void **haddr);
void free_hyp_pgds(void);
void __init free_hyp_pgds(void);

void stage2_unmap_vm(struct kvm *kvm);
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long type);
@@ -175,7 +175,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);

phys_addr_t kvm_mmu_get_httbr(void);
phys_addr_t kvm_get_idmap_vector(void);
int kvm_mmu_init(u32 *hyp_va_bits);
int __init kvm_mmu_init(u32 *hyp_va_bits);

static inline void *__kvm_vector_slot2addr(void *base,
					   enum arm64_hyp_spectre_vector slot)
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ if VIRTUALIZATION
menuconfig KVM
	bool "Kernel-based Virtual Machine (KVM) support"
	depends on HAVE_KVM
	select KVM_GENERIC_HARDWARE_ENABLING
	select MMU_NOTIFIER
	select PREEMPT_NOTIFIERS
	select HAVE_KVM_CPU_RELAX_INTERCEPT
+11 −18
Original line number Diff line number Diff line
@@ -811,12 +811,20 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
	ptimer->host_timer_irq_flags = host_ptimer_irq_flags;
}

static void kvm_timer_init_interrupt(void *info)
void kvm_timer_cpu_up(void)
{
	enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
	if (host_ptimer_irq)
		enable_percpu_irq(host_ptimer_irq, host_ptimer_irq_flags);
}

void kvm_timer_cpu_down(void)
{
	disable_percpu_irq(host_vtimer_irq);
	if (host_ptimer_irq)
		disable_percpu_irq(host_ptimer_irq);
}

int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
{
	struct arch_timer_context *timer;
@@ -976,18 +984,6 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
	preempt_enable();
}

static int kvm_timer_starting_cpu(unsigned int cpu)
{
	kvm_timer_init_interrupt(NULL);
	return 0;
}

static int kvm_timer_dying_cpu(unsigned int cpu)
{
	disable_percpu_irq(host_vtimer_irq);
	return 0;
}

static int timer_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
{
	if (vcpu)
@@ -1117,7 +1113,7 @@ static int kvm_irq_init(struct arch_timer_kvm_info *info)
	return 0;
}

int kvm_timer_hyp_init(bool has_gic)
int __init kvm_timer_hyp_init(bool has_gic)
{
	struct arch_timer_kvm_info *info;
	int err;
@@ -1185,9 +1181,6 @@ int kvm_timer_hyp_init(bool has_gic)
		goto out_free_irq;
	}

	cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING,
			  "kvm/arm/timer:starting", kvm_timer_starting_cpu,
			  kvm_timer_dying_cpu);
	return 0;
out_free_irq:
	free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus());
Loading