powerpc/fscr: Enable interrupts earlier before calling get_user()
The function get_user() can sleep while trying to fetch instruction from user address space and causes the following warning from the scheduler. BUG: sleeping function called from invalid context Though interrupts get enabled back but it happens bit later after get_user() is called. This change moves enabling these interrupts earlier covering the function get_user(). While at this, lets check for kernel mode and crash as this interrupt should not have been triggered from the kernel context. Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
501a78cbc1
commit
709b973c84
1 changed files with 17 additions and 15 deletions
|
@ -1613,6 +1613,22 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
||||||
value = mfspr(SPRN_FSCR);
|
value = mfspr(SPRN_FSCR);
|
||||||
|
|
||||||
status = value >> 56;
|
status = value >> 56;
|
||||||
|
if ((hv || status >= 2) &&
|
||||||
|
(status < ARRAY_SIZE(facility_strings)) &&
|
||||||
|
facility_strings[status])
|
||||||
|
facility = facility_strings[status];
|
||||||
|
|
||||||
|
/* We should not have taken this interrupt in kernel */
|
||||||
|
if (!user_mode(regs)) {
|
||||||
|
pr_emerg("Facility '%s' unavailable (%d) exception in kernel mode at %lx\n",
|
||||||
|
facility, status, regs->nip);
|
||||||
|
die("Unexpected facility unavailable exception", regs, SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We restore the interrupt state now */
|
||||||
|
if (!arch_irq_disabled_regs(regs))
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
if (status == FSCR_DSCR_LG) {
|
if (status == FSCR_DSCR_LG) {
|
||||||
/*
|
/*
|
||||||
* User is accessing the DSCR register using the problem
|
* User is accessing the DSCR register using the problem
|
||||||
|
@ -1679,25 +1695,11 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hv || status >= 2) &&
|
|
||||||
(status < ARRAY_SIZE(facility_strings)) &&
|
|
||||||
facility_strings[status])
|
|
||||||
facility = facility_strings[status];
|
|
||||||
|
|
||||||
/* We restore the interrupt state now */
|
|
||||||
if (!arch_irq_disabled_regs(regs))
|
|
||||||
local_irq_enable();
|
|
||||||
|
|
||||||
pr_err_ratelimited("%sFacility '%s' unavailable (%d), exception at 0x%lx, MSR=%lx\n",
|
pr_err_ratelimited("%sFacility '%s' unavailable (%d), exception at 0x%lx, MSR=%lx\n",
|
||||||
hv ? "Hypervisor " : "", facility, status, regs->nip, regs->msr);
|
hv ? "Hypervisor " : "", facility, status, regs->nip, regs->msr);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (user_mode(regs)) {
|
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
die("Unexpected facility unavailable exception", regs, SIGABRT);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue