diff options
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 3 | ||||
| -rw-r--r-- | drivers/xen/Makefile | 2 | ||||
| -rw-r--r-- | drivers/xen/preempt.c | 44 | ||||
| -rw-r--r-- | drivers/xen/privcmd.c | 2 | ||||
| -rw-r--r-- | include/xen/xen-ops.h | 26 |
6 files changed, 79 insertions, 1 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 000d4199b03e..31e2d5bf3e38 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -982,6 +982,9 @@ ENTRY(xen_hypervisor_callback) | |||
| 982 | ENTRY(xen_do_upcall) | 982 | ENTRY(xen_do_upcall) |
| 983 | 1: mov %esp, %eax | 983 | 1: mov %esp, %eax |
| 984 | call xen_evtchn_do_upcall | 984 | call xen_evtchn_do_upcall |
| 985 | #ifndef CONFIG_PREEMPT | ||
| 986 | call xen_maybe_preempt_hcall | ||
| 987 | #endif | ||
| 985 | jmp ret_from_intr | 988 | jmp ret_from_intr |
| 986 | CFI_ENDPROC | 989 | CFI_ENDPROC |
| 987 | ENDPROC(xen_hypervisor_callback) | 990 | ENDPROC(xen_hypervisor_callback) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index db13655c3a2a..10074ad9ebf8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -1208,6 +1208,9 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) | |||
| 1208 | popq %rsp | 1208 | popq %rsp |
| 1209 | CFI_DEF_CFA_REGISTER rsp | 1209 | CFI_DEF_CFA_REGISTER rsp |
| 1210 | decl PER_CPU_VAR(irq_count) | 1210 | decl PER_CPU_VAR(irq_count) |
| 1211 | #ifndef CONFIG_PREEMPT | ||
| 1212 | call xen_maybe_preempt_hcall | ||
| 1213 | #endif | ||
| 1211 | jmp error_exit | 1214 | jmp error_exit |
| 1212 | CFI_ENDPROC | 1215 | CFI_ENDPROC |
| 1213 | END(xen_do_hypervisor_callback) | 1216 | END(xen_do_hypervisor_callback) |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 2140398a2a8c..2ccd3592d41f 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
| @@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),) | |||
| 2 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o | 2 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o |
| 3 | endif | 3 | endif |
| 4 | obj-$(CONFIG_X86) += fallback.o | 4 | obj-$(CONFIG_X86) += fallback.o |
| 5 | obj-y += grant-table.o features.o balloon.o manage.o | 5 | obj-y += grant-table.o features.o balloon.o manage.o preempt.o |
| 6 | obj-y += events/ | 6 | obj-y += events/ |
| 7 | obj-y += xenbus/ | 7 | obj-y += xenbus/ |
| 8 | 8 | ||
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c new file mode 100644 index 000000000000..a1800c150839 --- /dev/null +++ b/drivers/xen/preempt.c | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * Preemptible hypercalls | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Citrix Systems R&D ltd. | ||
| 5 | * | ||
| 6 | * This source code is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation; either version 2 of the | ||
| 9 | * License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sched.h> | ||
| 13 | #include <xen/xen-ops.h> | ||
| 14 | |||
| 15 | #ifndef CONFIG_PREEMPT | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Some hypercalls issued by the toolstack can take many 10s of | ||
| 19 | * seconds. Allow tasks running hypercalls via the privcmd driver to | ||
| 20 | * be voluntarily preempted even if full kernel preemption is | ||
| 21 | * disabled. | ||
| 22 | * | ||
| 23 | * Such preemptible hypercalls are bracketed by | ||
| 24 | * xen_preemptible_hcall_begin() and xen_preemptible_hcall_end() | ||
| 25 | * calls. | ||
| 26 | */ | ||
| 27 | |||
| 28 | DEFINE_PER_CPU(bool, xen_in_preemptible_hcall); | ||
| 29 | EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall); | ||
| 30 | |||
| 31 | asmlinkage __visible void xen_maybe_preempt_hcall(void) | ||
| 32 | { | ||
| 33 | if (unlikely(__this_cpu_read(xen_in_preemptible_hcall) | ||
| 34 | && should_resched())) { | ||
| 35 | /* | ||
| 36 | * Clear flag as we may be rescheduled on a different | ||
| 37 | * cpu. | ||
| 38 | */ | ||
| 39 | __this_cpu_write(xen_in_preemptible_hcall, false); | ||
| 40 | _cond_resched(); | ||
| 41 | __this_cpu_write(xen_in_preemptible_hcall, true); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | #endif /* CONFIG_PREEMPT */ | ||
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 569a13b9e856..59ac71c4a043 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
| @@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata) | |||
| 56 | if (copy_from_user(&hypercall, udata, sizeof(hypercall))) | 56 | if (copy_from_user(&hypercall, udata, sizeof(hypercall))) |
| 57 | return -EFAULT; | 57 | return -EFAULT; |
| 58 | 58 | ||
| 59 | xen_preemptible_hcall_begin(); | ||
| 59 | ret = privcmd_call(hypercall.op, | 60 | ret = privcmd_call(hypercall.op, |
| 60 | hypercall.arg[0], hypercall.arg[1], | 61 | hypercall.arg[0], hypercall.arg[1], |
| 61 | hypercall.arg[2], hypercall.arg[3], | 62 | hypercall.arg[2], hypercall.arg[3], |
| 62 | hypercall.arg[4]); | 63 | hypercall.arg[4]); |
| 64 | xen_preemptible_hcall_end(); | ||
| 63 | 65 | ||
| 64 | return ret; | 66 | return ret; |
| 65 | } | 67 | } |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 7491ee5d8164..83338210ee04 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
| @@ -46,4 +46,30 @@ static inline efi_system_table_t __init *xen_efi_probe(void) | |||
| 46 | } | 46 | } |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_PREEMPT | ||
| 50 | |||
| 51 | static inline void xen_preemptible_hcall_begin(void) | ||
| 52 | { | ||
| 53 | } | ||
| 54 | |||
| 55 | static inline void xen_preemptible_hcall_end(void) | ||
| 56 | { | ||
| 57 | } | ||
| 58 | |||
| 59 | #else | ||
| 60 | |||
| 61 | DECLARE_PER_CPU(bool, xen_in_preemptible_hcall); | ||
| 62 | |||
| 63 | static inline void xen_preemptible_hcall_begin(void) | ||
| 64 | { | ||
| 65 | __this_cpu_write(xen_in_preemptible_hcall, true); | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline void xen_preemptible_hcall_end(void) | ||
| 69 | { | ||
| 70 | __this_cpu_write(xen_in_preemptible_hcall, false); | ||
| 71 | } | ||
| 72 | |||
| 73 | #endif /* CONFIG_PREEMPT */ | ||
| 74 | |||
| 49 | #endif /* INCLUDE_XEN_OPS_H */ | 75 | #endif /* INCLUDE_XEN_OPS_H */ |
