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:
Родитель
501a78cbc1
Коммит
709b973c84
|
@ -1613,6 +1613,22 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
|||
value = mfspr(SPRN_FSCR);
|
||||
|
||||
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) {
|
||||
/*
|
||||
* User is accessing the DSCR register using the problem
|
||||
|
@ -1679,25 +1695,11 @@ void facility_unavailable_exception(struct pt_regs *regs)
|
|||
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",
|
||||
hv ? "Hypervisor " : "", facility, status, regs->nip, regs->msr);
|
||||
|
||||
out:
|
||||
if (user_mode(regs)) {
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
return;
|
||||
}
|
||||
|
||||
die("Unexpected facility unavailable exception", regs, SIGABRT);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче