Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1271230 > unrolled thread
| Started by | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| First post | 2015-11-17 15:10 +0100 |
| Last post | 2015-11-17 21:00 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: irq_fpu_usable() is irreliable Thomas Gleixner <tglx@linutronix.de> - 2015-11-17 15:10 +0100
Re: irq_fpu_usable() is irreliable "Jason A. Donenfeld" <Jason@zx2c4.com> - 2015-11-17 16:00 +0100
Re: irq_fpu_usable() is irreliable "Jason A. Donenfeld" <Jason@zx2c4.com> - 2015-11-17 21:00 +0100
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2015-11-17 15:10 +0100 |
| Subject | Re: irq_fpu_usable() is irreliable |
| Message-ID | <qvP7j-64d-1@gated-at.bofh.it> |
Jason,
On Tue, 17 Nov 2015, Jason A. Donenfeld wrote:
> The availability of the FPU in kernel space, as you know, is determined by
> this function:
>
> bool irq_fpu_usable(void)
> {
> return !in_interrupt() ||
> interrupted_user_mode() ||
> interrupted_kernel_fpu_idle();
> }
>
> My understanding is that the first check is !in_interrupt(), because if
> `current` is valid - if we are in process context - then we have a place to
> store the existing FPU regs in kernel_fpu_begin, to be restored later in
> kernel_fpu_end. Recently I've been tracking down a problem in
> which irq_fpu_usable() returns false, yet a stack trace shows the first
> function is the syscall entry point. This leads me to believe that
> in_interrupt() is not an adequate way of testing for a valid `current`.
This function has absolute nothing to do with current. current is
always valid. The function checks whether we can use the fpu safely in
kernel context.
> In my particular problematic case, the reason in_interrupt() was
> returning false is because a number of rcu_read_lock_bh()s were
> being held; IOW this is occurring in the ndo_start_xmit path of a
> network driver.
>
> I therefore propose changing the function to this:
>
> bool irq_fpu_usable(void)
> {
> return (!in_irq() && !in_nmi()) ||
> interrupted_user_mode() ||
> interrupted_kernel_fpu_idle();
> }
>
> What would you think of that?
That's broken. Assume we interrupted a kernel thread which fiddles
with the FPU and then on irq exit we run a softirq which tries to use
the FPU....
The real question in your case is WHY interrupted_kernel_fpu_idle()
returns false. We know for sure that in a syscall with BH disabled the
first two checks are false.
Thanks,
tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | "Jason A. Donenfeld" <Jason@zx2c4.com> |
|---|---|
| Date | 2015-11-17 16:00 +0100 |
| Message-ID | <qvPTH-6ll-3@gated-at.bofh.it> |
| In reply to | #1271230 |
Hi Thomas,
On Tue, Nov 17, 2015 at 3:06 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> The real question in your case is WHY interrupted_kernel_fpu_idle()
> returns false. We know for sure that in a syscall with BH disabled the
> first two checks are false.
Blurg, indeed. I've been trying to track that down in a different
thread with the netdev folks. After not getting anywhere, I sort of
felt, "dammit! can't this not be the issue, and can't I just get rid
of that in_interrupt() condition?" But, as you've explained above, no,
we can't get rid of that. So yes: the question is why
interrupted_kernel_fpu_idle() is false. Mysteriously it happens to be
the case in UDP mode but not TCP mode (the topic of the other thread),
and so I should resume trying to determine why this is so. I don't
entirely understand the function though:
static bool interrupted_kernel_fpu_idle(void)
{
if (kernel_fpu_disabled())
return false;
if (use_eager_fpu())
return true;
return !current->thread.fpu.fpregs_active && (read_cr0() & X86_CR0_TS);
}
From my tests, when irq_fpu_usable() is false, the expression
`!current->thread.fpu.fpregs_active && (read_cr0() & X86_CR0_TS);` is
false, for both of it. What, then, is leading to the call of
fpregs_activate()? I can't find anything along the syscall path that
would result in this. I admit I do not have a deep understanding of
how the FPU is implemented in Linux. Is it possible that this means
that userspace is using the FPU? Is this what user_fpu_begin() is all
about?
(If so, why is that state not stored on syscall entry? If the reason
is "because it would be expensive to do it everytime", then is there a
way to selectively do that only when it's necessary?)
Or, must this imply that the kernel is actually using it elsewhere,
and I need to just keep digging diligently?
Thanks,
Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Jason A. Donenfeld" <Jason@zx2c4.com> |
|---|---|
| Date | 2015-11-17 21:00 +0100 |
| Message-ID | <qvUA1-Xn-13@gated-at.bofh.it> |
| In reply to | #1271291 |
Trying to get to the bottom of this still... Is interrupted_kernel_fpu_idle() in any way dependent on what userspace is doing? Or is it entirely related to other happenings inside the kernel? -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web