[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 08/18] x86/hvm: add length to mmio check op



When memory mapped I/O is range checked by internal handlers, the length
of the access should be taken into account.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
Cc: Keir Fraser <keir@xxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c                   |    7 ++++---
 xen/arch/x86/hvm/intercept.c              |    2 +-
 xen/arch/x86/hvm/vioapic.c                |   17 ++++++++++++++---
 xen/arch/x86/hvm/vlapic.c                 |    8 +++++---
 xen/arch/x86/hvm/vmsi.c                   |   27 ++++++++++++++++++++-------
 xen/drivers/passthrough/amd/iommu_guest.c |   18 +++++++++++++++---
 xen/include/asm-x86/hvm/io.h              |    4 +++-
 7 files changed, 62 insertions(+), 21 deletions(-)

diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index 8958873..1a1f239 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -498,10 +498,11 @@ static int hpet_write(
     return X86EMUL_OKAY;
 }
 
-static int hpet_range(struct vcpu *v, unsigned long addr)
+static int hpet_range(struct vcpu *v, unsigned long addr,
+                      unsigned long length)
 {
-    return ( (addr >= HPET_BASE_ADDRESS) &&
-             (addr < (HPET_BASE_ADDRESS + HPET_MMAP_SIZE)) );
+    return (addr >= HPET_BASE_ADDRESS) &&
+           ((addr + length) < (HPET_BASE_ADDRESS + HPET_MMAP_SIZE));
 }
 
 static const struct hvm_mmio_ops hpet_mmio_ops = {
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index 4db024e..5e8d8b2 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -38,7 +38,7 @@ static bool_t hvm_mmio_accept(struct hvm_io_handler *handler,
 {
     BUG_ON(handler->type != IOREQ_TYPE_COPY);
 
-    return handler->u.mmio.ops->check(current, addr);
+    return handler->u.mmio.ops->check(current, addr, size);
 }
 
 static int hvm_mmio_read(struct hvm_io_handler *handler,
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 9ad909b..4a9b33e 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -242,12 +242,13 @@ static int vioapic_write(
     return X86EMUL_OKAY;
 }
 
-static int vioapic_range(struct vcpu *v, unsigned long addr)
+static int vioapic_range(struct vcpu *v, unsigned long addr,
+                        unsigned long length)
 {
     struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
 
-    return ((addr >= vioapic->base_address &&
-             (addr < vioapic->base_address + VIOAPIC_MEM_LENGTH)));
+    return (addr >= vioapic->base_address) &&
+           ((addr + length) <= (vioapic->base_address + VIOAPIC_MEM_LENGTH));
 }
 
 static const struct hvm_mmio_ops vioapic_mmio_ops = {
@@ -466,3 +467,13 @@ void vioapic_deinit(struct domain *d)
     xfree(d->arch.hvm_domain.vioapic);
     d->arch.hvm_domain.vioapic = NULL;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index f2052cf..7421fc5 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -986,14 +986,16 @@ int hvm_x2apic_msr_write(struct vcpu *v, unsigned int 
msr, uint64_t msr_content)
     return vlapic_reg_write(v, offset, (uint32_t)msr_content);
 }
 
-static int vlapic_range(struct vcpu *v, unsigned long addr)
+static int vlapic_range(struct vcpu *v, unsigned long address,
+                        unsigned long len)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
-    unsigned long offset  = addr - vlapic_base_address(vlapic);
+    unsigned long offset  = address - vlapic_base_address(vlapic);
 
     return !vlapic_hw_disabled(vlapic) &&
            !vlapic_x2apic_mode(vlapic) &&
-           (offset < PAGE_SIZE);
+           (address >= vlapic_base_address(vlapic)) &&
+           ((offset + len) <= PAGE_SIZE);
 }
 
 static const struct hvm_mmio_ops vlapic_mmio_ops = {
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 09ea301..61fe391 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -168,14 +168,14 @@ struct msixtbl_entry
 static DEFINE_RCU_READ_LOCK(msixtbl_rcu_lock);
 
 static struct msixtbl_entry *msixtbl_find_entry(
-    struct vcpu *v, unsigned long addr)
+    struct vcpu *v, unsigned long address, unsigned long len)
 {
     struct msixtbl_entry *entry;
     struct domain *d = v->domain;
 
     list_for_each_entry( entry, &d->arch.hvm_domain.msixtbl_list, list )
-        if ( addr >= entry->gtable &&
-             addr < entry->gtable + entry->table_len )
+        if ( (address >= entry->gtable) &&
+             ((address + len) <= (entry->gtable + entry->table_len)) )
             return entry;
 
     return NULL;
@@ -214,7 +214,7 @@ static int msixtbl_read(
 
     rcu_read_lock(&msixtbl_rcu_lock);
 
-    entry = msixtbl_find_entry(v, address);
+    entry = msixtbl_find_entry(v, address, len);
     if ( !entry )
         goto out;
     offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
@@ -273,7 +273,7 @@ static int msixtbl_write(struct vcpu *v, unsigned long 
address,
 
     rcu_read_lock(&msixtbl_rcu_lock);
 
-    entry = msixtbl_find_entry(v, address);
+    entry = msixtbl_find_entry(v, address, len);
     if ( !entry )
         goto out;
     nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
@@ -333,12 +333,15 @@ out:
     return r;
 }
 
-static int msixtbl_range(struct vcpu *v, unsigned long addr)
+static int msixtbl_range(struct vcpu *v, unsigned long address,
+                         unsigned long len)
 {
+    struct msixtbl_entry *entry;
     const struct msi_desc *desc;
 
     rcu_read_lock(&msixtbl_rcu_lock);
-    desc = msixtbl_addr_to_desc(msixtbl_find_entry(v, addr), addr);
+    entry = msixtbl_find_entry(v, address, len);
+    desc = msixtbl_addr_to_desc(entry, address);
     rcu_read_unlock(&msixtbl_rcu_lock);
 
     return !!desc;
@@ -514,3 +517,13 @@ void msix_write_completion(struct vcpu *v)
     if ( msixtbl_write(v, ctrl_address, 4, 0) != X86EMUL_OKAY )
         gdprintk(XENLOG_WARNING, "MSI-X write completion failure\n");
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/passthrough/amd/iommu_guest.c 
b/xen/drivers/passthrough/amd/iommu_guest.c
index 9c3c488..dd84281 100644
--- a/xen/drivers/passthrough/amd/iommu_guest.c
+++ b/xen/drivers/passthrough/amd/iommu_guest.c
@@ -868,12 +868,14 @@ static void guest_iommu_reg_init(struct guest_iommu 
*iommu)
     iommu->reg_ext_feature.hi = upper;
 }
 
-static int guest_iommu_mmio_range(struct vcpu *v, unsigned long addr)
+static int guest_iommu_mmio_range(struct vcpu *v, unsigned long addr,
+                                  unsigned long length)
 {
     struct guest_iommu *iommu = vcpu_iommu(v);
 
-    return iommu && addr >= iommu->mmio_base &&
-           addr < iommu->mmio_base + IOMMU_MMIO_SIZE;
+    return iommu &&
+           (addr >= iommu->mmio_base) &&
+           ((addr + length) <= (iommu->mmio_base + IOMMU_MMIO_SIZE));
 }
 
 static const struct hvm_mmio_ops iommu_mmio_ops = {
@@ -926,3 +928,13 @@ void guest_iommu_destroy(struct domain *d)
 
     domain_hvm_iommu(d)->arch.g_iommu = NULL;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
index fecd02d..b4596fc 100644
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -35,7 +35,9 @@ typedef int (*hvm_mmio_write_t)(struct vcpu *v,
                                 unsigned long addr,
                                 unsigned long length,
                                 unsigned long val);
-typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
+typedef int (*hvm_mmio_check_t)(struct vcpu *v,
+                                unsigned long addr,
+                                unsigned long length);
 
 struct hvm_mmio_ops {
     hvm_mmio_check_t check;
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.