From c06b6d70feb32d28f04ba37aa3df17973fd37b6b Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Fri, 15 Apr 2016 18:23:00 -0700 Subject: xen/x86: don't lose event interrupts On slow platforms with unreliable TSC, such as QEMU emulated machines, it is possible for the kernel to request the next event in the past. In that case, in the current implementation of xen_vcpuop_clockevent, we simply return -ETIME. To be precise the Xen returns -ETIME and we pass it on. However the result of this is a missed event, which simply causes the kernel to hang. Instead it is better to always ask the hypervisor for a timer event, even if the timeout is in the past. That way there are no lost interrupts and the kernel survives. To do that, remove the VCPU_SSHOTTMR_future flag. Signed-off-by: Stefano Stabellini Acked-by: Juergen Gross --- arch/x86/xen/time.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index a0a4e55..6deba5b 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -290,11 +290,11 @@ static int xen_vcpuop_set_next_event(unsigned long delta, WARN_ON(!clockevent_state_oneshot(evt)); single.timeout_abs_ns = get_abs_timeout(delta); - single.flags = VCPU_SSHOTTMR_future; + /* Get an event anyway, even if the timeout is already expired */ + single.flags = 0; ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single); - - BUG_ON(ret != 0 && ret != -ETIME); + BUG_ON(ret != 0); return ret; } -- cgit v1.1 From 36ae220aa62d382a8bacbf7ec080d9d36a2b4d49 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 9 May 2016 10:59:48 +0100 Subject: xen/gntdev: reduce copy batch size to 16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IOCTL_GNTDEV_GRANT_COPY batches copy operations to reduce the number of hypercalls. The stack is used to avoid a memory allocation in a hot path. However, a batch size of 24 requires more than 1024 bytes of stack which in some configurations causes a compiler warning. xen/gntdev.c: In function ‘gntdev_ioctl_grant_copy’: xen/gntdev.c:949:1: warning: the frame size of 1248 bytes is larger than 1024 bytes [-Wframe-larger-than=] This is a harmless warning as there is still plenty of stack spare, but people keep trying to "fix" it. Reduce the batch size to 16 to reduce stack usage to less than 1024 bytes. This should have minimal impact on performance. Signed-off-by: David Vrabel --- drivers/xen/gntdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index dc49538..6793957 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -748,7 +748,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) return rc; } -#define GNTDEV_COPY_BATCH 24 +#define GNTDEV_COPY_BATCH 16 struct gntdev_copy_batch { struct gnttab_copy ops[GNTDEV_COPY_BATCH]; -- cgit v1.1 From 971a69db7dc02faaeed325c195f5db5da597cb58 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 11 May 2016 14:47:59 +0200 Subject: Xen: don't warn about 2-byte wchar_t in efi The XEN UEFI code has become available on the ARM architecture recently, but now causes a link-time warning: ld: warning: drivers/xen/efi.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail This seems harmless, because the efi code only uses 2-byte characters when interacting with EFI, so we don't pass on those strings to elsewhere in the system, and we just need to silence the warning. It is not clear to me whether we actually need to build the file with the -fshort-wchar flag, but if we do, then we should also pass --no-wchar-size-warning to the linker, to avoid the warning. Signed-off-by: Arnd Bergmann Reviewed-by: Stefano Stabellini Fixes: 37060935dc04 ("ARM64: XEN: Add a function to initialize Xen specific UEFI runtime services") --- drivers/xen/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 9b7a35c..030e91b 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -8,6 +8,7 @@ nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_features.o := $(nostackp) CFLAGS_efi.o += -fshort-wchar +LDFLAGS += $(call ld-option, --no-wchar-size-warning) dom0-$(CONFIG_PCI) += pci.o dom0-$(CONFIG_USB_SUPPORT) += dbgp.o -- cgit v1.1 From 702f926067d2a4b28c10a3c41a1172dd62d9e735 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 20 Apr 2016 14:15:01 +0100 Subject: xen/x86: actually allocate legacy interrupts on PV guests b4ff8389ed14 is incomplete: relies on nr_legacy_irqs() to get the number of legacy interrupts when actually nr_legacy_irqs() returns 0 after probe_8259A(). Use NR_IRQS_LEGACY instead. Signed-off-by: Stefano Stabellini CC: stable@vger.kernel.org --- arch/x86/pci/xen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index beac4df..349b8ce 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -491,8 +491,11 @@ int __init pci_xen_initial_domain(void) #endif __acpi_register_gsi = acpi_register_gsi_xen; __acpi_unregister_gsi = NULL; - /* Pre-allocate legacy irqs */ - for (irq = 0; irq < nr_legacy_irqs(); irq++) { + /* + * Pre-allocate the legacy IRQs. Use NR_LEGACY_IRQS here + * because we don't have a PIC and thus nr_legacy_irqs() is zero. + */ + for (irq = 0; irq < NR_IRQS_LEGACY; irq++) { int trigger, polarity; if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) -- cgit v1.1 From f0f393877c71ad227d36705d61d1e4062bc29cf5 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 10 May 2016 16:11:00 +0100 Subject: xen/events: Don't move disabled irqs Commit ff1e22e7a638 ("xen/events: Mask a moving irq") open-coded irq_move_irq() but left out checking if the IRQ is disabled. This broke resuming from suspend since it tries to move a (disabled) irq without holding the IRQ's desc->lock. Fix it by adding in a check for disabled IRQs. The resulting stacktrace was: kernel BUG at /build/linux-UbQGH5/linux-4.4.0/kernel/irq/migration.c:31! invalid opcode: 0000 [#1] SMP Modules linked in: xenfs xen_privcmd ... CPU: 0 PID: 9 Comm: migration/0 Not tainted 4.4.0-22-generic #39-Ubuntu Hardware name: Xen HVM domU, BIOS 4.6.1-xs125180 05/04/2016 task: ffff88003d75ee00 ti: ffff88003d7bc000 task.ti: ffff88003d7bc000 RIP: 0010:[] [] irq_move_masked_irq+0xd2/0xe0 RSP: 0018:ffff88003d7bfc50 EFLAGS: 00010046 RAX: 0000000000000000 RBX: ffff88003d40ba00 RCX: 0000000000000001 RDX: 0000000000000001 RSI: 0000000000000100 RDI: ffff88003d40bad8 RBP: ffff88003d7bfc68 R08: 0000000000000000 R09: ffff88003d000000 R10: 0000000000000000 R11: 000000000000023c R12: ffff88003d40bad0 R13: ffffffff81f3a4a0 R14: 0000000000000010 R15: 00000000ffffffff FS: 0000000000000000(0000) GS:ffff88003da00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd4264de624 CR3: 0000000037922000 CR4: 00000000003406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Stack: ffff88003d40ba38 0000000000000024 0000000000000000 ffff88003d7bfca0 ffffffff814c8d92 00000010813ef89d 00000000805ea732 0000000000000009 0000000000000024 ffff88003cc39b80 ffff88003d7bfce0 ffffffff814c8f66 Call Trace: [] eoi_pirq+0xb2/0xf0 [] __startup_pirq+0xe6/0x150 [] xen_irq_resume+0x319/0x360 [] xen_suspend+0xb5/0x180 [] multi_cpu_stop+0xb5/0xe0 [] ? cpu_stop_queue_work+0x80/0x80 [] cpu_stopper_thread+0xb0/0x140 [] ? finish_task_switch+0x76/0x220 [] ? __raw_callee_save___pv_queued_spin_unlock+0x11/0x20 [] smpboot_thread_fn+0x105/0x160 [] ? sort_range+0x30/0x30 [] kthread+0xd8/0xf0 [] ? kthread_create_on_node+0x1e0/0x1e0 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x1e0/0x1e0 Signed-off-by: Ross Lagerwall Reviewed-by: Boris Ostrovsky Cc: Signed-off-by: David Vrabel --- drivers/xen/events/events_base.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index cb7138c..71d49a9 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -487,7 +487,8 @@ static void eoi_pirq(struct irq_data *data) if (!VALID_EVTCHN(evtchn)) return; - if (unlikely(irqd_is_setaffinity_pending(data))) { + if (unlikely(irqd_is_setaffinity_pending(data)) && + likely(!irqd_irq_disabled(data))) { int masked = test_and_set_mask(evtchn); clear_evtchn(evtchn); @@ -1370,7 +1371,8 @@ static void ack_dynirq(struct irq_data *data) if (!VALID_EVTCHN(evtchn)) return; - if (unlikely(irqd_is_setaffinity_pending(data))) { + if (unlikely(irqd_is_setaffinity_pending(data)) && + likely(!irqd_irq_disabled(data))) { int masked = test_and_set_mask(evtchn); clear_evtchn(evtchn); -- cgit v1.1 From dd14be92fbf5bc1ef7343f34968440e44e21b46a Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Wed, 18 May 2016 16:44:54 +0200 Subject: xen: use same main loop for counting and remapping pages Instead of having two functions for cycling through the E820 map in order to count to be remapped pages and remap them later, just use one function with a caller supplied sub-function called for each region to be processed. This eliminates the possibility of a mismatch between both loops which showed up in certain configurations. Suggested-by: Ed Swierk Signed-off-by: Juergen Gross Cc: Signed-off-by: David Vrabel --- arch/x86/xen/setup.c | 65 +++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 7ab2951..e345891 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -393,6 +393,9 @@ static unsigned long __init xen_set_identity_and_remap_chunk( unsigned long i = 0; unsigned long n = end_pfn - start_pfn; + if (remap_pfn == 0) + remap_pfn = nr_pages; + while (i < n) { unsigned long cur_pfn = start_pfn + i; unsigned long left = n - i; @@ -438,17 +441,29 @@ static unsigned long __init xen_set_identity_and_remap_chunk( return remap_pfn; } -static void __init xen_set_identity_and_remap(unsigned long nr_pages) +static unsigned long __init xen_count_remap_pages( + unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, + unsigned long remap_pages) +{ + if (start_pfn >= nr_pages) + return remap_pages; + + return remap_pages + min(end_pfn, nr_pages) - start_pfn; +} + +static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, + unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn, + unsigned long nr_pages, unsigned long last_val)) { phys_addr_t start = 0; - unsigned long last_pfn = nr_pages; + unsigned long ret_val = 0; const struct e820entry *entry = xen_e820_map; int i; /* * Combine non-RAM regions and gaps until a RAM region (or the - * end of the map) is reached, then set the 1:1 map and - * remap the memory in those non-RAM regions. + * end of the map) is reached, then call the provided function + * to perform its duty on the non-RAM region. * * The combined non-RAM regions are rounded to a whole number * of pages so any partial pages are accessible via the 1:1 @@ -466,14 +481,13 @@ static void __init xen_set_identity_and_remap(unsigned long nr_pages) end_pfn = PFN_UP(entry->addr); if (start_pfn < end_pfn) - last_pfn = xen_set_identity_and_remap_chunk( - start_pfn, end_pfn, nr_pages, - last_pfn); + ret_val = func(start_pfn, end_pfn, nr_pages, + ret_val); start = end; } } - pr_info("Released %ld page(s)\n", xen_released_pages); + return ret_val; } /* @@ -596,35 +610,6 @@ static void __init xen_ignore_unusable(void) } } -static unsigned long __init xen_count_remap_pages(unsigned long max_pfn) -{ - unsigned long extra = 0; - unsigned long start_pfn, end_pfn; - const struct e820entry *entry = xen_e820_map; - int i; - - end_pfn = 0; - for (i = 0; i < xen_e820_map_entries; i++, entry++) { - start_pfn = PFN_DOWN(entry->addr); - /* Adjacent regions on non-page boundaries handling! */ - end_pfn = min(end_pfn, start_pfn); - - if (start_pfn >= max_pfn) - return extra + max_pfn - end_pfn; - - /* Add any holes in map to result. */ - extra += start_pfn - end_pfn; - - end_pfn = PFN_UP(entry->addr + entry->size); - end_pfn = min(end_pfn, max_pfn); - - if (entry->type != E820_RAM) - extra += end_pfn - start_pfn; - } - - return extra; -} - bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) { struct e820entry *entry; @@ -804,7 +789,7 @@ char * __init xen_memory_setup(void) max_pages = xen_get_max_pages(); /* How many extra pages do we need due to remapping? */ - max_pages += xen_count_remap_pages(max_pfn); + max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages); if (max_pages > max_pfn) extra_pages += max_pages - max_pfn; @@ -922,7 +907,9 @@ char * __init xen_memory_setup(void) * Set identity map on non-RAM pages and prepare remapping the * underlying RAM. */ - xen_set_identity_and_remap(max_pfn); + xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk); + + pr_info("Released %ld page(s)\n", xen_released_pages); return "Xen"; } -- cgit v1.1