Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'powerpc-5.8-8' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fix from Michael Ellerman:
"Fix a bug introduced by the changes we made to lockless page table
walking this cycle.

When using the hash MMU, and perf with callchain recording, we can
deadlock if the PMI interrupts a hash fault, and the callchain
recording then takes a hash fault on the same page.

Thanks to Nicholas Piggin, Aneesh Kumar K.V, Anton Blanchard, and
Athira Rajeev"

* tag 'powerpc-5.8-8' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc/64s/hash: Fix hash_preload running with interrupts enabled

+42 -3
+11 -3
arch/powerpc/kernel/exceptions-64s.S
··· 3072 3072 ori r0,r0,DSISR_BAD_FAULT_64S@l 3073 3073 and. r0,r5,r0 /* weird error? */ 3074 3074 bne- handle_page_fault /* if not, try to insert a HPTE */ 3075 + 3076 + /* 3077 + * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then 3078 + * don't call hash_page, just fail the fault. This is required to 3079 + * prevent re-entrancy problems in the hash code, namely perf 3080 + * interrupts hitting while something holds H_PAGE_BUSY, and taking a 3081 + * hash fault. See the comment in hash_preload(). 3082 + */ 3075 3083 ld r11, PACA_THREAD_INFO(r13) 3076 - lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ 3077 - andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ 3078 - bne 77f /* then don't call hash_page now */ 3084 + lwz r0,TI_PREEMPT(r11) 3085 + andis. r0,r0,NMI_MASK@h 3086 + bne 77f 3079 3087 3080 3088 /* 3081 3089 * r3 contains the trap number
+25
arch/powerpc/mm/book3s64/hash_utils.c
··· 1559 1559 pgd_t *pgdir; 1560 1560 int rc, ssize, update_flags = 0; 1561 1561 unsigned long access = _PAGE_PRESENT | _PAGE_READ | (is_exec ? _PAGE_EXEC : 0); 1562 + unsigned long flags; 1562 1563 1563 1564 BUG_ON(get_region_id(ea) != USER_REGION_ID); 1564 1565 ··· 1593 1592 return; 1594 1593 #endif /* CONFIG_PPC_64K_PAGES */ 1595 1594 1595 + /* 1596 + * __hash_page_* must run with interrupts off, as it sets the 1597 + * H_PAGE_BUSY bit. It's possible for perf interrupts to hit at any 1598 + * time and may take a hash fault reading the user stack, see 1599 + * read_user_stack_slow() in the powerpc/perf code. 1600 + * 1601 + * If that takes a hash fault on the same page as we lock here, it 1602 + * will bail out when seeing H_PAGE_BUSY set, and retry the access 1603 + * leading to an infinite loop. 1604 + * 1605 + * Disabling interrupts here does not prevent perf interrupts, but it 1606 + * will prevent them taking hash faults (see the NMI test in 1607 + * do_hash_page), then read_user_stack's copy_from_user_nofault will 1608 + * fail and perf will fall back to read_user_stack_slow(), which 1609 + * walks the Linux page tables. 1610 + * 1611 + * Interrupts must also be off for the duration of the 1612 + * mm_is_thread_local test and update, to prevent preempt running the 1613 + * mm on another CPU (XXX: this may be racy vs kthread_use_mm). 1614 + */ 1615 + local_irq_save(flags); 1616 + 1596 1617 /* Is that local to this CPU ? */ 1597 1618 if (mm_is_thread_local(mm)) 1598 1619 update_flags |= HPTE_LOCAL_UPDATE; ··· 1637 1614 mm_ctx_user_psize(&mm->context), 1638 1615 mm_ctx_user_psize(&mm->context), 1639 1616 pte_val(*ptep)); 1617 + 1618 + local_irq_restore(flags); 1640 1619 } 1641 1620 1642 1621 /*
+6
arch/powerpc/perf/core-book3s.c
··· 2179 2179 2180 2180 perf_read_regs(regs); 2181 2181 2182 + /* 2183 + * If perf interrupts hit in a local_irq_disable (soft-masked) region, 2184 + * we consider them as NMIs. This is required to prevent hash faults on 2185 + * user addresses when reading callchains. See the NMI test in 2186 + * do_hash_page. 2187 + */ 2182 2188 nmi = perf_intr_is_nmi(regs); 2183 2189 if (nmi) 2184 2190 nmi_enter();