Skip to content

Commit

Permalink
Merge branch 'kvm-6.15-rc2-fixes' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
Paolo Bonzini committed Apr 4, 2025
2 parents 70817b2 + bc52ae0 commit 369348e
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 20 deletions.
7 changes: 6 additions & 1 deletion arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -1472,8 +1472,13 @@ struct kvm_arch {
struct once nx_once;

#ifdef CONFIG_X86_64
/* The number of TDP MMU pages across all roots. */
#ifdef CONFIG_KVM_PROVE_MMU
/*
* The number of TDP MMU pages across all roots. Used only to sanity
* check that KVM isn't leaking TDP MMU pages.
*/
atomic64_t tdp_mmu_pages;
#endif

/*
* List of struct kvm_mmu_pages being used as roots.
Expand Down
8 changes: 3 additions & 5 deletions arch/x86/kvm/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,8 +1427,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
}
break;
case 0xa: { /* Architectural Performance Monitoring */
union cpuid10_eax eax;
union cpuid10_edx edx;
union cpuid10_eax eax = { };
union cpuid10_edx edx = { };

if (!enable_pmu || !static_cpu_has(X86_FEATURE_ARCH_PERFMON)) {
entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
Expand All @@ -1444,8 +1444,6 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)

if (kvm_pmu_cap.version)
edx.split.anythread_deprecated = 1;
edx.split.reserved1 = 0;
edx.split.reserved2 = 0;

entry->eax = eax.full;
entry->ebx = kvm_pmu_cap.events_mask;
Expand Down Expand Up @@ -1763,7 +1761,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
break;
/* AMD Extended Performance Monitoring and Debug */
case 0x80000022: {
union cpuid_0x80000022_ebx ebx;
union cpuid_0x80000022_ebx ebx = { };

entry->ecx = entry->edx = 0;
if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) {
Expand Down
8 changes: 7 additions & 1 deletion arch/x86/kvm/mmu/tdp_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
kvm_tdp_mmu_invalidate_roots(kvm, KVM_VALID_ROOTS);
kvm_tdp_mmu_zap_invalidated_roots(kvm, false);

WARN_ON(atomic64_read(&kvm->arch.tdp_mmu_pages));
#ifdef CONFIG_KVM_PROVE_MMU
KVM_MMU_WARN_ON(atomic64_read(&kvm->arch.tdp_mmu_pages));
#endif
WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));

/*
Expand Down Expand Up @@ -325,13 +327,17 @@ static void handle_changed_spte(struct kvm *kvm, int as_id, gfn_t gfn,
static void tdp_account_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
kvm_account_pgtable_pages((void *)sp->spt, +1);
#ifdef CONFIG_KVM_PROVE_MMU
atomic64_inc(&kvm->arch.tdp_mmu_pages);
#endif
}

static void tdp_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
kvm_account_pgtable_pages((void *)sp->spt, -1);
#ifdef CONFIG_KVM_PROVE_MMU
atomic64_dec(&kvm->arch.tdp_mmu_pages);
#endif
}

/**
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -11786,6 +11786,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
if (kvm_mpx_supported())
kvm_load_guest_fpu(vcpu);

kvm_vcpu_srcu_read_lock(vcpu);

r = kvm_apic_accept_events(vcpu);
if (r < 0)
goto out;
Expand All @@ -11799,6 +11801,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
mp_state->mp_state = vcpu->arch.mp_state;

out:
kvm_vcpu_srcu_read_unlock(vcpu);

if (kvm_mpx_supported())
kvm_put_guest_fpu(vcpu);
vcpu_put(vcpu);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -2382,7 +2382,7 @@ static inline bool kvm_is_visible_memslot(struct kvm_memory_slot *memslot)
struct kvm_vcpu *kvm_get_running_vcpu(void);
struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);

#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
bool kvm_arch_has_irq_bypass(void);
int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *,
struct irq_bypass_producer *);
Expand Down
31 changes: 25 additions & 6 deletions tools/testing/selftests/kvm/rseq_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,27 @@ static void calc_min_max_cpu(void)
static void help(const char *name)
{
puts("");
printf("usage: %s [-h] [-u]\n", name);
printf("usage: %s [-h] [-u] [-l latency]\n", name);
printf(" -u: Don't sanity check the number of successful KVM_RUNs\n");
printf(" -l: Set /dev/cpu_dma_latency to suppress deep sleep states\n");
puts("");
exit(0);
}

int main(int argc, char *argv[])
{
int r, i, snapshot, opt, fd = -1, latency = -1;
bool skip_sanity_check = false;
int r, i, snapshot;
struct kvm_vm *vm;
struct kvm_vcpu *vcpu;
u32 cpu, rseq_cpu;
int opt;

while ((opt = getopt(argc, argv, "hu")) != -1) {
while ((opt = getopt(argc, argv, "hl:u")) != -1) {
switch (opt) {
case 'u':
skip_sanity_check = true;
case 'l':
latency = atoi_paranoid(optarg);
break;
case 'h':
default:
Expand Down Expand Up @@ -243,6 +245,20 @@ int main(int argc, char *argv[])
pthread_create(&migration_thread, NULL, migration_worker,
(void *)(unsigned long)syscall(SYS_gettid));

if (latency >= 0) {
/*
* Writes to cpu_dma_latency persist only while the file is
* open, i.e. it allows userspace to provide guaranteed latency
* while running a workload. Keep the file open until the test
* completes, otherwise writing cpu_dma_latency is meaningless.
*/
fd = open("/dev/cpu_dma_latency", O_RDWR);
TEST_ASSERT(fd >= 0, __KVM_SYSCALL_ERROR("open() /dev/cpu_dma_latency", fd));

r = write(fd, &latency, 4);
TEST_ASSERT(r >= 1, "Error setting /dev/cpu_dma_latency");
}

for (i = 0; !done; i++) {
vcpu_run(vcpu);
TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
Expand Down Expand Up @@ -278,6 +294,9 @@ int main(int argc, char *argv[])
"rseq CPU = %d, sched CPU = %d", rseq_cpu, cpu);
}

if (fd > 0)
close(fd);

/*
* Sanity check that the test was able to enter the guest a reasonable
* number of times, e.g. didn't get stalled too often/long waiting for
Expand All @@ -293,8 +312,8 @@ int main(int argc, char *argv[])
TEST_ASSERT(skip_sanity_check || i > (NR_TASK_MIGRATIONS / 2),
"Only performed %d KVM_RUNs, task stalled too much?\n\n"
" Try disabling deep sleep states to reduce CPU wakeup latency,\n"
" e.g. via cpuidle.off=1 or setting /dev/cpu_dma_latency to '0',\n"
" or run with -u to disable this sanity check.", i);
" e.g. via cpuidle.off=1 or via -l <latency>, or run with -u to\n"
" disable this sanity check.", i);

pthread_join(migration_thread, NULL);

Expand Down
2 changes: 1 addition & 1 deletion virt/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ config KVM_COMPAT
depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)

config HAVE_KVM_IRQ_BYPASS
bool
tristate
select IRQ_BYPASS_MANAGER

config HAVE_KVM_VCPU_ASYNC_IOCTL
Expand Down
10 changes: 5 additions & 5 deletions virt/kvm/eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ irqfd_shutdown(struct work_struct *work)
/*
* It is now safe to release the object's resources
*/
#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
irq_bypass_unregister_consumer(&irqfd->consumer);
#endif
eventfd_ctx_put(irqfd->eventfd);
Expand Down Expand Up @@ -274,7 +274,7 @@ static void irqfd_update(struct kvm *kvm, struct kvm_kernel_irqfd *irqfd)
write_seqcount_end(&irqfd->irq_entry_sc);
}

#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
void __attribute__((weak)) kvm_arch_irq_bypass_stop(
struct irq_bypass_consumer *cons)
{
Expand Down Expand Up @@ -424,7 +424,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
if (events & EPOLLIN)
schedule_work(&irqfd->inject);

#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
if (kvm_arch_has_irq_bypass()) {
irqfd->consumer.token = (void *)irqfd->eventfd;
irqfd->consumer.add_producer = kvm_arch_irq_bypass_add_producer;
Expand Down Expand Up @@ -609,14 +609,14 @@ void kvm_irq_routing_update(struct kvm *kvm)
spin_lock_irq(&kvm->irqfds.lock);

list_for_each_entry(irqfd, &kvm->irqfds.items, list) {
#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
/* Under irqfds.lock, so can read irq_entry safely */
struct kvm_kernel_irq_routing_entry old = irqfd->irq_entry;
#endif

irqfd_update(kvm, irqfd);

#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
#if IS_ENABLED(CONFIG_HAVE_KVM_IRQ_BYPASS)
if (irqfd->producer &&
kvm_arch_irqfd_route_changed(&old, &irqfd->irq_entry)) {
int ret = kvm_arch_update_irqfd_routing(
Expand Down

0 comments on commit 369348e

Please sign in to comment.