[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] BUG: bad page map under Xen
On Mon, Oct 21, 2013 at 04:12:56PM +0100, Jan Beulich wrote: > >>> On 21.10.13 at 16:44, Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > >>> wrote: > > On Mon, Oct 21, 2013 at 03:27:50PM +0100, Jan Beulich wrote: > >> >>> On 21.10.13 at 16:18, Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > >> >>> wrote: > >> > On Mon, Oct 21, 2013 at 04:06:07PM +0200, Lukas Hejtmanek wrote: > >> >> Region 2: Memory at 380fff000000 (64-bit, prefetchable) > >> >> [size=8M] > >> >... > >> > --- a/arch/x86/xen/setup.c > >> > +++ b/arch/x86/xen/setup.c > >> > @@ -92,6 +92,9 @@ static void __init xen_add_extra_mem(u64 start, u64 > >> > size) > >> > > >> > __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); > >> > } > >> > + /* Anything past the balloon area is marked as identity. */ > >> > + for (pfn = xen_max_p2m_pfn; pfn < MAX_DOMAIN_PAGES; pfn++) > >> > + __set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)); > >> > >> Hardly - MAX_DOMAIN_PAGES derives from > >> CONFIG_XEN_MAX_DOMAIN_MEMORY, which in turn is unrelated > >> to where MMIO might be. Should you perhaps simply start from > > > > Looks like your mailer ate some words. > > I don't think so - they're all there in the text you quoted. > > >> an all 1:1 mapping, inserting the RAM translations as you find > >> them? > > > > > > Yeah, as this code can be called for the regions under 4GB. Definitly > > needs more analysis. > > > > Were you suggesting a lookup when we scan the PCI devices? (xen_add_device)? > > That was for PVH, and is obviously fragile, as there can be MMIO > regions not matched by any PCI device's BAR. We could hope for > all of them to be below 4Gb, but I think (based on logs I got to see > recently from a certain vendor's upcoming systems) this isn't going > to work out. This is the patch I had in mind that I think will fix these issues. But I would appreciate testing it and naturally send me the dmesg if possible. diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b232908..258e3f9 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -133,6 +133,25 @@ static void balloon_append(struct page *page) adjust_managed_page_count(page, -1); } +/* + * Check if any the balloon pages overlap with the supplied + * pfn and its range. + */ +bool balloon_pfn(unsigned long pfn, unsigned long nr) +{ + struct page *page; + + if (list_empty(&ballooned_pages)) + return false; + + list_for_each_entry(page, &ballooned_pages, lru) { + unsigned long b_pfn = page_to_pfn(page); + + if (b_pfn >= pfn && b_pfn < pfn + nr) + return true; + } + return false; +} /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ static struct page *balloon_retrieve(bool prefer_highmem) { diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c index 18fff88..7e5ff49 100644 --- a/drivers/xen/pci.c +++ b/drivers/xen/pci.c @@ -17,11 +17,16 @@ * Author: Weidong Han <weidong.han@xxxxxxxxx> */ +#define DEBUG 1 + #include <linux/pci.h> #include <linux/acpi.h> #include <xen/xen.h> #include <xen/interface/physdev.h> #include <xen/interface/xen.h> +#include <xen/interface/memory.h> +#include <xen/page.h> +#include <xen/balloon.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -123,10 +128,78 @@ static int xen_add_device(struct device *dev) r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci); } - return r; } +static void xen_p2m_add_device(struct device *dev) +{ + int i; + struct pci_dev *pci_dev = to_pci_dev(dev); + + /* Verify whether the MMIO BARs are 1-1 in the P2M. */ + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + unsigned long pfn, start, end, ok_pfns; + char bus_addr[64]; + char *fmt; + + if (!pci_resource_len(pci_dev, i)) + continue; + + if (pci_resource_flags(pci_dev, i) == IORESOURCE_IO) + fmt = " (bus address [%#06llx-%#06llx])"; + else + fmt = " (bus address [%#010llx-%#010llx])"; + + snprintf(bus_addr, sizeof(bus_addr), fmt, + (unsigned long long) (pci_resource_start(pci_dev, i)), + (unsigned long long) (pci_resource_end(pci_dev, i))); + + start = pci_resource_start(pci_dev, i) >> PAGE_SHIFT; + end = pci_resource_end(pci_dev, i) >> PAGE_SHIFT; + + /* + * We don't worry about the balloon scratch page as it has a + * valid PFN - which means we will catch in the loop below. + */ + if (balloon_pfn(start, end - start)) { + dev_warn(dev, "%s is within balloon pages!\n", bus_addr); + continue; + } + + for (ok_pfns = 0, pfn = start; pfn < end; pfn ++) { + unsigned long mfn = pfn_to_mfn(pfn); + + if (mfn == pfn) { + ok_pfns ++; + continue; + } + if (mfn != INVALID_P2M_ENTRY) { /* RAM */ + dev_warn(dev, "%s is within RAM [%lx] region!\n", bus_addr, pfn); + break; + } + } + dev_dbg(dev, "%s pfn:%lx, s:%lx, e:%lx ok:%ld\n", bus_addr, pfn, start, end, ok_pfns); + if (pfn != end - 1) /* We broke out of the loop above. */ + continue; + + if (ok_pfns == end - start) /* All good. */ + continue; + + dev_dbg(dev, "%s [%lx->%lx]\n", bus_addr, start, end); + + /* This BAR was not detected during E820 parsing. */ + for (pfn = start; pfn < end; pfn ++) { + if (!set_phys_to_machine(pfn, pfn)) + break; + } + WARN(pfn != end - 1, "Only set %ld instead of %ld PFNs!\n", + end - pfn, end - start); + + dev_info(dev, "%s set %ld page(s) to 1-1 mapping.\n", + bus_addr, end - pfn); + } +} + static int xen_remove_device(struct device *dev) { int r; @@ -164,10 +237,14 @@ static int xen_pci_notifier(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_ADD_DEVICE: - r = xen_add_device(dev); + if (xen_initial_domain()) + r = xen_add_device(dev); + if (r == 0) + xen_p2m_add_device(dev); break; case BUS_NOTIFY_DEL_DEVICE: - r = xen_remove_device(dev); + if (xen_initial_domain()) + r = xen_remove_device(dev); break; default: return NOTIFY_DONE; @@ -185,9 +262,8 @@ static struct notifier_block device_nb = { static int __init register_xen_pci_notifier(void) { - if (!xen_initial_domain()) + if (!xen_domain()) return 0; - return bus_register_notifier(&pci_bus_type, &device_nb); } diff --git a/include/xen/balloon.h b/include/xen/balloon.h index a4c1c6a..60ecc50 100644 --- a/include/xen/balloon.h +++ b/include/xen/balloon.h @@ -41,3 +41,4 @@ static inline int register_xen_selfballooning(struct device *dev) return -ENOSYS; } #endif +bool balloon_pfn(unsigned long pfn, unsigned long nr); > > Jan > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |