Skip to content

Commit a2f7734

Browse files
Automatic merge of 'next' into merge (2026-03-29 10:35)
2 parents 4f37907 + 07791ff commit a2f7734

File tree

8 files changed

+79
-71
lines changed

8 files changed

+79
-71
lines changed

arch/powerpc/include/asm/book3s/64/pgtable.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@
107107
* in here, on radix we expect them to be zero.
108108
*/
109109
#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
110-
_PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_PTE | \
111-
_PAGE_SOFT_DIRTY)
110+
_PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_SPECIAL | \
111+
_PAGE_PTE | _PAGE_SOFT_DIRTY)
112112
/*
113113
* user access blocked by key
114114
*/
@@ -1313,12 +1313,27 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
13131313
{
13141314
pmd_t old_pmd;
13151315

1316+
/*
1317+
* Non-present PMDs can be migration entries or device-private THP
1318+
* entries. This can happen at 2 places:
1319+
* - When the address space is being unmapped zap_huge_pmd(), and we
1320+
* encounter non-present pmds.
1321+
* - migrate_vma_collect_huge_pmd() could calls this during migration
1322+
* of device-private pmd entries.
1323+
*/
1324+
if (!pmd_present(*pmdp)) {
1325+
old_pmd = READ_ONCE(*pmdp);
1326+
pmd_clear(pmdp);
1327+
goto out;
1328+
}
1329+
13161330
if (radix_enabled()) {
13171331
old_pmd = radix__pmdp_huge_get_and_clear(mm, addr, pmdp);
13181332
} else {
13191333
old_pmd = hash__pmdp_huge_get_and_clear(mm, addr, pmdp);
13201334
}
13211335

1336+
out:
13221337
page_table_check_pmd_clear(mm, addr, old_pmd);
13231338

13241339
return old_pmd;
@@ -1400,7 +1415,6 @@ static inline bool arch_needs_pgtable_deposit(void)
14001415
return false;
14011416
return true;
14021417
}
1403-
extern void serialize_against_pte_lookup(struct mm_struct *mm);
14041418

14051419
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
14061420

arch/powerpc/include/asm/book3s/64/tlbflush-radix.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmad
9292
#define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr)
9393
#define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p)
9494
#endif
95-
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
9695
extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
9796
extern void radix__flush_tlb_all(void);
9897

arch/powerpc/kernel/setup-common.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,10 @@ static __init void print_system_info(void)
865865
cur_cpu_spec->cpu_user_features,
866866
cur_cpu_spec->cpu_user_features2);
867867
pr_info("mmu_features = 0x%08x\n", cur_cpu_spec->mmu_features);
868+
pr_info(" possible = 0x%016lx\n",
869+
(unsigned long)MMU_FTRS_POSSIBLE);
870+
pr_info(" always = 0x%016lx\n",
871+
(unsigned long)MMU_FTRS_ALWAYS);
868872
#ifdef CONFIG_PPC64
869873
pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features);
870874
#ifdef CONFIG_PPC_BOOK3S

arch/powerpc/mm/book3s64/hash_pgtable.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,27 @@ unsigned long hash__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr
221221
return old;
222222
}
223223

224+
static void do_nothing(void *arg)
225+
{
226+
227+
}
228+
229+
/*
230+
* Serialize against __find_linux_pte() which does lock-less
231+
* lookup in page tables with local interrupts disabled. For huge pages
232+
* it casts pmd_t to pte_t. Since format of pte_t is different from
233+
* pmd_t we want to prevent transit from pmd pointing to page table
234+
* to pmd pointing to huge page (and back) while interrupts are disabled.
235+
* We clear pmd to possibly replace it with page table pointer in
236+
* different code paths. So make sure we wait for the parallel
237+
* __find_linux_pte() to finish.
238+
*/
239+
static void serialize_against_pte_lookup(struct mm_struct *mm)
240+
{
241+
smp_mb();
242+
smp_call_function_many(mm_cpumask(mm), do_nothing, mm, 1);
243+
}
244+
224245
pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
225246
pmd_t *pmdp)
226247
{

arch/powerpc/mm/book3s64/internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,4 @@ static inline bool slb_preload_disabled(void)
3131

3232
void hpt_do_stress(unsigned long ea, unsigned long hpte_group);
3333

34-
void exit_lazy_flush_tlb(struct mm_struct *mm, bool always_flush);
35-
3634
#endif /* ARCH_POWERPC_MM_BOOK3S64_INTERNAL_H */

arch/powerpc/mm/book3s64/pgtable.c

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
#include <mm/mmu_decl.h>
2424
#include <trace/events/thp.h>
2525

26-
#include "internal.h"
27-
2826
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
2927
EXPORT_SYMBOL_GPL(mmu_psize_defs);
3028

@@ -150,31 +148,6 @@ void set_pud_at(struct mm_struct *mm, unsigned long addr,
150148
return set_pte_at_unchecked(mm, addr, pudp_ptep(pudp), pud_pte(pud));
151149
}
152150

153-
static void do_serialize(void *arg)
154-
{
155-
/* We've taken the IPI, so try to trim the mask while here */
156-
if (radix_enabled()) {
157-
struct mm_struct *mm = arg;
158-
exit_lazy_flush_tlb(mm, false);
159-
}
160-
}
161-
162-
/*
163-
* Serialize against __find_linux_pte() which does lock-less
164-
* lookup in page tables with local interrupts disabled. For huge pages
165-
* it casts pmd_t to pte_t. Since format of pte_t is different from
166-
* pmd_t we want to prevent transit from pmd pointing to page table
167-
* to pmd pointing to huge page (and back) while interrupts are disabled.
168-
* We clear pmd to possibly replace it with page table pointer in
169-
* different code paths. So make sure we wait for the parallel
170-
* __find_linux_pte() to finish.
171-
*/
172-
void serialize_against_pte_lookup(struct mm_struct *mm)
173-
{
174-
smp_mb();
175-
smp_call_function_many(mm_cpumask(mm), do_serialize, mm, 1);
176-
}
177-
178151
/*
179152
* We use this to invalidate a pmdp entry before switching from a
180153
* hugepte to regular pmd entry.
@@ -209,16 +182,21 @@ pmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma,
209182
unsigned long addr, pmd_t *pmdp, int full)
210183
{
211184
pmd_t pmd;
185+
bool was_present = pmd_present(*pmdp);
186+
212187
VM_BUG_ON(addr & ~HPAGE_PMD_MASK);
213-
VM_BUG_ON((pmd_present(*pmdp) && !pmd_trans_huge(*pmdp)) ||
214-
!pmd_present(*pmdp));
188+
VM_BUG_ON(was_present && !pmd_trans_huge(*pmdp));
189+
/*
190+
* Check pmdp_huge_get_and_clear() for non-present pmd case.
191+
*/
215192
pmd = pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp);
216193
/*
217194
* if it not a fullmm flush, then we can possibly end up converting
218195
* this PMD pte entry to a regular level 0 PTE by a parallel page fault.
219-
* Make sure we flush the tlb in this case.
196+
* Make sure we flush the tlb in this case. TLB flush not needed for
197+
* non-present case.
220198
*/
221-
if (!full)
199+
if (was_present && !full)
222200
flush_pmd_tlb_range(vma, addr, addr + HPAGE_PMD_SIZE);
223201
return pmd;
224202
}

arch/powerpc/mm/book3s64/radix_tlb.c

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#include <asm/cputhreads.h>
2020
#include <asm/plpar_wrappers.h>
2121

22-
#include "internal.h"
23-
2422
/*
2523
* tlbiel instruction for radix, set invalidation
2624
* i.e., r=1 and is=01 or is=10 or is=11
@@ -187,7 +185,7 @@ static __always_inline void __tlbie_va(unsigned long va, unsigned long pid,
187185
trace_tlbie(0, 0, rb, rs, ric, prs, r);
188186
}
189187

190-
static __always_inline void __tlbie_lpid_va(unsigned long va, unsigned long lpid,
188+
static __always_inline void __tlbie_va_lpid(unsigned long va, unsigned long lpid,
191189
unsigned long ap, unsigned long ric)
192190
{
193191
unsigned long rb,rs,prs,r;
@@ -251,17 +249,17 @@ static inline void fixup_tlbie_pid(unsigned long pid)
251249
}
252250
}
253251

254-
static inline void fixup_tlbie_lpid_va(unsigned long va, unsigned long lpid,
252+
static inline void fixup_tlbie_va_lpid(unsigned long va, unsigned long lpid,
255253
unsigned long ap)
256254
{
257255
if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
258256
asm volatile("ptesync": : :"memory");
259-
__tlbie_lpid_va(va, 0, ap, RIC_FLUSH_TLB);
257+
__tlbie_va_lpid(va, 0, ap, RIC_FLUSH_TLB);
260258
}
261259

262260
if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
263261
asm volatile("ptesync": : :"memory");
264-
__tlbie_lpid_va(va, lpid, ap, RIC_FLUSH_TLB);
262+
__tlbie_va_lpid(va, lpid, ap, RIC_FLUSH_TLB);
265263
}
266264
}
267265

@@ -280,7 +278,7 @@ static inline void fixup_tlbie_lpid(unsigned long lpid)
280278

281279
if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
282280
asm volatile("ptesync": : :"memory");
283-
__tlbie_lpid_va(va, lpid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
281+
__tlbie_va_lpid(va, lpid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
284282
}
285283
}
286284

@@ -531,14 +529,14 @@ static void do_tlbiel_va_range(void *info)
531529
t->psize, t->also_pwc);
532530
}
533531

534-
static __always_inline void _tlbie_lpid_va(unsigned long va, unsigned long lpid,
532+
static __always_inline void _tlbie_va_lpid(unsigned long va, unsigned long lpid,
535533
unsigned long psize, unsigned long ric)
536534
{
537535
unsigned long ap = mmu_get_ap(psize);
538536

539537
asm volatile("ptesync": : :"memory");
540-
__tlbie_lpid_va(va, lpid, ap, ric);
541-
fixup_tlbie_lpid_va(va, lpid, ap);
538+
__tlbie_va_lpid(va, lpid, ap, ric);
539+
fixup_tlbie_va_lpid(va, lpid, ap);
542540
asm volatile("eieio; tlbsync; ptesync": : :"memory");
543541
}
544542

@@ -660,7 +658,7 @@ static bool mm_needs_flush_escalation(struct mm_struct *mm)
660658
* If always_flush is true, then flush even if this CPU can't be removed
661659
* from mm_cpumask.
662660
*/
663-
void exit_lazy_flush_tlb(struct mm_struct *mm, bool always_flush)
661+
static void exit_lazy_flush_tlb(struct mm_struct *mm)
664662
{
665663
unsigned long pid = mm->context.id;
666664
int cpu = smp_processor_id();
@@ -703,19 +701,17 @@ void exit_lazy_flush_tlb(struct mm_struct *mm, bool always_flush)
703701
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
704702
dec_mm_active_cpus(mm);
705703
cpumask_clear_cpu(cpu, mm_cpumask(mm));
706-
always_flush = true;
707704
}
708705

709706
out:
710-
if (always_flush)
711-
_tlbiel_pid(pid, RIC_FLUSH_ALL);
707+
_tlbiel_pid(pid, RIC_FLUSH_ALL);
712708
}
713709

714710
#ifdef CONFIG_SMP
715711
static void do_exit_flush_lazy_tlb(void *arg)
716712
{
717713
struct mm_struct *mm = arg;
718-
exit_lazy_flush_tlb(mm, true);
714+
exit_lazy_flush_tlb(mm);
719715
}
720716

721717
static void exit_flush_lazy_tlbs(struct mm_struct *mm)
@@ -777,7 +773,7 @@ static enum tlb_flush_type flush_type_needed(struct mm_struct *mm, bool fullmm)
777773
* to trim.
778774
*/
779775
if (tick_and_test_trim_clock()) {
780-
exit_lazy_flush_tlb(mm, true);
776+
exit_lazy_flush_tlb(mm);
781777
return FLUSH_TYPE_NONE;
782778
}
783779
}
@@ -823,7 +819,7 @@ static enum tlb_flush_type flush_type_needed(struct mm_struct *mm, bool fullmm)
823819
if (current->mm == mm)
824820
return FLUSH_TYPE_LOCAL;
825821
if (cpumask_test_cpu(cpu, mm_cpumask(mm)))
826-
exit_lazy_flush_tlb(mm, true);
822+
exit_lazy_flush_tlb(mm);
827823
return FLUSH_TYPE_NONE;
828824
}
829825

@@ -889,8 +885,7 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm)
889885
} else if (type == FLUSH_TYPE_GLOBAL) {
890886
if (!mmu_has_feature(MMU_FTR_GTSE)) {
891887
unsigned long tgt = H_RPTI_TARGET_CMMU;
892-
unsigned long type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
893-
H_RPTI_TYPE_PRT;
888+
unsigned long type = H_RPTI_TYPE_ALL;
894889

895890
if (atomic_read(&mm->context.copros) > 0)
896891
tgt |= H_RPTI_TARGET_NMMU;
@@ -986,8 +981,7 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
986981
{
987982
if (!mmu_has_feature(MMU_FTR_GTSE)) {
988983
unsigned long tgt = H_RPTI_TARGET_CMMU | H_RPTI_TARGET_NMMU;
989-
unsigned long type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
990-
H_RPTI_TYPE_PRT;
984+
unsigned long type = H_RPTI_TYPE_ALL;
991985

992986
pseries_rpt_invalidate(0, tgt, type, H_RPTI_PAGE_ALL,
993987
start, end);
@@ -1151,7 +1145,7 @@ void radix__flush_tlb_lpid_page(unsigned int lpid,
11511145
{
11521146
int psize = radix_get_mmu_psize(page_size);
11531147

1154-
_tlbie_lpid_va(addr, lpid, psize, RIC_FLUSH_TLB);
1148+
_tlbie_va_lpid(addr, lpid, psize, RIC_FLUSH_TLB);
11551149
}
11561150
EXPORT_SYMBOL_GPL(radix__flush_tlb_lpid_page);
11571151

@@ -1341,8 +1335,7 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
13411335
unsigned long tgt, type, pg_sizes;
13421336

13431337
tgt = H_RPTI_TARGET_CMMU;
1344-
type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
1345-
H_RPTI_TYPE_PRT;
1338+
type = H_RPTI_TYPE_ALL;
13461339
pg_sizes = psize_to_rpti_pgsize(mmu_virtual_psize);
13471340

13481341
if (atomic_read(&mm->context.copros) > 0)
@@ -1415,7 +1408,7 @@ static __always_inline void __tlbie_pid_lpid(unsigned long pid,
14151408
trace_tlbie(0, 0, rb, rs, ric, prs, r);
14161409
}
14171410

1418-
static __always_inline void __tlbie_va_lpid(unsigned long va, unsigned long pid,
1411+
static __always_inline void __tlbie_va_pid_lpid(unsigned long va, unsigned long pid,
14191412
unsigned long lpid,
14201413
unsigned long ap, unsigned long ric)
14211414
{
@@ -1447,7 +1440,7 @@ static inline void fixup_tlbie_pid_lpid(unsigned long pid, unsigned long lpid)
14471440

14481441
if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
14491442
asm volatile("ptesync" : : : "memory");
1450-
__tlbie_va_lpid(va, pid, lpid, mmu_get_ap(MMU_PAGE_64K),
1443+
__tlbie_va_pid_lpid(va, pid, lpid, mmu_get_ap(MMU_PAGE_64K),
14511444
RIC_FLUSH_TLB);
14521445
}
14531446
}
@@ -1478,7 +1471,7 @@ static inline void _tlbie_pid_lpid(unsigned long pid, unsigned long lpid,
14781471
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
14791472
}
14801473

1481-
static inline void fixup_tlbie_va_range_lpid(unsigned long va,
1474+
static inline void fixup_tlbie_va_range_pid_lpid(unsigned long va,
14821475
unsigned long pid,
14831476
unsigned long lpid,
14841477
unsigned long ap)
@@ -1490,11 +1483,11 @@ static inline void fixup_tlbie_va_range_lpid(unsigned long va,
14901483

14911484
if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
14921485
asm volatile("ptesync" : : : "memory");
1493-
__tlbie_va_lpid(va, pid, lpid, ap, RIC_FLUSH_TLB);
1486+
__tlbie_va_pid_lpid(va, pid, lpid, ap, RIC_FLUSH_TLB);
14941487
}
14951488
}
14961489

1497-
static inline void __tlbie_va_range_lpid(unsigned long start, unsigned long end,
1490+
static inline void __tlbie_va_range_pid_lpid(unsigned long start, unsigned long end,
14981491
unsigned long pid, unsigned long lpid,
14991492
unsigned long page_size,
15001493
unsigned long psize)
@@ -1503,20 +1496,20 @@ static inline void __tlbie_va_range_lpid(unsigned long start, unsigned long end,
15031496
unsigned long ap = mmu_get_ap(psize);
15041497

15051498
for (addr = start; addr < end; addr += page_size)
1506-
__tlbie_va_lpid(addr, pid, lpid, ap, RIC_FLUSH_TLB);
1499+
__tlbie_va_pid_lpid(addr, pid, lpid, ap, RIC_FLUSH_TLB);
15071500

1508-
fixup_tlbie_va_range_lpid(addr - page_size, pid, lpid, ap);
1501+
fixup_tlbie_va_range_pid_lpid(addr - page_size, pid, lpid, ap);
15091502
}
15101503

1511-
static inline void _tlbie_va_range_lpid(unsigned long start, unsigned long end,
1504+
static inline void _tlbie_va_range_pid_lpid(unsigned long start, unsigned long end,
15121505
unsigned long pid, unsigned long lpid,
15131506
unsigned long page_size,
15141507
unsigned long psize, bool also_pwc)
15151508
{
15161509
asm volatile("ptesync" : : : "memory");
15171510
if (also_pwc)
15181511
__tlbie_pid_lpid(pid, lpid, RIC_FLUSH_PWC);
1519-
__tlbie_va_range_lpid(start, end, pid, lpid, page_size, psize);
1512+
__tlbie_va_range_pid_lpid(start, end, pid, lpid, page_size, psize);
15201513
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
15211514
}
15221515

@@ -1567,7 +1560,7 @@ void do_h_rpt_invalidate_prt(unsigned long pid, unsigned long lpid,
15671560
_tlbie_pid_lpid(pid, lpid, RIC_FLUSH_TLB);
15681561
return;
15691562
}
1570-
_tlbie_va_range_lpid(start, end, pid, lpid,
1563+
_tlbie_va_range_pid_lpid(start, end, pid, lpid,
15711564
(1UL << def->shift), psize, false);
15721565
}
15731566
}

0 commit comments

Comments
 (0)