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

[PATCH] x86/PVH: PHYSDEVOP_pci_mmcfg_reserved should not blindly register a region



The op has a register/unregister flag, and hence registration shouldn't
happen unilaterally. Introduce unregister_vpci_mmcfg_handler() to handle
this case.

Fixes: eb3dd90e4089 ("x86/physdev: enable PHYSDEVOP_pci_mmcfg_reserved for PVH 
Dom0")
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -558,6 +558,47 @@ int register_vpci_mmcfg_handler(struct d
     return 0;
 }
 
+int unregister_vpci_mmcfg_handler(struct domain *d, paddr_t addr,
+                                  unsigned int start_bus, unsigned int end_bus,
+                                  unsigned int seg)
+{
+    struct hvm_mmcfg *mmcfg;
+    int rc = -ENOENT;
+
+    ASSERT(is_hardware_domain(d));
+
+    if ( start_bus > end_bus )
+        return -EINVAL;
+
+    write_lock(&d->arch.hvm.mmcfg_lock);
+
+    list_for_each_entry ( mmcfg, &d->arch.hvm.mmcfg_regions, next )
+        if ( mmcfg->addr == addr + (start_bus << 20) &&
+             mmcfg->segment == seg &&
+             mmcfg->start_bus == start_bus &&
+             mmcfg->size == ((end_bus - start_bus + 1) << 20) )
+        {
+            list_del(&mmcfg->next);
+            if ( !list_empty(&d->arch.hvm.mmcfg_regions) )
+                xfree(mmcfg);
+            else
+            {
+                /*
+                 * Cannot unregister the MMIO handler - leave a fake entry
+                 * on the list.
+                 */
+                memset(mmcfg, 0, sizeof(*mmcfg));
+                list_add(&mmcfg->next, &d->arch.hvm.mmcfg_regions);
+            }
+            rc = 0;
+            break;
+        }
+
+    write_unlock(&d->arch.hvm.mmcfg_lock);
+
+    return rc;
+}
+
 void destroy_vpci_mmcfg(struct domain *d)
 {
     struct list_head *mmcfg_regions = &d->arch.hvm.mmcfg_regions;
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -559,12 +559,18 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
         if ( !ret && has_vpci(currd) )
         {
             /*
-             * For HVM (PVH) domains try to add the newly found MMCFG to the
-             * domain.
+             * For HVM (PVH) domains try to add/remove the reported MMCFG
+             * to/from the domain.
              */
-            ret = register_vpci_mmcfg_handler(currd, info.address,
-                                              info.start_bus, info.end_bus,
-                                              info.segment);
+            if ( info.flags & XEN_PCI_MMCFG_RESERVED )
+                ret = register_vpci_mmcfg_handler(currd, info.address,
+                                                  info.start_bus, info.end_bus,
+                                                  info.segment);
+            else
+                ret = unregister_vpci_mmcfg_handler(currd, info.address,
+                                                    info.start_bus,
+                                                    info.end_bus,
+                                                    info.segment);
         }
 
         break;
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -178,6 +178,9 @@ void register_vpci_portio_handler(struct
 int register_vpci_mmcfg_handler(struct domain *d, paddr_t addr,
                                 unsigned int start_bus, unsigned int end_bus,
                                 unsigned int seg);
+int unregister_vpci_mmcfg_handler(struct domain *d, paddr_t addr,
+                                  unsigned int start_bus, unsigned int end_bus,
+                                  unsigned int seg);
 /* Destroy tracked MMCFG areas. */
 void destroy_vpci_mmcfg(struct domain *d);
 



 


Rackspace

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