arch/tile: don't wait for migrating PTEs in an NMI handler
Doing so raises the possibility of self-deadlock if we are waiting for a backtrace for an oprofile or perf interrupt while we are in the middle of migrating our own stack page. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
This commit is contained in:
parent
6731aa9eae
commit
48292738d0
|
@ -203,9 +203,14 @@ static pgd_t *get_current_pgd(void)
|
||||||
* interrupt or a critical region, and must do as little as possible.
|
* interrupt or a critical region, and must do as little as possible.
|
||||||
* Similarly, we can't use atomic ops here, since we may be handling a
|
* Similarly, we can't use atomic ops here, since we may be handling a
|
||||||
* fault caused by an atomic op access.
|
* fault caused by an atomic op access.
|
||||||
|
*
|
||||||
|
* If we find a migrating PTE while we're in an NMI context, and we're
|
||||||
|
* at a PC that has a registered exception handler, we don't wait,
|
||||||
|
* since this thread may (e.g.) have been interrupted while migrating
|
||||||
|
* its own stack, which would then cause us to self-deadlock.
|
||||||
*/
|
*/
|
||||||
static int handle_migrating_pte(pgd_t *pgd, int fault_num,
|
static int handle_migrating_pte(pgd_t *pgd, int fault_num,
|
||||||
unsigned long address,
|
unsigned long address, unsigned long pc,
|
||||||
int is_kernel_mode, int write)
|
int is_kernel_mode, int write)
|
||||||
{
|
{
|
||||||
pud_t *pud;
|
pud_t *pud;
|
||||||
|
@ -227,6 +232,8 @@ static int handle_migrating_pte(pgd_t *pgd, int fault_num,
|
||||||
pte_offset_kernel(pmd, address);
|
pte_offset_kernel(pmd, address);
|
||||||
pteval = *pte;
|
pteval = *pte;
|
||||||
if (pte_migrating(pteval)) {
|
if (pte_migrating(pteval)) {
|
||||||
|
if (in_nmi() && search_exception_tables(pc))
|
||||||
|
return 0;
|
||||||
wait_for_migration(pte);
|
wait_for_migration(pte);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -300,7 +307,7 @@ static int handle_page_fault(struct pt_regs *regs,
|
||||||
* rather than trying to patch up the existing PTE.
|
* rather than trying to patch up the existing PTE.
|
||||||
*/
|
*/
|
||||||
pgd = get_current_pgd();
|
pgd = get_current_pgd();
|
||||||
if (handle_migrating_pte(pgd, fault_num, address,
|
if (handle_migrating_pte(pgd, fault_num, address, regs->pc,
|
||||||
is_kernel_mode, write))
|
is_kernel_mode, write))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -665,7 +672,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
|
||||||
*/
|
*/
|
||||||
if (fault_num == INT_DTLB_ACCESS)
|
if (fault_num == INT_DTLB_ACCESS)
|
||||||
write = 1;
|
write = 1;
|
||||||
if (handle_migrating_pte(pgd, fault_num, address, 1, write))
|
if (handle_migrating_pte(pgd, fault_num, address, pc, 1, write))
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
/* Return zero so that we continue on with normal fault handling. */
|
/* Return zero so that we continue on with normal fault handling. */
|
||||||
|
|
Loading…
Reference in New Issue