Skip to content

Commit aa0ab02

Browse files
chleroympe
authored andcommitted
powerpc/mm/slice: Fix hugepage allocation at hint address on 8xx
On the 8xx, the page size is set in the PMD entry and applies to all pages of the page table pointed by the said PMD entry. When an app has some regular pages allocated (e.g. see below) and tries to mmap() a huge page at a hint address covered by the same PMD entry, the kernel accepts the hint allthough the 8xx cannot handle different page sizes in the same PMD entry. 10000000-10001000 r-xp 00000000 00:0f 2597 /root/malloc 10010000-10011000 rwxp 00000000 00:0f 2597 /root/malloc mmap(0x10080000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x40000, -1, 0) = 0x10080000 This results the app remaining forever in do_page_fault()/hugetlb_fault() and when interrupting that app, we get the following warning: [162980.035629] WARNING: CPU: 0 PID: 2777 at arch/powerpc/mm/hugetlbpage.c:354 hugetlb_free_pgd_range+0xc8/0x1e4 [162980.035699] CPU: 0 PID: 2777 Comm: malloc Tainted: G W 4.14.6 #85 [162980.035744] task: c67e2c00 task.stack: c668e000 [162980.035783] NIP: c000fe18 LR: c00e1eec CTR: c00f90c0 [162980.035830] REGS: c668fc20 TRAP: 0700 Tainted: G W (4.14.6) [162980.035854] MSR: 00029032 <EE,ME,IR,DR,RI> CR: 24044224 XER: 20000000 [162980.036003] [162980.036003] GPR00: c00e1eec c668fcd0 c67e2c00 00000010 c6869410 10080000 00000000 77fb4000 [162980.036003] GPR08: ffff0001 0683c001 00000000 ffffff80 44028228 10018a34 00004008 418004fc [162980.036003] GPR16: c668e000 00040100 c668e000 c06c0000 c668fe78 c668e000 c6835ba0 c668fd48 [162980.036003] GPR24: 00000000 73ffffff 74000000 00000001 77fb4000 100fffff 10100000 10100000 [162980.036743] NIP [c000fe18] hugetlb_free_pgd_range+0xc8/0x1e4 [162980.036839] LR [c00e1eec] free_pgtables+0x12c/0x150 [162980.036861] Call Trace: [162980.036939] [c668fcd0] [c00f0774] unlink_anon_vmas+0x1c4/0x214 (unreliable) [162980.037040] [c668fd10] [c00e1eec] free_pgtables+0x12c/0x150 [162980.037118] [c668fd40] [c00eabac] exit_mmap+0xe8/0x1b4 [162980.037210] [c668fda0] [c0019710] mmput.part.9+0x20/0xd8 [162980.037301] [c668fdb0] [c001ecb0] do_exit+0x1f0/0x93c [162980.037386] [c668fe00] [c001f478] do_group_exit+0x40/0xcc [162980.037479] [c668fe10] [c002a76c] get_signal+0x47c/0x614 [162980.037570] [c668fe70] [c0007840] do_signal+0x54/0x244 [162980.037654] [c668ff30] [c0007ae8] do_notify_resume+0x34/0x88 [162980.037744] [c668ff40] [c000dae8] do_user_signal+0x74/0xc4 [162980.037781] Instruction dump: [162980.037821] 7fdff378 81370000 54a3463a 80890020 7d24182e 7c841a14 712a0004 4082ff94 [162980.038014] 2f890000 419e0010 712a0ff0 408200e0 <0fe00000> 54a9000a 7f984840 419d0094 [162980.038216] ---[ end trace c0ceeca8e7a5800a ]--- [162980.038754] BUG: non-zero nr_ptes on freeing mm: 1 [162985.363322] BUG: non-zero nr_ptes on freeing mm: -1 In order to fix this, this patch uses the address space "slices" implemented for BOOK3S/64 and enhanced to support PPC32 by the preceding patch. This patch modifies the context.id on the 8xx to be in the range [1:16] instead of [0:15] in order to identify context.id == 0 as not initialised contexts as done on BOOK3S This patch activates CONFIG_PPC_MM_SLICES when CONFIG_HUGETLB_PAGE is selected for the 8xx Alltough we could in theory have as many slices as PMD entries, the current slices implementation limits the number of low slices to 16. This limitation is not preventing us to fix the initial issue allthough it is suboptimal. It will be cured in a subsequent patch. Fixes: 4b91428 ("powerpc/8xx: Implement support of hugepages") Signed-off-by: Christophe Leroy <[email protected]> Reviewed-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent db3a528 commit aa0ab02

File tree

6 files changed

+28
-3
lines changed

6 files changed

+28
-3
lines changed

arch/powerpc/include/asm/mmu-8xx.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ typedef struct {
191191
unsigned int id;
192192
unsigned int active;
193193
unsigned long vdso_base;
194+
#ifdef CONFIG_PPC_MM_SLICES
195+
u16 user_psize; /* page size index */
196+
u64 low_slices_psize; /* page size encodings */
197+
unsigned char high_slices_psize[0];
198+
unsigned long slb_addr_limit;
199+
#endif
194200
} mm_context_t;
195201

196202
#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)

arch/powerpc/kernel/setup-common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,8 @@ void __init setup_arch(char **cmdline_p)
919919
#ifdef CONFIG_PPC64
920920
if (!radix_enabled())
921921
init_mm.context.slb_addr_limit = DEFAULT_MAP_WINDOW_USER64;
922+
#elif defined(CONFIG_PPC_8xx)
923+
init_mm.context.slb_addr_limit = DEFAULT_MAP_WINDOW;
922924
#else
923925
#error "context.addr_limit not initialized."
924926
#endif

arch/powerpc/mm/8xx_mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void set_context(unsigned long id, pgd_t *pgd)
192192
mtspr(SPRN_M_TW, __pa(pgd) - offset);
193193

194194
/* Update context */
195-
mtspr(SPRN_M_CASID, id);
195+
mtspr(SPRN_M_CASID, id - 1);
196196
/* sync */
197197
mb();
198198
}

arch/powerpc/mm/hugetlbpage.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,11 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
553553
struct hstate *hstate = hstate_file(file);
554554
int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
555555

556+
#ifdef CONFIG_PPC_RADIX_MMU
556557
if (radix_enabled())
557558
return radix__hugetlb_get_unmapped_area(file, addr, len,
558559
pgoff, flags);
560+
#endif
559561
return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1);
560562
}
561563
#endif

arch/powerpc/mm/mmu_context_nohash.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,20 @@ int init_new_context(struct task_struct *t, struct mm_struct *mm)
331331
{
332332
pr_hard("initing context for mm @%p\n", mm);
333333

334+
#ifdef CONFIG_PPC_MM_SLICES
335+
if (!mm->context.slb_addr_limit)
336+
mm->context.slb_addr_limit = DEFAULT_MAP_WINDOW;
337+
338+
/*
339+
* We have MMU_NO_CONTEXT set to be ~0. Hence check
340+
* explicitly against context.id == 0. This ensures that we properly
341+
* initialize context slice details for newly allocated mm's (which will
342+
* have id == 0) and don't alter context slice inherited via fork (which
343+
* will have id != 0).
344+
*/
345+
if (mm->context.id == 0)
346+
slice_set_user_psize(mm, mmu_virtual_psize);
347+
#endif
334348
mm->context.id = MMU_NO_CONTEXT;
335349
mm->context.active = 0;
336350
return 0;
@@ -428,8 +442,8 @@ void __init mmu_context_init(void)
428442
* -- BenH
429443
*/
430444
if (mmu_has_feature(MMU_FTR_TYPE_8xx)) {
431-
first_context = 0;
432-
last_context = 15;
445+
first_context = 1;
446+
last_context = 16;
433447
no_selective_tlbil = true;
434448
} else if (mmu_has_feature(MMU_FTR_TYPE_47x)) {
435449
first_context = 1;

arch/powerpc/platforms/Kconfig.cputype

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ config PPC_BOOK3E_MMU
326326
config PPC_MM_SLICES
327327
bool
328328
default y if PPC_BOOK3S_64
329+
default y if PPC_8xx && HUGETLB_PAGE
329330
default n
330331

331332
config PPC_HAVE_PMU_SUPPORT

0 commit comments

Comments
 (0)