197 lines
5.9 KiB
Diff
197 lines
5.9 KiB
Diff
|
|
From c4829aa6fce007c995b21cfbd86de0473263c19a Mon Sep 17 00:00:00 2001
|
||
|
|
From: Dongxu Sun <sundongxu3@huawei.com>
|
||
|
|
Date: Sat, 30 Mar 2024 12:49:05 +0800
|
||
|
|
Subject: [PATCH] shadow_dev: introduce shadow dev for virtio-net device
|
||
|
|
|
||
|
|
for virtio net devices, create the shadow device for vlpi
|
||
|
|
bypass inject supported.
|
||
|
|
|
||
|
|
Signed-off-by: Wang Haibin <wanghaibin.wang@huawei.com>
|
||
|
|
Signed-off-by: Yu Zenghui <yuzenghui@huawei.com>
|
||
|
|
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
|
||
|
|
Signed-off-by: KunKun Jiang <jiangkunkun@huawei.com>
|
||
|
|
Signed-off-by: Dongxu Sun <sundongxu3@huawei.com>
|
||
|
|
Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
|
||
|
|
---
|
||
|
|
hw/virtio/virtio-pci.c | 32 ++++++++++++++++++++++++++
|
||
|
|
include/sysemu/kvm.h | 5 +++++
|
||
|
|
linux-headers/linux/kvm.h | 13 +++++++++++
|
||
|
|
target/arm/kvm.c | 47 +++++++++++++++++++++++++++++++++++++++
|
||
|
|
4 files changed, 97 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
|
||
|
|
index 134a8eaef6..f8adb0520a 100644
|
||
|
|
--- a/hw/virtio/virtio-pci.c
|
||
|
|
+++ b/hw/virtio/virtio-pci.c
|
||
|
|
@@ -922,18 +922,44 @@ undo:
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+int __attribute__((weak)) kvm_create_shadow_device(PCIDevice *dev)
|
||
|
|
+{
|
||
|
|
+ return 0;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int __attribute__((weak)) kvm_delete_shadow_device(PCIDevice *dev)
|
||
|
|
+{
|
||
|
|
+ return 0;
|
||
|
|
+}
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs)
|
||
|
|
{
|
||
|
|
int queue_no;
|
||
|
|
int ret = 0;
|
||
|
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||
|
|
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+ if (!strcmp(vdev->name, "virtio-net")) {
|
||
|
|
+ kvm_create_shadow_device(&proxy->pci_dev);
|
||
|
|
+ }
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
for (queue_no = 0; queue_no < nvqs; queue_no++) {
|
||
|
|
if (!virtio_queue_get_num(vdev, queue_no)) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
ret = kvm_virtio_pci_vector_use_one(proxy, queue_no);
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+ if (!strcmp(vdev->name, "virtio-net") && ret != 0) {
|
||
|
|
+ kvm_delete_shadow_device(&proxy->pci_dev);
|
||
|
|
+ }
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -976,6 +1002,12 @@ static void kvm_virtio_pci_vector_vq_release(VirtIOPCIProxy *proxy, int nvqs)
|
||
|
|
}
|
||
|
|
kvm_virtio_pci_vector_release_one(proxy, queue_no);
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+ if (!strcmp(vdev->name, "virtio-net")) {
|
||
|
|
+ kvm_delete_shadow_device(&proxy->pci_dev);
|
||
|
|
+ }
|
||
|
|
+#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy)
|
||
|
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||
|
|
index d614878164..b46d6203b4 100644
|
||
|
|
--- a/include/sysemu/kvm.h
|
||
|
|
+++ b/include/sysemu/kvm.h
|
||
|
|
@@ -538,4 +538,9 @@ bool kvm_arch_cpu_check_are_resettable(void);
|
||
|
|
bool kvm_dirty_ring_enabled(void);
|
||
|
|
|
||
|
|
uint32_t kvm_dirty_ring_size(void);
|
||
|
|
+
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+int kvm_create_shadow_device(PCIDevice *dev);
|
||
|
|
+int kvm_delete_shadow_device(PCIDevice *dev);
|
||
|
|
+#endif
|
||
|
|
#endif
|
||
|
|
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||
|
|
index 549fea3a97..56f6b2583f 100644
|
||
|
|
--- a/linux-headers/linux/kvm.h
|
||
|
|
+++ b/linux-headers/linux/kvm.h
|
||
|
|
@@ -1198,6 +1198,8 @@ struct kvm_ppc_resize_hpt {
|
||
|
|
#define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229
|
||
|
|
#define KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES 230
|
||
|
|
|
||
|
|
+#define KVM_CAP_ARM_VIRT_MSI_BYPASS 799
|
||
|
|
+
|
||
|
|
#ifdef KVM_CAP_IRQ_ROUTING
|
||
|
|
|
||
|
|
struct kvm_irq_routing_irqchip {
|
||
|
|
@@ -1524,6 +1526,17 @@ struct kvm_s390_ucas_mapping {
|
||
|
|
#define KVM_XEN_HVM_CONFIG _IOW(KVMIO, 0x7a, struct kvm_xen_hvm_config)
|
||
|
|
#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data)
|
||
|
|
#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data)
|
||
|
|
+
|
||
|
|
+#ifdef __aarch64__
|
||
|
|
+struct kvm_master_dev_info
|
||
|
|
+{
|
||
|
|
+ __u32 nvectors; /* number of msi vectors */
|
||
|
|
+ struct kvm_msi msi[0];
|
||
|
|
+};
|
||
|
|
+#define KVM_CREATE_SHADOW_DEV _IOW(KVMIO, 0xf0, struct kvm_master_dev_info)
|
||
|
|
+#define KVM_DEL_SHADOW_DEV _IOW(KVMIO, 0xf1, __u32)
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
/* Available with KVM_CAP_PIT_STATE2 */
|
||
|
|
#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
|
||
|
|
#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
|
||
|
|
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
||
|
|
index 7903e2ddde..f59f4f81b2 100644
|
||
|
|
--- a/target/arm/kvm.c
|
||
|
|
+++ b/target/arm/kvm.c
|
||
|
|
@@ -26,6 +26,8 @@
|
||
|
|
#include "trace.h"
|
||
|
|
#include "internals.h"
|
||
|
|
#include "hw/pci/pci.h"
|
||
|
|
+#include "hw/pci/msi.h"
|
||
|
|
+#include "hw/pci/msix.h"
|
||
|
|
#include "exec/memattrs.h"
|
||
|
|
#include "exec/address-spaces.h"
|
||
|
|
#include "hw/boards.h"
|
||
|
|
@@ -1053,6 +1055,51 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
+int kvm_create_shadow_device(PCIDevice *dev)
|
||
|
|
+{
|
||
|
|
+ KVMState *s = kvm_state;
|
||
|
|
+ struct kvm_master_dev_info *mdi;
|
||
|
|
+ MSIMessage msg;
|
||
|
|
+ uint32_t vector, nvectors = msix_nr_vectors_allocated(dev);
|
||
|
|
+ uint32_t request_id;
|
||
|
|
+ int ret;
|
||
|
|
+
|
||
|
|
+ if (!kvm_vm_check_extension(s, KVM_CAP_ARM_VIRT_MSI_BYPASS) || !nvectors) {
|
||
|
|
+ return 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ mdi = g_malloc0(sizeof(uint32_t) + sizeof(struct kvm_msi) * nvectors);
|
||
|
|
+ mdi->nvectors = nvectors;
|
||
|
|
+ request_id = pci_requester_id(dev);
|
||
|
|
+
|
||
|
|
+ for (vector = 0; vector < nvectors; vector++) {
|
||
|
|
+ msg = msix_get_message(dev, vector);
|
||
|
|
+ mdi->msi[vector].address_lo = extract64(msg.address, 0, 32);
|
||
|
|
+ mdi->msi[vector].address_hi = extract64(msg.address, 32, 32);
|
||
|
|
+ mdi->msi[vector].data = le32_to_cpu(msg.data);
|
||
|
|
+ mdi->msi[vector].flags = KVM_MSI_VALID_DEVID;
|
||
|
|
+ mdi->msi[vector].devid = request_id;
|
||
|
|
+ memset(mdi->msi[vector].pad, 0, sizeof(mdi->msi[vector].pad));
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ ret = kvm_vm_ioctl(s, KVM_CREATE_SHADOW_DEV, mdi);
|
||
|
|
+ g_free(mdi);
|
||
|
|
+ return ret;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int kvm_delete_shadow_device(PCIDevice *dev)
|
||
|
|
+{
|
||
|
|
+ KVMState *s = kvm_state;
|
||
|
|
+ uint32_t request_id, nvectors = msix_nr_vectors_allocated(dev);
|
||
|
|
+
|
||
|
|
+ if (!kvm_vm_check_extension(s, KVM_CAP_ARM_VIRT_MSI_BYPASS) || !nvectors) {
|
||
|
|
+ return 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ request_id = pci_requester_id(dev);
|
||
|
|
+ return kvm_vm_ioctl(s, KVM_DEL_SHADOW_DEV, &request_id);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
|
||
|
|
int vector, PCIDevice *dev)
|
||
|
|
{
|
||
|
|
--
|
||
|
|
2.27.0
|
||
|
|
|