[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 2/3] hw/nvme: use KVM irqfd when available
From: |
Jinhao Fan |
Subject: |
[PATCH v2 2/3] hw/nvme: use KVM irqfd when available |
Date: |
Thu, 25 Aug 2022 15:47:45 +0800 |
Use KVM's irqfd to send interrupts when possible. This approach is
thread safe. Moreover, it does not have the inter-thread communication
overhead of plain event notifiers since handler callback are called
in the same system call as irqfd write.
Signed-off-by: Jinhao Fan <fanjinhao21s@ict.ac.cn>
---
hw/nvme/ctrl.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
hw/nvme/nvme.h | 1 +
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 6ecf6fafd9..74075f782f 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -192,6 +192,7 @@
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
#include "sysemu/block-backend.h"
#include "sysemu/hostmem.h"
#include "hw/pci/msix.h"
@@ -1377,8 +1378,26 @@ static void nvme_deassert_notifier_read(EventNotifier *e)
}
}
+static int nvme_kvm_msix_vector_use(NvmeCtrl *n,
+ NvmeCQueue *cq,
+ uint32_t vector)
+{
+ int ret;
+
+ KVMRouteChange c = kvm_irqchip_begin_route_changes(kvm_state);
+ ret = kvm_irqchip_add_msi_route(&c, vector, &n->parent_obj);
+ if (ret < 0) {
+ return ret;
+ }
+ kvm_irqchip_commit_route_changes(&c);
+ cq->virq = ret;
+ return 0;
+}
+
static void nvme_init_irq_notifier(NvmeCtrl *n, NvmeCQueue *cq)
{
+ bool with_irqfd = msix_enabled(&n->parent_obj) &&
+ kvm_msi_via_irqfd_enabled();
int ret;
ret = event_notifier_init(&cq->assert_notifier, 0);
@@ -1386,8 +1405,21 @@ static void nvme_init_irq_notifier(NvmeCtrl *n,
NvmeCQueue *cq)
goto fail_assert_handler;
}
- event_notifier_set_handler(&cq->assert_notifier,
- nvme_assert_notifier_read);
+ if (with_irqfd) {
+ ret = nvme_kvm_msix_vector_use(n, cq, cq->vector);
+ if (ret < 0) {
+ goto fail_assert_handler;
+ }
+ ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state,
+ &cq->assert_notifier, NULL,
+ cq->virq);
+ if (ret < 0) {
+ goto fail_kvm;
+ }
+ } else {
+ event_notifier_set_handler(&cq->assert_notifier,
+ nvme_assert_notifier_read);
+ }
if (!msix_enabled(&n->parent_obj)) {
ret = event_notifier_init(&cq->deassert_notifier, 0);
@@ -1404,6 +1436,12 @@ static void nvme_init_irq_notifier(NvmeCtrl *n,
NvmeCQueue *cq)
fail_deassert_handler:
event_notifier_set_handler(&cq->deassert_notifier, NULL);
event_notifier_cleanup(&cq->deassert_notifier);
+ if (with_irqfd) {
+ kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &cq->assert_notifier,
+ cq->virq);
+fail_kvm:
+ kvm_irqchip_release_virq(kvm_state, cq->virq);
+ }
fail_assert_handler:
event_notifier_set_handler(&cq->assert_notifier, NULL);
event_notifier_cleanup(&cq->assert_notifier);
@@ -4783,6 +4821,8 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest
*req)
static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
{
+ bool with_irqfd = msix_enabled(&n->parent_obj) &&
+ kvm_msi_via_irqfd_enabled();
uint16_t offset = (cq->cqid << 3) + (1 << 2);
n->cq[cq->cqid] = NULL;
@@ -4794,6 +4834,12 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
event_notifier_cleanup(&cq->notifier);
}
if (cq->assert_notifier.initialized) {
+ if (with_irqfd) {
+ kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state,
+ &cq->assert_notifier,
+ cq->virq);
+ kvm_irqchip_release_virq(kvm_state, cq->virq);
+ }
event_notifier_set_handler(&cq->assert_notifier, NULL);
event_notifier_cleanup(&cq->assert_notifier);
}
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 759d0ecd7c..85fd9cd0e2 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -396,6 +396,7 @@ typedef struct NvmeCQueue {
uint64_t dma_addr;
uint64_t db_addr;
uint64_t ei_addr;
+ int virq;
QEMUTimer *timer;
EventNotifier notifier;
EventNotifier assert_notifier;
--
2.25.1
- [PATCH v2 0/3] hw/nvme: add irqfd support, Jinhao Fan, 2022/08/25
- [PATCH v2 2/3] hw/nvme: use KVM irqfd when available,
Jinhao Fan <=
- [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Jinhao Fan, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Klaus Jensen, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Jinhao Fan, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Klaus Jensen, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Klaus Jensen, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Jinhao Fan, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Klaus Jensen, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Jinhao Fan, 2022/08/25
- Re: [PATCH v2 1/3] hw/nvme: support irq(de)assertion with eventfd, Jinhao Fan, 2022/08/25
[PATCH v2 3/3] hw/nvme: add MSI-x mask handlers for irqfd, Jinhao Fan, 2022/08/25