From: David Vrabel <david.vrabel@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
BorisOstrovsky <boris.ostrovsky@oracle.com>,
xen-devel@lists.xen.org,
Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Subject: Re: [PATCH 3/3] xen/events: schedule if the interrupted task is in a preemptible hypercall
Date: Wed, 12 Feb 2014 16:35:31 +0000 [thread overview]
Message-ID: <52FBA2D3.7020503@citrix.com> (raw)
In-Reply-To: <52FB8B8A020000780011BB7D@nat28.tlf.novell.com>
On 12/02/14 13:56, Jan Beulich wrote:
>>>> On 12.02.14 at 13:54, David Vrabel <david.vrabel@citrix.com> wrote:
>> On 12/02/14 11:59, Jan Beulich wrote:
>>>>>> On 11.02.14 at 20:19, David Vrabel <david.vrabel@citrix.com> wrote:
>>>> --- a/drivers/xen/events/events_base.c
>>>> +++ b/drivers/xen/events/events_base.c
>>>> @@ -1254,6 +1254,12 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
>>>>
>>>> irq_exit();
>>>> set_irq_regs(old_regs);
>>>> +
>>>> +#ifndef CONFIG_PREEMPT
>>>> + if ( __this_cpu_read(xed_nesting_count) == 0
>>>> + && is_preemptible_hypercall(regs) )
>>>> + _cond_resched();
>>>> +#endif
>>>
>>> I don't think this can be done here - a 64-bit x86 kernel would
>>> generally be on the IRQ stack, and I don't think scheduling
>>> should be done in this state.
>>
>> _cond_resched() doesn't look that different from preempt_schedule_irq()
>> which is explicitly callable from irq context.
>
> But IRQ context and running on the IRQ stack isn't the same. All
> current callers of that function are in assembly code, where one
> would hope people know what they're doing (and in particular
> _when_ they do so).
Ok.
I'm not sure I can claim I know what I'm doing, but I think this does
the right thing now.
8<--------------------------------------
>From 3094ed5851697b8bffe1227d32c1f1022e553191 Mon Sep 17 00:00:00 2001
From: David Vrabel <david.vrabel@citrix.com>
Date: Tue, 11 Feb 2014 15:41:03 +0000
Subject: [PATCH] xen: allow privcmd hypercalls to be preempted
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 a 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>
---
arch/x86/kernel/entry_64.S | 23 ++++++++++++++++++++++-
drivers/xen/Makefile | 2 +-
drivers/xen/events/events_base.c | 1 +
drivers/xen/preempt.c | 16 ++++++++++++++++
drivers/xen/privcmd.c | 2 ++
include/xen/xen-ops.h | 27 +++++++++++++++++++++++++++
6 files changed, 69 insertions(+), 2 deletions(-)
create mode 100644 drivers/xen/preempt.c
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1e96c36..e614aaa 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1404,7 +1404,7 @@ ENTRY(xen_do_hypervisor_callback) #
do_hypervisor_callback(struct *pt_regs)
popq %rsp
CFI_DEF_CFA_REGISTER rsp
decl PER_CPU_VAR(irq_count)
- jmp error_exit
+ jmp xen_error_exit
CFI_ENDPROC
END(xen_do_hypervisor_callback)
@@ -1470,6 +1470,26 @@ END(xen_failsafe_callback)
apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
xen_hvm_callback_vector xen_evtchn_do_upcall
+ENTRY(xen_error_exit)
+ DEFAULT_FRAME
+ movl %ebx,%eax
+ RESTORE_REST
+ DISABLE_INTERRUPTS(CLBR_NONE)
+ TRACE_IRQS_OFF
+ GET_THREAD_INFO(%rcx)
+ testl %eax,%eax
+ je error_exit_user
+#ifndef CONFIG_PREEMPT
+ testb $0, PER_CPU_VAR(xen_in_preemptible_hcall)
+ je retint_kernel
+ movb $0, PER_CPU_VAR(xen_in_preemptible_hcall)
+ call preempt_schedule_irq
+ movb $1, PER_CPU_VAR(xen_in_preemptible_hcall)
+#endif
+ jmp retint_kernel
+ CFI_ENDPROC
+END(xen_error_exit)
+
#endif /* CONFIG_XEN */
#if IS_ENABLED(CONFIG_HYPERV)
@@ -1629,6 +1649,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 d75c811..f8c7e04 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/events/events_base.c
b/drivers/xen/events/events_base.c
index 4672e00..db9584a 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/irqnr.h>
#include <linux/pci.h>
+#include <linux/sched.h>
#ifdef CONFIG_X86
#include <asm/desc.h>
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
new file mode 100644
index 0000000..3275ffe
--- /dev/null
+++ b/drivers/xen/preempt.c
@@ -0,0 +1,16 @@
+/*
+ * 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);
+#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
next prev parent reply other threads:[~2014-02-12 16:35 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-11 19:19 [PATCHv1 0/3]: xen: voluntary preemption for privcmd hypercalls David Vrabel
2014-02-11 19:19 ` [PATCH 1/3] x86/xen: allow for privcmd hypercalls to be preempted David Vrabel
2014-02-12 9:38 ` Ian Campbell
2014-02-12 10:10 ` Andrew Cooper
2014-02-12 10:18 ` Ian Campbell
2014-02-11 19:19 ` [PATCH 2/3] arm/xen: add stub is_preemptible_hypercall() David Vrabel
2014-02-11 19:19 ` [PATCH 3/3] xen/events: schedule if the interrupted task is in a preemptible hypercall David Vrabel
2014-02-12 11:59 ` Jan Beulich
2014-02-12 12:54 ` David Vrabel
2014-02-12 13:56 ` Jan Beulich
2014-02-12 16:35 ` David Vrabel [this message]
2014-02-12 16:47 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52FBA2D3.7020503@citrix.com \
--to=david.vrabel@citrix.com \
--cc=JBeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=boris.ostrovsky@oracle.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).