aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk2016-02-11 15:10:26 -0600
committerGreg Kroah-Hartman2016-03-03 17:06:54 -0600
commit08b706179843ff538c51bf11a04b893f149b6247 (patch)
treec923e795efcdf56858fad1f1deded6cf1e834dd2
parent478ee5e09bbd59e219cc6d281c84e9495f006ab8 (diff)
downloadkernel-video-08b706179843ff538c51bf11a04b893f149b6247.tar.gz
kernel-video-08b706179843ff538c51bf11a04b893f149b6247.tar.xz
kernel-video-08b706179843ff538c51bf11a04b893f149b6247.zip
xen/pcifront: Fix mysterious crashes when NUMA locality information was extracted.
commit 4d8c8bd6f2062c9988817183a91fe2e623c8aa5e upstream. Occasionaly PV guests would crash with: pciback 0000:00:00.1: Xen PCI mapped GSI0 to IRQ16 BUG: unable to handle kernel paging request at 0000000d1a8c0be0 .. snip.. <ffffffff8139ce1b>] find_next_bit+0xb/0x10 [<ffffffff81387f22>] cpumask_next_and+0x22/0x40 [<ffffffff813c1ef8>] pci_device_probe+0xb8/0x120 [<ffffffff81529097>] ? driver_sysfs_add+0x77/0xa0 [<ffffffff815293e4>] driver_probe_device+0x1a4/0x2d0 [<ffffffff813c1ddd>] ? pci_match_device+0xdd/0x110 [<ffffffff81529657>] __device_attach_driver+0xa7/0xb0 [<ffffffff815295b0>] ? __driver_attach+0xa0/0xa0 [<ffffffff81527622>] bus_for_each_drv+0x62/0x90 [<ffffffff8152978d>] __device_attach+0xbd/0x110 [<ffffffff815297fb>] device_attach+0xb/0x10 [<ffffffff813b75ac>] pci_bus_add_device+0x3c/0x70 [<ffffffff813b7618>] pci_bus_add_devices+0x38/0x80 [<ffffffff813dc34e>] pcifront_scan_root+0x13e/0x1a0 [<ffffffff817a0692>] pcifront_backend_changed+0x262/0x60b [<ffffffff814644c6>] ? xenbus_gather+0xd6/0x160 [<ffffffff8120900f>] ? put_object+0x2f/0x50 [<ffffffff81465c1d>] xenbus_otherend_changed+0x9d/0xa0 [<ffffffff814678ee>] backend_changed+0xe/0x10 [<ffffffff81463a28>] xenwatch_thread+0xc8/0x190 [<ffffffff810f22f0>] ? woken_wake_function+0x10/0x10 which was the result of two things: When we call pci_scan_root_bus we would pass in 'sd' (sysdata) pointer which was an 'pcifront_sd' structure. However in the pci_device_add it expects that the 'sd' is 'struct sysdata' and sets the dev->node to what is in sd->node (offset 4): set_dev_node(&dev->dev, pcibus_to_node(bus)); __pcibus_to_node(const struct pci_bus *bus) { const struct pci_sysdata *sd = bus->sysdata; return sd->node; } However our structure was pcifront_sd which had nothing at that offset: struct pcifront_sd { int domain; /* 0 4 */ /* XXX 4 bytes hole, try to pack */ struct pcifront_device * pdev; /* 8 8 */ } That is an hole - filled with garbage as we used kmalloc instead of kzalloc (the second problem). This patch fixes the issue by: 1) Use kzalloc to initialize to a well known state. 2) Put 'struct pci_sysdata' at the start of 'pcifront_sd'. That way access to the 'node' will access the right offset. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/pci/xen-pcifront.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 179b8edc226..318d535e337 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -52,7 +52,7 @@ struct pcifront_device {
52}; 52};
53 53
54struct pcifront_sd { 54struct pcifront_sd {
55 int domain; 55 struct pci_sysdata sd;
56 struct pcifront_device *pdev; 56 struct pcifront_device *pdev;
57}; 57};
58 58
@@ -66,7 +66,9 @@ static inline void pcifront_init_sd(struct pcifront_sd *sd,
66 unsigned int domain, unsigned int bus, 66 unsigned int domain, unsigned int bus,
67 struct pcifront_device *pdev) 67 struct pcifront_device *pdev)
68{ 68{
69 sd->domain = domain; 69 /* Because we do not expose that information via XenBus. */
70 sd->sd.node = first_online_node;
71 sd->sd.domain = domain;
70 sd->pdev = pdev; 72 sd->pdev = pdev;
71} 73}
72 74
@@ -464,8 +466,8 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
464 dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n", 466 dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
465 domain, bus); 467 domain, bus);
466 468
467 bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL); 469 bus_entry = kzalloc(sizeof(*bus_entry), GFP_KERNEL);
468 sd = kmalloc(sizeof(*sd), GFP_KERNEL); 470 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
469 if (!bus_entry || !sd) { 471 if (!bus_entry || !sd) {
470 err = -ENOMEM; 472 err = -ENOMEM;
471 goto err_out; 473 goto err_out;