b56a1fa35b
- kvm-numa-Validate-cluster-and-NUMA-node-boundary-if-requ.patch [bz#2171363] - kvm-hw-arm-Validate-cluster-and-NUMA-node-boundary.patch [bz#2171363] - kvm-hw-arm-virt-Validate-cluster-and-NUMA-node-boundary-.patch [bz#2171363] - kvm-vhost-fix-vhost_dev_enable_notifiers-error-case.patch [RHEL-330] - kvm-kvm-reuse-per-vcpu-stats-fd-to-avoid-vcpu-interrupti.patch [bz#2218644] - kvm-vhost-vdpa-do-not-cleanup-the-vdpa-vhost-net-structu.patch [bz#2128929] - Resolves: bz#2171363 ([aarch64] Kernel hits Call trace with irregular CPU-to-NUMA association) - Resolves: RHEL-330 ([virtual network][qemu-kvm-8.0.0-rc1]qemu core dump: qemu-kvm: ../softmmu/memory.c:2592: void memory_region_del_eventfd(MemoryRegion *, hwaddr, unsigned int, _Bool, uint64_t, EventNotifier *): Assertion `i != mr->ioeventfd_nb' failed) - Resolves: bz#2218644 (query-stats QMP command interrupts vcpus, the Max Latencies could be more than 100us (rhel 9.3.0 clone)) - Resolves: bz#2128929 ([rhel9.2] hotplug/hotunplug mlx vdpa device to the occupied addr port, then qemu core dump occurs after shutdown guest)
161 lines
6.3 KiB
Diff
161 lines
6.3 KiB
Diff
From a5857fb12fcad46e27c415fe82ce13c0cb5d09c7 Mon Sep 17 00:00:00 2001
|
|
From: Marcelo Tosatti <mtosatti@redhat.com>
|
|
Date: Thu, 29 Jun 2023 14:48:32 -0300
|
|
Subject: [PATCH 5/6] kvm: reuse per-vcpu stats fd to avoid vcpu interruption
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
RH-Author: Marcelo Tosatti <None>
|
|
RH-MergeRequest: 177: kvm: reuse per-vcpu stats fd to avoid vcpu interruption
|
|
RH-Bugzilla: 2218644
|
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
RH-Acked-by: Leonardo Brás <leobras@redhat.com>
|
|
RH-Commit: [1/1] 4ec72385a9047888121485f49bacb1aff84f7018 (mtosatti/qemu-kvm)
|
|
|
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2218644
|
|
Commit: 3b6f485275ae95a81eec589d2773b86ca9ddec4d
|
|
|
|
A regression has been detected in latency testing of KVM guests.
|
|
More specifically, it was observed that the cyclictest
|
|
numbers inside of an isolated vcpu (running on isolated pcpu) are:
|
|
|
|
Where a maximum of 50us is acceptable.
|
|
|
|
The implementation of KVM_GET_STATS_FD uses run_on_cpu to query
|
|
per vcpu statistics, which interrupts the vcpu (and is unnecessary).
|
|
|
|
To fix this, open the per vcpu stats fd on vcpu initialization,
|
|
and read from that fd from QEMU's main thread.
|
|
|
|
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
---
|
|
accel/kvm/kvm-all.c | 30 +++++++++++++++---------------
|
|
include/hw/core/cpu.h | 1 +
|
|
2 files changed, 16 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
|
index cf3a88d90e..fa7ca46c66 100644
|
|
--- a/accel/kvm/kvm-all.c
|
|
+++ b/accel/kvm/kvm-all.c
|
|
@@ -450,6 +450,8 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
|
"kvm_init_vcpu: kvm_arch_init_vcpu failed (%lu)",
|
|
kvm_arch_vcpu_id(cpu));
|
|
}
|
|
+ cpu->kvm_vcpu_stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
|
+
|
|
err:
|
|
return ret;
|
|
}
|
|
@@ -3959,7 +3961,7 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
|
|
|
|
/* Read stats header */
|
|
kvm_stats_header = &descriptors->kvm_stats_header;
|
|
- ret = read(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header));
|
|
+ ret = pread(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header), 0);
|
|
if (ret != sizeof(*kvm_stats_header)) {
|
|
error_setg(errp, "KVM stats: failed to read stats header: "
|
|
"expected %zu actual %zu",
|
|
@@ -3990,7 +3992,8 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd
|
|
}
|
|
|
|
static void query_stats(StatsResultList **result, StatsTarget target,
|
|
- strList *names, int stats_fd, Error **errp)
|
|
+ strList *names, int stats_fd, CPUState *cpu,
|
|
+ Error **errp)
|
|
{
|
|
struct kvm_stats_desc *kvm_stats_desc;
|
|
struct kvm_stats_header *kvm_stats_header;
|
|
@@ -4048,7 +4051,7 @@ static void query_stats(StatsResultList **result, StatsTarget target,
|
|
break;
|
|
case STATS_TARGET_VCPU:
|
|
add_stats_entry(result, STATS_PROVIDER_KVM,
|
|
- current_cpu->parent_obj.canonical_path,
|
|
+ cpu->parent_obj.canonical_path,
|
|
stats_list);
|
|
break;
|
|
default:
|
|
@@ -4085,10 +4088,9 @@ static void query_stats_schema(StatsSchemaList **result, StatsTarget target,
|
|
add_stats_schema(result, STATS_PROVIDER_KVM, target, stats_list);
|
|
}
|
|
|
|
-static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
|
|
+static void query_stats_vcpu(CPUState *cpu, StatsArgs *kvm_stats_args)
|
|
{
|
|
- StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
|
|
- int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
|
+ int stats_fd = cpu->kvm_vcpu_stats_fd;
|
|
Error *local_err = NULL;
|
|
|
|
if (stats_fd == -1) {
|
|
@@ -4097,14 +4099,13 @@ static void query_stats_vcpu(CPUState *cpu, run_on_cpu_data data)
|
|
return;
|
|
}
|
|
query_stats(kvm_stats_args->result.stats, STATS_TARGET_VCPU,
|
|
- kvm_stats_args->names, stats_fd, kvm_stats_args->errp);
|
|
- close(stats_fd);
|
|
+ kvm_stats_args->names, stats_fd, cpu,
|
|
+ kvm_stats_args->errp);
|
|
}
|
|
|
|
-static void query_stats_schema_vcpu(CPUState *cpu, run_on_cpu_data data)
|
|
+static void query_stats_schema_vcpu(CPUState *cpu, StatsArgs *kvm_stats_args)
|
|
{
|
|
- StatsArgs *kvm_stats_args = (StatsArgs *) data.host_ptr;
|
|
- int stats_fd = kvm_vcpu_ioctl(cpu, KVM_GET_STATS_FD, NULL);
|
|
+ int stats_fd = cpu->kvm_vcpu_stats_fd;
|
|
Error *local_err = NULL;
|
|
|
|
if (stats_fd == -1) {
|
|
@@ -4114,7 +4115,6 @@ static void query_stats_schema_vcpu(CPUState *cpu, run_on_cpu_data data)
|
|
}
|
|
query_stats_schema(kvm_stats_args->result.schema, STATS_TARGET_VCPU, stats_fd,
|
|
kvm_stats_args->errp);
|
|
- close(stats_fd);
|
|
}
|
|
|
|
static void query_stats_cb(StatsResultList **result, StatsTarget target,
|
|
@@ -4132,7 +4132,7 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target,
|
|
error_setg_errno(errp, errno, "KVM stats: ioctl failed");
|
|
return;
|
|
}
|
|
- query_stats(result, target, names, stats_fd, errp);
|
|
+ query_stats(result, target, names, stats_fd, NULL, errp);
|
|
close(stats_fd);
|
|
break;
|
|
}
|
|
@@ -4146,7 +4146,7 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target,
|
|
if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
|
|
continue;
|
|
}
|
|
- run_on_cpu(cpu, query_stats_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
|
|
+ query_stats_vcpu(cpu, &stats_args);
|
|
}
|
|
break;
|
|
}
|
|
@@ -4172,6 +4172,6 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
|
|
if (first_cpu) {
|
|
stats_args.result.schema = result;
|
|
stats_args.errp = errp;
|
|
- run_on_cpu(first_cpu, query_stats_schema_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
|
|
+ query_stats_schema_vcpu(first_cpu, &stats_args);
|
|
}
|
|
}
|
|
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
|
|
index 397fd3ac68..ae96be07e7 100644
|
|
--- a/include/hw/core/cpu.h
|
|
+++ b/include/hw/core/cpu.h
|
|
@@ -399,6 +399,7 @@ struct CPUState {
|
|
struct kvm_dirty_gfn *kvm_dirty_gfns;
|
|
uint32_t kvm_fetch_index;
|
|
uint64_t dirty_pages;
|
|
+ int kvm_vcpu_stats_fd;
|
|
|
|
/* Use by accel-block: CPU is executing an ioctl() */
|
|
QemuLockCnt in_ioctl_lock;
|
|
--
|
|
2.39.3
|
|
|