All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3] x86/xen: allow privcmd hypercalls to be preempted
@ 2014-02-27 15:07 David Vrabel
  2014-02-28  2:38 ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 3+ messages in thread
From: David Vrabel @ 2014-02-27 15:07 UTC (permalink / raw)
  To: xen-devel; +Cc: Boris Ostrovsky, David Vrabel

From: David Vrabel <david.vrabel@citrix.com>

Hypercalls submitted by user space tools via the privcmd driver can
take a long time (potentially many 10s of seconds) if the hypercall
has many sub-operations.

A fully preemptible kernel may deschedule such as task in any upcall
called from a hypercall continuation.

However, in a kernel with voluntary or no preemption, hypercall
continuations in Xen allow event handlers to be run but the task
issuing the hypercall will not be descheduled until the hypercall is
complete and the ioctl returns to user space.  These long running
tasks may also trigger the kernel's soft lockup detection.

Add xen_preemptible_hcall_begin() and xen_preemptible_hcall_end() to
bracket hypercalls that may be preempted.  Use these in the privcmd
driver.

When returning from an upcall, call preempt_schedule_irq() if the
current task was within a preemptible hypercall.

Since preempt_schedule_irq() can move the task to a different CPU,
clear and set xen_in_preemptible_hcall around the call.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
Changes in v3:
- Export xen_in_preemptible_hcall (to fix modular privcmd driver).

Changes in v2:
- Use per-cpu variable to mark preemptible regions
- Call preempt_schedule_irq() from the correct place in
  xen_hypervisor_callback
---
 arch/x86/kernel/entry_32.S |   23 +++++++++++++++++++++++
 arch/x86/kernel/entry_64.S |   19 +++++++++++++++++++
 drivers/xen/Makefile       |    2 +-
 drivers/xen/preempt.c      |   17 +++++++++++++++++
 drivers/xen/privcmd.c      |    2 ++
 include/xen/xen-ops.h      |   27 +++++++++++++++++++++++++++
 6 files changed, 89 insertions(+), 1 deletions(-)
 create mode 100644 drivers/xen/preempt.c

diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index a2a4f46..b99bc9c 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -998,7 +998,30 @@ ENTRY(xen_hypervisor_callback)
 ENTRY(xen_do_upcall)
 1:	mov %esp, %eax
 	call xen_evtchn_do_upcall
+#ifdef CONFIG_PREEMPT
 	jmp  ret_from_intr
+#else
+	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_VM86
+	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+	movb PT_CS(%esp), %al
+	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+	movl PT_CS(%esp), %eax
+	andl $SEGMENT_RPL_MASK, %eax
+#endif
+	cmpl $USER_RPL, %eax
+	jae resume_userspace		# returning to v8086 or userspace
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+	jnz resume_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz resume_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp resume_kernel
+#endif /* CONFIG_PREEMPT */
 	CFI_ENDPROC
 ENDPROC(xen_hypervisor_callback)
 
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1e96c36..d8f4fd8 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1404,7 +1404,25 @@ ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
 	popq %rsp
 	CFI_DEF_CFA_REGISTER rsp
 	decl PER_CPU_VAR(irq_count)
+#ifdef CONFIG_PREEMPT
 	jmp  error_exit
+#else
+	movl %ebx, %eax
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	testl %eax, %eax
+	je error_exit_user
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz retint_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz retint_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp retint_kernel
+#endif
 	CFI_ENDPROC
 END(xen_do_hypervisor_callback)
 
@@ -1629,6 +1647,7 @@ ENTRY(error_exit)
 	GET_THREAD_INFO(%rcx)
 	testl %eax,%eax
 	jne retint_kernel
+error_exit_user:
 	LOCKDEP_SYS_EXIT_IRQ
 	movl TI_flags(%rcx),%edx
 	movl $_TIF_WORK_MASK,%edi
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 45e00af..6b867e9 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),)
 obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 endif
 obj-$(CONFIG_X86)			+= fallback.o
-obj-y	+= grant-table.o features.o balloon.o manage.o
+obj-y	+= grant-table.o features.o balloon.o manage.o preempt.o
 obj-y	+= events/
 obj-y	+= xenbus/
 
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
new file mode 100644
index 0000000..b5a3e98
--- /dev/null
+++ b/drivers/xen/preempt.c
@@ -0,0 +1,17 @@
+/*
+ * Preemptible hypercalls
+ *
+ * Copyright (C) 2014 Citrix Systems R&D ltd.
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <xen/xen-ops.h>
+
+#ifndef CONFIG_PREEMPT
+DEFINE_PER_CPU(bool, xen_in_preemptible_hcall);
+EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall);
+#endif
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 569a13b..59ac71c 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata)
 	if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
 		return -EFAULT;
 
+	xen_preemptible_hcall_begin();
 	ret = privcmd_call(hypercall.op,
 			   hypercall.arg[0], hypercall.arg[1],
 			   hypercall.arg[2], hypercall.arg[3],
 			   hypercall.arg[4]);
+	xen_preemptible_hcall_end();
 
 	return ret;
 }
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index fb2ea8f..6d8c042 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -35,4 +35,31 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 			       int numpgs, struct page **pages);
 
 bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
+
+#ifdef CONFIG_PREEMPT
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+}
+
+#else
+
+DECLARE_PER_CPU(bool, xen_in_preemptible_hcall);
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, true);
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, false);
+}
+
+#endif /* CONFIG_PREEMPT */
+
 #endif /* INCLUDE_XEN_OPS_H */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCHv3] x86/xen: allow privcmd hypercalls to be preempted
  2014-02-27 15:07 [PATCHv3] x86/xen: allow privcmd hypercalls to be preempted David Vrabel
@ 2014-02-28  2:38 ` Konrad Rzeszutek Wilk
  2014-02-28 10:45   ` David Vrabel
  0 siblings, 1 reply; 3+ messages in thread
From: Konrad Rzeszutek Wilk @ 2014-02-28  2:38 UTC (permalink / raw)
  To: David Vrabel; +Cc: Boris Ostrovsky, xen-devel

On Thu, Feb 27, 2014 at 03:07:55PM +0000, David Vrabel wrote:
> From: David Vrabel <david.vrabel@citrix.com>
> 
> Hypercalls submitted by user space tools via the privcmd driver can
> take a long time (potentially many 10s of seconds) if the hypercall
> has many sub-operations.
> 
> A fully preemptible kernel may deschedule such as task in any upcall
> called from a hypercall continuation.
> 
> However, in a kernel with voluntary or no preemption, hypercall
> continuations in Xen allow event handlers to be run but the task
> issuing the hypercall will not be descheduled until the hypercall is
> complete and the ioctl returns to user space.  These long running
> tasks may also trigger the kernel's soft lockup detection.
> 
> Add xen_preemptible_hcall_begin() and xen_preemptible_hcall_end() to
> bracket hypercalls that may be preempted.  Use these in the privcmd
> driver.
> 
> When returning from an upcall, call preempt_schedule_irq() if the
> current task was within a preemptible hypercall.
> 
> Since preempt_schedule_irq() can move the task to a different CPU,
> clear and set xen_in_preemptible_hcall around the call.
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> ---
> Changes in v3:
> - Export xen_in_preemptible_hcall (to fix modular privcmd driver).

On 32-bit builds I get:

arch/x86/built-in.o: In function `xen_do_upcall':
/home/konrad/ssd/konrad/linux/arch/x86/kernel/entry_32.S:1016: undefined
reference to `TI_preempt_count'

> 
> Changes in v2:
> - Use per-cpu variable to mark preemptible regions
> - Call preempt_schedule_irq() from the correct place in
>   xen_hypervisor_callback
> ---
>  arch/x86/kernel/entry_32.S |   23 +++++++++++++++++++++++
>  arch/x86/kernel/entry_64.S |   19 +++++++++++++++++++
>  drivers/xen/Makefile       |    2 +-
>  drivers/xen/preempt.c      |   17 +++++++++++++++++
>  drivers/xen/privcmd.c      |    2 ++
>  include/xen/xen-ops.h      |   27 +++++++++++++++++++++++++++
>  6 files changed, 89 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/xen/preempt.c
> 
> diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
> index a2a4f46..b99bc9c 100644
> --- a/arch/x86/kernel/entry_32.S
> +++ b/arch/x86/kernel/entry_32.S
> @@ -998,7 +998,30 @@ ENTRY(xen_hypervisor_callback)
>  ENTRY(xen_do_upcall)
>  1:	mov %esp, %eax
>  	call xen_evtchn_do_upcall
> +#ifdef CONFIG_PREEMPT
>  	jmp  ret_from_intr
> +#else
> +	GET_THREAD_INFO(%ebp)
> +#ifdef CONFIG_VM86
> +	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
> +	movb PT_CS(%esp), %al
> +	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
> +#else
> +	movl PT_CS(%esp), %eax
> +	andl $SEGMENT_RPL_MASK, %eax
> +#endif
> +	cmpl $USER_RPL, %eax
> +	jae resume_userspace		# returning to v8086 or userspace
> +	DISABLE_INTERRUPTS(CLBR_ANY)
> +	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
> +	jnz resume_kernel
> +	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	jz resume_kernel
> +	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	call preempt_schedule_irq
> +	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	jmp resume_kernel
> +#endif /* CONFIG_PREEMPT */
>  	CFI_ENDPROC
>  ENDPROC(xen_hypervisor_callback)
>  
> diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
> index 1e96c36..d8f4fd8 100644
> --- a/arch/x86/kernel/entry_64.S
> +++ b/arch/x86/kernel/entry_64.S
> @@ -1404,7 +1404,25 @@ ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
>  	popq %rsp
>  	CFI_DEF_CFA_REGISTER rsp
>  	decl PER_CPU_VAR(irq_count)
> +#ifdef CONFIG_PREEMPT
>  	jmp  error_exit
> +#else
> +	movl %ebx, %eax
> +	RESTORE_REST
> +	DISABLE_INTERRUPTS(CLBR_NONE)
> +	TRACE_IRQS_OFF
> +	GET_THREAD_INFO(%rcx)
> +	testl %eax, %eax
> +	je error_exit_user
> +	cmpl $0,PER_CPU_VAR(__preempt_count)
> +	jnz retint_kernel
> +	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	jz retint_kernel
> +	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	call preempt_schedule_irq
> +	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
> +	jmp retint_kernel
> +#endif
>  	CFI_ENDPROC
>  END(xen_do_hypervisor_callback)
>  
> @@ -1629,6 +1647,7 @@ ENTRY(error_exit)
>  	GET_THREAD_INFO(%rcx)
>  	testl %eax,%eax
>  	jne retint_kernel
> +error_exit_user:
>  	LOCKDEP_SYS_EXIT_IRQ
>  	movl TI_flags(%rcx),%edx
>  	movl $_TIF_WORK_MASK,%edi
> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
> index 45e00af..6b867e9 100644
> --- a/drivers/xen/Makefile
> +++ b/drivers/xen/Makefile
> @@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),)
>  obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
>  endif
>  obj-$(CONFIG_X86)			+= fallback.o
> -obj-y	+= grant-table.o features.o balloon.o manage.o
> +obj-y	+= grant-table.o features.o balloon.o manage.o preempt.o
>  obj-y	+= events/
>  obj-y	+= xenbus/
>  
> diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
> new file mode 100644
> index 0000000..b5a3e98
> --- /dev/null
> +++ b/drivers/xen/preempt.c
> @@ -0,0 +1,17 @@
> +/*
> + * Preemptible hypercalls
> + *
> + * Copyright (C) 2014 Citrix Systems R&D ltd.
> + *
> + * This source code is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + */
> +
> +#include <xen/xen-ops.h>
> +
> +#ifndef CONFIG_PREEMPT
> +DEFINE_PER_CPU(bool, xen_in_preemptible_hcall);
> +EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall);
> +#endif
> diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
> index 569a13b..59ac71c 100644
> --- a/drivers/xen/privcmd.c
> +++ b/drivers/xen/privcmd.c
> @@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata)
>  	if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
>  		return -EFAULT;
>  
> +	xen_preemptible_hcall_begin();
>  	ret = privcmd_call(hypercall.op,
>  			   hypercall.arg[0], hypercall.arg[1],
>  			   hypercall.arg[2], hypercall.arg[3],
>  			   hypercall.arg[4]);
> +	xen_preemptible_hcall_end();
>  
>  	return ret;
>  }
> diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
> index fb2ea8f..6d8c042 100644
> --- a/include/xen/xen-ops.h
> +++ b/include/xen/xen-ops.h
> @@ -35,4 +35,31 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
>  			       int numpgs, struct page **pages);
>  
>  bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
> +
> +#ifdef CONFIG_PREEMPT
> +
> +static inline void xen_preemptible_hcall_begin(void)
> +{
> +}
> +
> +static inline void xen_preemptible_hcall_end(void)
> +{
> +}
> +
> +#else
> +
> +DECLARE_PER_CPU(bool, xen_in_preemptible_hcall);
> +
> +static inline void xen_preemptible_hcall_begin(void)
> +{
> +	__this_cpu_write(xen_in_preemptible_hcall, true);
> +}
> +
> +static inline void xen_preemptible_hcall_end(void)
> +{
> +	__this_cpu_write(xen_in_preemptible_hcall, false);
> +}
> +
> +#endif /* CONFIG_PREEMPT */
> +
>  #endif /* INCLUDE_XEN_OPS_H */
> -- 
> 1.7.2.5
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCHv3] x86/xen: allow privcmd hypercalls to be preempted
  2014-02-28  2:38 ` Konrad Rzeszutek Wilk
@ 2014-02-28 10:45   ` David Vrabel
  0 siblings, 0 replies; 3+ messages in thread
From: David Vrabel @ 2014-02-28 10:45 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: Boris Ostrovsky, xen-devel

On 28/02/14 02:38, Konrad Rzeszutek Wilk wrote:
> On 32-bit builds I get:
> 
> arch/x86/built-in.o: In function `xen_do_upcall':
> /home/konrad/ssd/konrad/linux/arch/x86/kernel/entry_32.S:1016: undefined
> reference to `TI_preempt_count'

Sorry, I forward ported the 32-bit code from 3.10 kernel I was
using for testing in XenServer.

8<-----------------------------------------------------------
x86/xen: allow privcmd hypercalls to be preempted

From: David Vrabel <david.vrabel@citrix.com>

Hypercalls submitted by user space tools via the privcmd driver can
take a long time (potentially many 10s of seconds) if the hypercall
has many sub-operations.

A fully preemptible kernel may deschedule such as task in any upcall
called from a hypercall continuation.

However, in a kernel with voluntary or no preemption, hypercall
continuations in Xen allow event handlers to be run but the task
issuing the hypercall will not be descheduled until the hypercall is
complete and the ioctl returns to user space.  These long running
tasks may also trigger the kernel's soft lockup detection.

Add xen_preemptible_hcall_begin() and xen_preemptible_hcall_end() to
bracket hypercalls that may be preempted.  Use these in the privcmd
driver.

When returning from an upcall, call preempt_schedule_irq() if the
current task was within a preemptible hypercall.

Since preempt_schedule_irq() can move the task to a different CPU,
clear and set xen_in_preemptible_hcall around the call.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
Changes in v4:
- Fix 32-bit build.

Changes in v3:
- Export xen_in_preemptible_hcall (to fix modular privcmd driver).

Changes in v2:
- Use per-cpu variable to mark preemptible regions
- Call preempt_schedule_irq() from the correct place in
  xen_hypervisor_callback
---
 arch/x86/kernel/entry_32.S |   23 +++++++++++++++++++++++
 arch/x86/kernel/entry_64.S |   19 +++++++++++++++++++
 drivers/xen/Makefile       |    2 +-
 drivers/xen/preempt.c      |   17 +++++++++++++++++
 drivers/xen/privcmd.c      |    2 ++
 include/xen/xen-ops.h      |   27 +++++++++++++++++++++++++++
 6 files changed, 89 insertions(+), 1 deletions(-)
 create mode 100644 drivers/xen/preempt.c

diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index a2a4f46..024578d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -998,7 +998,30 @@ ENTRY(xen_hypervisor_callback)
 ENTRY(xen_do_upcall)
 1:	mov %esp, %eax
 	call xen_evtchn_do_upcall
+#ifdef CONFIG_PREEMPT
 	jmp  ret_from_intr
+#else
+	GET_THREAD_INFO(%ebp)
+#ifdef CONFIG_VM86
+	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+	movb PT_CS(%esp), %al
+	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+	movl PT_CS(%esp), %eax
+	andl $SEGMENT_RPL_MASK, %eax
+#endif
+	cmpl $USER_RPL, %eax
+	jae resume_userspace		# returning to v8086 or userspace
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz resume_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz resume_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp resume_kernel
+#endif /* CONFIG_PREEMPT */
 	CFI_ENDPROC
 ENDPROC(xen_hypervisor_callback)
 
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1e96c36..d8f4fd8 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1404,7 +1404,25 @@ ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
 	popq %rsp
 	CFI_DEF_CFA_REGISTER rsp
 	decl PER_CPU_VAR(irq_count)
+#ifdef CONFIG_PREEMPT
 	jmp  error_exit
+#else
+	movl %ebx, %eax
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	testl %eax, %eax
+	je error_exit_user
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz retint_kernel
+	cmpb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jz retint_kernel
+	movb $0,PER_CPU_VAR(xen_in_preemptible_hcall)
+	call preempt_schedule_irq
+	movb $1,PER_CPU_VAR(xen_in_preemptible_hcall)
+	jmp retint_kernel
+#endif
 	CFI_ENDPROC
 END(xen_do_hypervisor_callback)
 
@@ -1629,6 +1647,7 @@ ENTRY(error_exit)
 	GET_THREAD_INFO(%rcx)
 	testl %eax,%eax
 	jne retint_kernel
+error_exit_user:
 	LOCKDEP_SYS_EXIT_IRQ
 	movl TI_flags(%rcx),%edx
 	movl $_TIF_WORK_MASK,%edi
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 45e00af..6b867e9 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -2,7 +2,7 @@ ifeq ($(filter y, $(CONFIG_ARM) $(CONFIG_ARM64)),)
 obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o
 endif
 obj-$(CONFIG_X86)			+= fallback.o
-obj-y	+= grant-table.o features.o balloon.o manage.o
+obj-y	+= grant-table.o features.o balloon.o manage.o preempt.o
 obj-y	+= events/
 obj-y	+= xenbus/
 
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
new file mode 100644
index 0000000..b5a3e98
--- /dev/null
+++ b/drivers/xen/preempt.c
@@ -0,0 +1,17 @@
+/*
+ * Preemptible hypercalls
+ *
+ * Copyright (C) 2014 Citrix Systems R&D ltd.
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <xen/xen-ops.h>
+
+#ifndef CONFIG_PREEMPT
+DEFINE_PER_CPU(bool, xen_in_preemptible_hcall);
+EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall);
+#endif
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 569a13b..59ac71c 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -56,10 +56,12 @@ static long privcmd_ioctl_hypercall(void __user *udata)
 	if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
 		return -EFAULT;
 
+	xen_preemptible_hcall_begin();
 	ret = privcmd_call(hypercall.op,
 			   hypercall.arg[0], hypercall.arg[1],
 			   hypercall.arg[2], hypercall.arg[3],
 			   hypercall.arg[4]);
+	xen_preemptible_hcall_end();
 
 	return ret;
 }
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index fb2ea8f..6d8c042 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -35,4 +35,31 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 			       int numpgs, struct page **pages);
 
 bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
+
+#ifdef CONFIG_PREEMPT
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+}
+
+#else
+
+DECLARE_PER_CPU(bool, xen_in_preemptible_hcall);
+
+static inline void xen_preemptible_hcall_begin(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, true);
+}
+
+static inline void xen_preemptible_hcall_end(void)
+{
+	__this_cpu_write(xen_in_preemptible_hcall, false);
+}
+
+#endif /* CONFIG_PREEMPT */
+
 #endif /* INCLUDE_XEN_OPS_H */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-02-28 10:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-27 15:07 [PATCHv3] x86/xen: allow privcmd hypercalls to be preempted David Vrabel
2014-02-28  2:38 ` Konrad Rzeszutek Wilk
2014-02-28 10:45   ` David Vrabel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.