提交 48292738 编写于 作者: C Chris Metcalf

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: NChris Metcalf <cmetcalf@tilera.com>
上级 6731aa9e
...@@ -203,9 +203,14 @@ static pgd_t *get_current_pgd(void) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册