|
[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);
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |