From d1b758ebc2a82d738092cb42e742470f9d0ea53e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 9 Dec 2010 14:53:29 -0500 Subject: xen/irq: Cleanup the find_unbound_irq The "find_unbound_irq" is a bit unusual - it allocates virtual IRQ (event channels) in reverse order. This means starting at the "top" of the available IRQs (nr_irqs) down to the GSI/MSI IRQs (nr_irqs_gsi). Lets document this and also make the variables easier to understand. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 31af0ac31a98..4d4a23d4c9f6 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -405,15 +405,21 @@ static int find_unbound_irq(void) { struct irq_data *data; int irq, res; - int start = get_nr_hw_irqs(); + int bottom = get_nr_hw_irqs(); + int top = nr_irqs-1; - if (start == nr_irqs) + if (bottom == nr_irqs) goto no_irqs; - /* nr_irqs is a magic value. Must not use it.*/ - for (irq = nr_irqs-1; irq > start; irq--) { + /* This loop starts from the top of IRQ space and goes down. + * We need this b/c if we have a PCI device in a Xen PV guest + * we do not have an IO-APIC (though the backend might have them) + * mapped in. To not have a collision of physical IRQs with the Xen + * event channels start at the top of the IRQ space for virtual IRQs. + */ + for (irq = top; irq > bottom; irq--) { data = irq_get_irq_data(irq); - /* only 0->15 have init'd desc; handle irq > 16 */ + /* only 15->0 have init'd desc; handle irq > 16 */ if (!data) break; if (data->chip == &no_irq_chip) @@ -424,7 +430,7 @@ static int find_unbound_irq(void) return irq; } - if (irq == start) + if (irq == bottom) goto no_irqs; res = irq_alloc_desc_at(irq, -1); -- cgit v1.2.3 From c1f5db1a53a7286f6c818f71016ae6aced814d27 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 3 Dec 2010 09:54:03 +0000 Subject: xen: disable ACPI NUMA for PV guests Xen does not currently expose PV-NUMA information to PV guests. Therefore disable NUMA for the time being to prevent the kernel picking up on an host-level NUMA information which it might come across in the firmware. [ Added comment - Jeremy ] Signed-off-by: Ian Campbell Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/enlighten.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 44dcad43989d..ed47d12fdecb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1174,6 +1174,15 @@ asmlinkage void __init xen_start_kernel(void) xen_smp_init(); +#ifdef CONFIG_ACPI_NUMA + /* + * The pages we from Xen are not related to machine pages, so + * any NUMA information the kernel tries to get from ACPI will + * be meaningless. Prevent it from trying. + */ + acpi_numa = -1; +#endif + pgd = (pgd_t *)xen_start_info->pt_base; if (!xen_initial_domain()) -- cgit v1.2.3 From 731f3ab66a23dab28a359e87364f53d221b3d366 Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Fri, 7 Jan 2011 18:17:17 +0800 Subject: xen/fb: fix xenfb suspend/resume race. When migrating guests over a long period we hit this: <1>BUG: unable to handle kernel paging request at 0000000b819fdb98 <1>IP: [] notify_remote_via_irq+0x13/0x34 <4>PGD 94b10067 PUD 0 <0>Oops: 0000 [#1] SMP .. snip.. Call Trace: [] xenfb_send_event+0x5c/0x5e [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? _spin_unlock_irqrestore+0x16/0x18 [] xenfb_refresh+0x1b1/0x1d7 [] ? sys_imageblit+0x1ac/0x458 [] xenfb_imageblit+0x2f/0x34 [] soft_cursor+0x1b5/0x1c8 [] bit_cursor+0x4b6/0x4d7 [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? _spin_unlock_irqrestore+0x16/0x18 [] ? bit_cursor+0x0/0x4d7 [] fb_flashcursor+0xff/0x111 [] ? fb_flashcursor+0x0/0x111 [] worker_thread+0x14d/0x1ed [] ? autoremove_wake_function+0x0/0x3d [] ? _spin_unlock_irqrestore+0x16/0x18 [] ? worker_thread+0x0/0x1ed [] kthread+0x6e/0x76 [] child_rip+0xa/0x20 [] ? int_ret_from_sys_call+0x7/0x1b [] ? retint_restore_args+0x5/0x6 [] ? child_rip+0x0/0x20 Code: 6b ff 0c 8b 87 a4 db 9f 81 66 85 c0 74 08 0f b7 f8 e8 3b ff ff ff c9 c3 55 48 89 e5 48 83 ec 10 0f 1f 44 00 00 89 ff 48 6b ff 0c <8b> 87 a4 db 9f 81 66 85 c0 74 14 48 8d 75 f0 0f b7 c0 bf 04 00 RIP [] notify_remote_via_irq+0x13/0x34 RSP CR2: 0000000b819fdb98 ---[ end trace 098b4b74827595d0 ]--- The root cause of the panic is the race between the resume and reconnect to the backend. Clearing the 'update_wanted' flag of xenfb before disconnecting from the backend fixes this issue. Signed-off-by: Joe Jin Signed-off-by: Konrad Rzeszutek Wilk Tested-by: Gurudas Pai Acked-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Andrew Morton --- drivers/video/xen-fbfront.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index 428d273be727..f92313d33e27 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -617,6 +617,8 @@ static int xenfb_connect_backend(struct xenbus_device *dev, static void xenfb_disconnect_backend(struct xenfb_info *info) { + /* Prevent xenfb refresh */ + info->update_wanted = 0; if (info->irq >= 0) unbind_from_irqhandler(info->irq, info); info->irq = -1; -- cgit v1.2.3 From fc550e95921e109f3778a6b2dc560d63388810ab Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Fri, 7 Jan 2011 18:20:54 +0800 Subject: xen/fb: fix potential memory leak This patch fixes a potential memory leak when xenfb connect to the backend fails. Thanks for Ian's review and comments. [v2: reworded the commit message a bit] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Joe Jin Tested-by: Gurudas Pai Acked-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Andrew Morton --- drivers/video/xen-fbfront.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index f92313d33e27..95bbd0a1e5da 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -562,26 +562,24 @@ static void xenfb_init_shared_page(struct xenfb_info *info, static int xenfb_connect_backend(struct xenbus_device *dev, struct xenfb_info *info) { - int ret, evtchn; + int ret, evtchn, irq; struct xenbus_transaction xbt; ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) return ret; - ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, + irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, 0, dev->devicetype, info); - if (ret < 0) { + if (irq < 0) { xenbus_free_evtchn(dev, evtchn); xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); - return ret; + return irq; } - info->irq = ret; - again: ret = xenbus_transaction_start(&xbt); if (ret) { xenbus_dev_fatal(dev, ret, "starting transaction"); - return ret; + goto unbind_irq; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page)); @@ -603,15 +601,18 @@ static int xenfb_connect_backend(struct xenbus_device *dev, if (ret == -EAGAIN) goto again; xenbus_dev_fatal(dev, ret, "completing transaction"); - return ret; + goto unbind_irq; } xenbus_switch_state(dev, XenbusStateInitialised); + info->irq = irq; return 0; error_xenbus: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, ret, "writing xenstore"); + unbind_irq: + unbind_from_irqhandler(irq, info); return ret; } -- cgit v1.2.3 From 110e7c7e4f8a61a34e0ab88fc9bdf4d5c6d220b2 Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Fri, 7 Jan 2011 14:50:12 +0800 Subject: xen/event: validate irq before get evtchn by irq When retrieving the event channel number from irq, the irq number may not be valid under some conditions. So far that can be when we suspend/resume and irq ends with -1. Validate and return sanitized irq and provide diagnostics information. [v3: added unlikely on the WARN path] [v2: reworded the commit message] Signed-off-by: Joe Jin Signed-off-by: Konrad Rzeszutek Wilk Tested-by: Gurudas Pai Cc: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Andrew Morton --- drivers/xen/events.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 4d4a23d4c9f6..3df7e477694a 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -170,6 +170,9 @@ static struct irq_info *info_for_irq(unsigned irq) static unsigned int evtchn_from_irq(unsigned irq) { + if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq))) + return 0; + return info_for_irq(irq)->evtchn; } -- cgit v1.2.3