[PATCH v2] vfio/pci: Verify each MSI vector to avoid invalid MSI vectors

2022-11-22 Thread chenxiang via
From: Xiang Chen 

Currently the number of MSI vectors comes from register PCI_MSI_FLAGS
which should be power-of-2 in qemu, in some scenaries it is not the same as
the number that driver requires in guest, for example, a PCI driver wants
to allocate 6 MSI vecotrs in guest, but as the limitation, it will allocate
8 MSI vectors. So it requires 8 MSI vectors in qemu while the driver in
guest only wants to allocate 6 MSI vectors.

When GICv4.1 is enabled, it iterates over all possible MSIs and enable the
forwarding while the guest has only created some of mappings in the virtual
ITS, so some calls fail. The exception print is as following:
vfio-pci :3a:00.1: irq bypass producer (token 8f08224d) registration
fails:66311

To avoid the issue, verify each MSI vector, skip some operations such as
request_irq() and irq_bypass_register_producer() for those invalid MSI vectors.

Signed-off-by: Xiang Chen 
---
I reported the issue at the link:
https://lkml.kernel.org/lkml/87cze9lcut.wl-...@kernel.org/T/

Change Log:
v1 -> v2:
Verify each MSI vector in kernel instead of adding systemcall according to
Mar's suggestion
---
 arch/arm64/kvm/vgic/vgic-irqfd.c  | 13 +
 arch/arm64/kvm/vgic/vgic-its.c| 36 
 arch/arm64/kvm/vgic/vgic.h|  1 +
 drivers/vfio/pci/vfio_pci_intrs.c | 33 +
 include/linux/kvm_host.h  |  2 ++
 5 files changed, 85 insertions(+)

diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
index 475059b..71f6af57 100644
--- a/arch/arm64/kvm/vgic/vgic-irqfd.c
+++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
@@ -98,6 +98,19 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
return vgic_its_inject_msi(kvm, );
 }
 
+int kvm_verify_msi(struct kvm *kvm,
+  struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+   struct kvm_msi msi;
+
+   if (!vgic_has_its(kvm))
+   return -ENODEV;
+
+   kvm_populate_msi(irq_entry, );
+
+   return vgic_its_verify_msi(kvm, );
+}
+
 /**
  * kvm_arch_set_irq_inatomic: fast-path for irqfd injection
  */
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 94a666d..8312a4a 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -767,6 +767,42 @@ int vgic_its_inject_cached_translation(struct kvm *kvm, 
struct kvm_msi *msi)
return 0;
 }
 
+int vgic_its_verify_msi(struct kvm *kvm, struct kvm_msi *msi)
+{
+   struct vgic_its *its;
+   struct its_ite *ite;
+   struct kvm_vcpu *vcpu;
+   int ret = 0;
+
+   if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
+   return -EINVAL;
+
+   if (!vgic_has_its(kvm))
+   return -ENODEV;
+
+   its = vgic_msi_to_its(kvm, msi);
+   if (IS_ERR(its))
+   return PTR_ERR(its);
+
+   mutex_lock(>its_lock);
+   if (!its->enabled) {
+   ret = -EBUSY;
+   goto unlock;
+   }
+   ite = find_ite(its, msi->devid, msi->data);
+   if (!ite || !its_is_collection_mapped(ite->collection)) {
+   ret = E_ITS_INT_UNMAPPED_INTERRUPT;
+   goto unlock;
+   }
+
+   vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
+   if (!vcpu)
+   ret = E_ITS_INT_UNMAPPED_INTERRUPT;
+unlock:
+   mutex_unlock(>its_lock);
+   return ret;
+}
+
 /*
  * Queries the KVM IO bus framework to get the ITS pointer from the given
  * doorbell address.
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 0c8da72..d452150 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -240,6 +240,7 @@ int kvm_vgic_register_its_device(void);
 void vgic_enable_lpis(struct kvm_vcpu *vcpu);
 void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu);
 int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
+int vgic_its_verify_msi(struct kvm *kvm, struct kvm_msi *msi);
 int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr 
*attr);
 int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 int offset, u32 *val);
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 40c3d7c..3027805 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "vfio_pci_priv.h"
 
@@ -315,6 +316,28 @@ static int vfio_msi_enable(struct vfio_pci_core_device 
*vdev, int nvec, bool msi
return 0;
 }
 
+static int vfio_pci_verify_msi_entry(struct vfio_pci_core_device *vdev,
+   struct eventfd_ctx *trigger)
+{
+   struct kvm *kvm = vdev->vdev.kvm;
+   struct kvm_kernel_irqfd *tmp;
+   struct kvm_kernel_irq_routing_entry irq_entry;
+   int ret = -ENODEV;
+
+   spin_lock_irq(>irqfds.lock);
+   list_for_each_entry(tmp, >irqfds.items, list) {
+   

[PATCH] vfio/pci: Add system call KVM_VERIFY_MSI to verify every MSI vector

2022-11-07 Thread chenxiang via
From: Xiang Chen 

Currently the numbers of MSI vectors come from register PCI_MSI_FLAGS
which should be power-of-2, but in some scenaries it is not the same as
the number that driver requires in guest, for example, a PCI driver wants
to allocate 6 MSI vecotrs in guest, but as the limitation, it will allocate
8 MSI vectors. So it requires 8 MSI vectors in qemu while the driver in
guest only wants to allocate 6 MSI vectors.

When GICv4.1 is enabled, we can see some exception print as following for
above scenaro:
vfio-pci :3a:00.1: irq bypass producer (token 8f08224d) 
registration fails:66311

To avoid the issue, add system call KVM_VERIFY_MSI to verify whether every
MSI vecotor is valid and adjust the numver of MSI vectors.

This is qemu part of adding system call KVM_VERIFY_MSI.

Signed-off-by: Xiang Chen 
---
 accel/kvm/kvm-all.c   | 19 +++
 hw/vfio/pci.c | 13 +
 include/sysemu/kvm.h  |  2 ++
 linux-headers/linux/kvm.h |  1 +
 4 files changed, 35 insertions(+)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index f99b0be..19c8b84 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1918,6 +1918,25 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
 return kvm_set_irq(s, route->kroute.gsi, 1);
 }
 
+int kvm_irqchip_verify_msi_route(KVMState *s, int vector, PCIDevice *dev)
+{
+if (pci_available && dev && kvm_msi_devid_required()) {
+   MSIMessage msg = {0, 0};
+   struct kvm_msi msi;
+
+   msg = pci_get_msi_message(dev, vector);
+   msi.address_lo = (uint32_t)msg.address;
+   msi.address_hi = msg.address >> 32;
+   msi.devid = pci_requester_id(dev);
+   msi.data = le32_to_cpu(msg.data);
+   msi.flags = KVM_MSI_VALID_DEVID;
+   memset(msi.pad, 0, sizeof(msi.pad));
+
+   return kvm_vm_ioctl(s, KVM_VERIFY_MSI, );
+}
+return 0;
+}
+
 int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
 {
 struct kvm_irq_routing_entry kroute = {};
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 939dcc3..8dae0e4 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -660,6 +660,7 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
 static void vfio_msi_enable(VFIOPCIDevice *vdev)
 {
 int ret, i;
+int msi_invalid = 0;
 
 vfio_disable_interrupts(vdev);
 
@@ -671,6 +672,18 @@ static void vfio_msi_enable(VFIOPCIDevice *vdev)
 vfio_prepare_kvm_msi_virq_batch(vdev);
 
 vdev->nr_vectors = msi_nr_vectors_allocated(>pdev);
+
+/*
+ * Verify whether every msi interrupt is valid as the number of
+ * MSI vectors comes from PCI device registers which may be not the
+ * same as the number of vectors that driver requires.
+ */
+for (i = 0; i < vdev->nr_vectors; i++) {
+   ret = kvm_irqchip_verify_msi_route(kvm_state, i, >pdev);
+   if (ret < 0)
+   msi_invalid++;
+}
+vdev->nr_vectors -= msi_invalid;
 retry:
 vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->nr_vectors);
 
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index e9a97ed..aca6e5b 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -482,6 +482,8 @@ void kvm_cpu_synchronize_state(CPUState *cpu);
 
 void kvm_init_cpu_signals(CPUState *cpu);
 
+int kvm_irqchip_verify_msi_route(KVMState *s, int vector, PCIDevice *dev);
+
 /**
  * kvm_irqchip_add_msi_route - Add MSI route for specific vector
  * @c:  KVMRouteChange instance.
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index ebdafa5..ac59350 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1540,6 +1540,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_SVM_OFF  _IO(KVMIO,  0xb3)
 #define KVM_ARM_MTE_COPY_TAGS_IOR(KVMIO,  0xb4, struct 
kvm_arm_copy_mte_tags)
 
+#define KVM_VERIFY_MSI_IOW(KVMIO,  0xb5, struct kvm_msi)
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE_IOWR(KVMIO,  0xe0, struct kvm_create_device)
 
-- 
2.8.1




[PATCH] KVM: Add system call KVM_VERIFY_MSI to verify MSI vector

2022-11-07 Thread chenxiang via
From: Xiang Chen 

Currently the numbers of MSI vectors come from register PCI_MSI_FLAGS
which should be power-of-2, but in some scenaries it is not the same as
the number that driver requires in guest, for example, a PCI driver wants
to allocate 6 MSI vecotrs in guest, but as the limitation, it will allocate
8 MSI vectors. So it requires 8 MSI vectors in qemu while the driver in
guest only wants to allocate 6 MSI vectors.

When GICv4.1 is enabled, we can see some exception print as following for
above scenaro:
vfio-pci :3a:00.1: irq bypass producer (token 8f08224d) 
registration fails:66311

In order to verify whether a MSI vector is valid, add KVM_VERIFY_MSI to do
that. If there is a mapping, return 0, otherwise return negative value.

This is the kernel part of adding system call KVM_VERIFY_MSI.

Signed-off-by: Xiang Chen 
---
 arch/arm64/kvm/vgic/vgic-irqfd.c |  5 +
 arch/arm64/kvm/vgic/vgic-its.c   | 36 
 arch/arm64/kvm/vgic/vgic.h   |  1 +
 include/linux/kvm_host.h |  2 +-
 include/uapi/linux/kvm.h |  2 ++
 virt/kvm/kvm_main.c  |  9 +
 6 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
index 475059b..2312da6 100644
--- a/arch/arm64/kvm/vgic/vgic-irqfd.c
+++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
@@ -98,6 +98,11 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
return vgic_its_inject_msi(kvm, );
 }
 
+int kvm_verify_msi(struct kvm *kvm, struct kvm_msi *msi)
+{
+   return vgic_its_verify_msi(kvm, msi);
+}
+
 /**
  * kvm_arch_set_irq_inatomic: fast-path for irqfd injection
  */
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 24d7778..cae6183 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -767,6 +767,42 @@ int vgic_its_inject_cached_translation(struct kvm *kvm, 
struct kvm_msi *msi)
return 0;
 }
 
+int vgic_its_verify_msi(struct kvm *kvm, struct kvm_msi *msi)
+{
+   struct vgic_its *its;
+   struct its_ite *ite;
+   struct kvm_vcpu *vcpu;
+   int ret = 0;
+
+   if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
+   return -EINVAL;
+
+   if (!vgic_has_its(kvm))
+   return -ENODEV;
+
+   its = vgic_msi_to_its(kvm, msi);
+   if (IS_ERR(its))
+   return PTR_ERR(its);
+
+   mutex_lock(>its_lock);
+   if (!its->enabled) {
+   ret = -EBUSY;
+   goto unlock;
+   }
+   ite = find_ite(its, msi->devid, msi->data);
+   if (!ite || !its_is_collection_mapped(ite->collection)) {
+   ret = -E_ITS_INT_UNMAPPED_INTERRUPT;
+   goto unlock;
+   }
+
+   vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
+   if (!vcpu)
+   ret = -E_ITS_INT_UNMAPPED_INTERRUPT;
+unlock:
+   mutex_unlock(>its_lock);
+   return ret;
+}
+
 /*
  * Queries the KVM IO bus framework to get the ITS pointer from the given
  * doorbell address.
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 0c8da72..d452150 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -240,6 +240,7 @@ int kvm_vgic_register_its_device(void);
 void vgic_enable_lpis(struct kvm_vcpu *vcpu);
 void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu);
 int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
+int vgic_its_verify_msi(struct kvm *kvm, struct kvm_msi *msi);
 int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr 
*attr);
 int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 int offset, u32 *val);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 32f259f..7923352 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1597,7 +1597,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
 int kvm_request_irq_source_id(struct kvm *kvm);
 void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
 bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
-
+int kvm_verify_msi(struct kvm *kvm, struct kvm_msi *msi);
 /*
  * Returns a pointer to the memslot if it contains gfn.
  * Otherwise returns NULL.
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 0d5d441..72b28f8 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1543,6 +1543,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_SVM_OFF  _IO(KVMIO,  0xb3)
 #define KVM_ARM_MTE_COPY_TAGS_IOR(KVMIO,  0xb4, struct 
kvm_arm_copy_mte_tags)
 
+#define KVM_VERIFY_MSI_IOW(KVMIO,  0xb5, struct kvm_msi)
+
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE_IOWR(KVMIO,  0xe0, struct kvm_create_device)
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index e30f1b4..439bdd7 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ 

[PATCH v2] hw/vfio/common: Fix a small boundary issue of a trace

2022-04-16 Thread chenxiang via
From: Xiang Chen 

It uses [offset, offset + size - 1] to indicate that the length of range is
size in most places in vfio trace code (such as
trace_vfio_region_region_mmap()) execpt trace_vfio_region_sparse_mmap_entry().
So change it for trace_vfio_region_sparse_mmap_entry(), but if size is zero,
the trace will be weird with an underflow, so move the trace and trace it 
only if size is not zero.

Signed-off-by: Xiang Chen 
---
 hw/vfio/common.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 080046e3f5..345ea7bd8a 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1544,11 +1544,10 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion 
*region,
 region->mmaps = g_new0(VFIOMmap, sparse->nr_areas);
 
 for (i = 0, j = 0; i < sparse->nr_areas; i++) {
-trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset,
-sparse->areas[i].offset +
-sparse->areas[i].size);
-
 if (sparse->areas[i].size) {
+trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset,
+sparse->areas[i].offset +
+sparse->areas[i].size - 1);
 region->mmaps[j].offset = sparse->areas[i].offset;
 region->mmaps[j].size = sparse->areas[i].size;
 j++;
-- 
2.33.0




[PATCH] softmmu/memory: Skip translation size instead of fixed granularity if translate() successfully

2022-04-16 Thread chenxiang via
From: Xiang Chen 

Currently memory_region_iommu_replay() does full page table walk with
fixed granularity (page size) no matter translate() succeeds or not.
Actually if translate() successfully, we can skip translation size
(iotlb.addr_mask + 1) instead of fixed granularity.

 Signed-off-by: Xiang Chen 
---
 softmmu/memory.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/softmmu/memory.c b/softmmu/memory.c
index bfa5d5178c..ccfa19cf71 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -1924,7 +1924,7 @@ void memory_region_iommu_replay(IOMMUMemoryRegion 
*iommu_mr, IOMMUNotifier *n)
 {
 MemoryRegion *mr = MEMORY_REGION(iommu_mr);
 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
-hwaddr addr, granularity;
+hwaddr addr, granularity, def_granu;
 IOMMUTLBEntry iotlb;
 
 /* If the IOMMU has its own replay callback, override */
@@ -1933,12 +1933,15 @@ void memory_region_iommu_replay(IOMMUMemoryRegion 
*iommu_mr, IOMMUNotifier *n)
 return;
 }
 
-granularity = memory_region_iommu_get_min_page_size(iommu_mr);
+def_granu = memory_region_iommu_get_min_page_size(iommu_mr);
 
 for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
 iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx);
 if (iotlb.perm != IOMMU_NONE) {
 n->notify(n, );
+granularity = iotlb.addr_mask + 1;
+} else {
+granularity = def_granu;
 }
 
 /* if (2^64 - MR size) < granularity, it's possible to get an
-- 
2.33.0




[PATCH v2] hw/arm/smmuv3: Pass the actual perm to returned IOMMUTLBEntry in smmuv3_translate()

2022-04-16 Thread chenxiang via
From: Xiang Chen 

It always calls the IOMMU MR translate() callback with flag=IOMMU_NONE in
memory_region_iommu_replay(). Currently, smmuv3_translate() return an
IOMMUTLBEntry with perm set to IOMMU_NONE even if the translation success,
whereas it is expected to return the actual permission set in the table
entry.
So pass the actual perm to returned IOMMUTLBEntry in the table entry.

Signed-off-by: Xiang Chen 
Reviewed-by: Eric Auger 
---
 hw/arm/smmuv3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 674623aabe..707eb430c2 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -760,7 +760,7 @@ epilogue:
 qemu_mutex_unlock(>mutex);
 switch (status) {
 case SMMU_TRANS_SUCCESS:
-entry.perm = flag;
+entry.perm = cached_entry->entry.perm;
 entry.translated_addr = cached_entry->entry.translated_addr +
 (addr & cached_entry->entry.addr_mask);
 entry.addr_mask = cached_entry->entry.addr_mask;
-- 
2.33.0




[PATCH] hw/arm/smmuv3: Pass the real perm to returned IOMMUTLBEntry in smmuv3_translate()

2022-04-07 Thread chenxiang via
From: Xiang Chen 

In function memory_region_iommu_replay(), it decides to notify() or not
according to the perm of returned IOMMUTLBEntry. But for smmuv3, the
returned perm is always IOMMU_NONE even if the translation success.
Pass the real perm to returned IOMMUTLBEntry to avoid the issue.

Signed-off-by: Xiang Chen 
---
 hw/arm/smmuv3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 674623aabe..707eb430c2 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -760,7 +760,7 @@ epilogue:
 qemu_mutex_unlock(>mutex);
 switch (status) {
 case SMMU_TRANS_SUCCESS:
-entry.perm = flag;
+entry.perm = cached_entry->entry.perm;
 entry.translated_addr = cached_entry->entry.translated_addr +
 (addr & cached_entry->entry.addr_mask);
 entry.addr_mask = cached_entry->entry.addr_mask;
-- 
2.33.0




[PATCH] hw/vfio/common: Fix a small boundary issue of a trace

2022-04-06 Thread chenxiang via
From: Xiang Chen 

Right now the trace of vfio_region_sparse_mmap_entry is as follows:
vfio_region_sparse_mmap_entry sparse entry 0 [0x1000 - 0x9000]
Actually the range it wants to show is [0x1000 - 0x8fff]???so fix it.

Signed-off-by: Xiang Chen 
---
 hw/vfio/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 080046e3f5..0b3808caf8 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1546,7 +1546,7 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion 
*region,
 for (i = 0, j = 0; i < sparse->nr_areas; i++) {
 trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset,
 sparse->areas[i].offset +
-sparse->areas[i].size);
+sparse->areas[i].size - 1);
 
 if (sparse->areas[i].size) {
 region->mmaps[j].offset = sparse->areas[i].offset;
-- 
2.33.0




[PATCH] hw/arm/virt: Enable HMAT on arm virt machine

2022-01-25 Thread chenxiang via
From: Xiang Chen 

Since the patchset ("Build ACPI Heterogeneous Memory Attribute Table (HMAT)"),
HMAT is supported, but only x86 is enabled. Enable HMAT on arm virt machine.

Signed-off-by: Xiang Chen 
---
 hw/arm/Kconfig   | 1 +
 hw/arm/virt-acpi-build.c | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 2e0049196d..a3c6099829 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -29,6 +29,7 @@ config ARM_VIRT
 select ACPI_APEI
 select ACPI_VIOT
 select VIRTIO_MEM_SUPPORTED
+select ACPI_HMAT
 
 config CHEETAH
 bool
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 449fab0080..f19b55e486 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -42,6 +42,7 @@
 #include "hw/acpi/memory_hotplug.h"
 #include "hw/acpi/generic_event_device.h"
 #include "hw/acpi/tpm.h"
+#include "hw/acpi/hmat.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
@@ -990,6 +991,12 @@ void virt_acpi_build(VirtMachineState *vms, 
AcpiBuildTables *tables)
 build_slit(tables_blob, tables->linker, ms, vms->oem_id,
vms->oem_table_id);
 }
+
+if (ms->numa_state->hmat_enabled) {
+acpi_add_table(table_offsets, tables_blob);
+build_hmat(tables_blob, tables->linker, ms->numa_state,
+   vms->oem_id, vms->oem_table_id);
+}
 }
 
 if (ms->nvdimms_state->is_enabled) {
-- 
2.33.0