TIF_NOTITY_RESUME is evaluated on return to user space along with other TIF
flags.
>From the kernels point of view a VMENTER is more or less equivalent to
return to user space which means that at least a subset of TIF flags needs
to be evaluated and handled.
Currently KVM handles only TIF_SIGPENDING and TIF_NEED_RESCHED, but
TIF_NOTIFY_RESUME is ignored. So pending task_work etc, is completely
ignored until the vCPU thread actually goes all the way back into
userspace/qemu.
Provide notify_resume_pending() and tracehook_handle_notify_resume() so
this can be handled similar to SIGPENDING.
Signed-off-by: Thomas Gleixner <[email protected]>
Cc: Oleg Nesterov <[email protected]>
---
include/linux/tracehook.h | 15 +++++++++++++++
kernel/task_work.c | 19 +++++++++++++++++++
2 files changed, 34 insertions(+)
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -163,6 +163,21 @@ static inline void set_notify_resume(str
#endif
}
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+/**
+ * notify_resume_pending - Check whether current has TIF_NOTIFY_RESUME set
+ */
+static inline bool notify_resume_pending(void)
+{
+ return test_thread_flag(TIF_NOTIFY_RESUME);
+}
+
+void tracehook_handle_notify_resume(void);
+#else
+static inline bool notify_resume_pending(void) { return false; }
+static inline void tracehook_handle_notify_resume(void) { }
+#endif
+
/**
* tracehook_notify_resume - report when about to return to user mode
* @regs: user-mode registers of @current task
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -116,3 +116,22 @@ void task_work_run(void)
} while (work);
}
}
+
+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+/**
+ * tracehook_handle_notify_resume - Notify resume handling for virt
+ *
+ * Called with interrupts and preemption enabled from VMENTER/EXIT.
+ */
+void tracehook_handle_notify_resume(void)
+{
+ local_irq_disable();
+ while (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+ local_irq_enable();
+ tracehook_notify_resume(NULL);
+ local_irq_disable();
+ }
+ local_irq_enable();
+}
+EXPORT_SYMBOL_GPL(tracehook_handle_notify_resume);
+#endif
On Thu, Aug 01, 2019 at 04:32:51PM +0200, Thomas Gleixner wrote:
> +#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
> +/**
> + * tracehook_handle_notify_resume - Notify resume handling for virt
> + *
> + * Called with interrupts and preemption enabled from VMENTER/EXIT.
> + */
> +void tracehook_handle_notify_resume(void)
> +{
> + local_irq_disable();
> + while (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
> + local_irq_enable();
> + tracehook_notify_resume(NULL);
> + local_irq_disable();
> + }
> + local_irq_enable();
I'm confused by the IRQ state swizzling here, what is it doing?
> +}
> +EXPORT_SYMBOL_GPL(tracehook_handle_notify_resume);
> +#endif
>
>
On Thu, 1 Aug 2019, Peter Zijlstra wrote:
> On Thu, Aug 01, 2019 at 04:32:51PM +0200, Thomas Gleixner wrote:
> > +#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
> > +/**
> > + * tracehook_handle_notify_resume - Notify resume handling for virt
> > + *
> > + * Called with interrupts and preemption enabled from VMENTER/EXIT.
> > + */
> > +void tracehook_handle_notify_resume(void)
> > +{
> > + local_irq_disable();
> > + while (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
> > + local_irq_enable();
> > + tracehook_notify_resume(NULL);
> > + local_irq_disable();
> > + }
> > + local_irq_enable();
>
> I'm confused by the IRQ state swizzling here, what is it doing?
Hmm, right. It's not really needed. Modeled it after the user space return
code, but the KVM case is different because it evaluates the TIF bit again
before entering the VM with interrupts disabled anyway.
I'll remove the brainfart in V2.
Thanks,
tglx
> On Aug 1, 2019, at 7:48 AM, Peter Zijlstra <[email protected]> wrote:
>
>> On Thu, Aug 01, 2019 at 04:32:51PM +0200, Thomas Gleixner wrote:
>> +#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
>> +/**
>> + * tracehook_handle_notify_resume - Notify resume handling for virt
>> + *
>> + * Called with interrupts and preemption enabled from VMENTER/EXIT.
>> + */
>> +void tracehook_handle_notify_resume(void)
>> +{
>> + local_irq_disable();
>> + while (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
>> + local_irq_enable();
>> + tracehook_notify_resume(NULL);
>> + local_irq_disable();
>> + }
>> + local_irq_enable();
>
> I'm confused by the IRQ state swizzling here, what is it doing?
Me too. Also, why is a loop needed?
>
>> +}
>> +EXPORT_SYMBOL_GPL(tracehook_handle_notify_resume);
>> +#endif
>>
>>