Commit 8fed04d0 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

powerpc/64s/hash: remove user SLB data from the paca



User SLB mappig data is copied into the PACA from the mm->context so
it can be accessed by the SLB miss handlers.

After the C conversion, SLB miss handlers now run with relocation on,
and user SLB misses are able to take recursive kernel SLB misses, so
the user SLB mapping data can be removed from the paca and accessed
directly.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 5e46e29e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ struct slb_entry {
};

extern void slb_initialize(void);
extern void core_flush_all_slbs(struct mm_struct *mm);
extern void slb_flush_and_rebolt(void);
void slb_flush_all_realmode(void);
void __slb_restore_bolted_realmode(void);
+0 −13
Original line number Diff line number Diff line
@@ -143,18 +143,6 @@ struct paca_struct {
	struct tlb_core_data tcd;
#endif /* CONFIG_PPC_BOOK3E */

#ifdef CONFIG_PPC_BOOK3S
	mm_context_id_t mm_ctx_id;
#ifdef CONFIG_PPC_MM_SLICES
	unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE];
	unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE];
	unsigned long mm_ctx_slb_addr_limit;
#else
	u16 mm_ctx_user_psize;
	u16 mm_ctx_sllp;
#endif
#endif

	/*
	 * then miscellaneous read-write fields
	 */
@@ -258,7 +246,6 @@ struct paca_struct {
#endif /* CONFIG_PPC_BOOK3S_64 */
} ____cacheline_aligned;

extern void copy_mm_to_paca(struct mm_struct *mm);
extern struct paca_struct **paca_ptrs;
extern void initialise_paca(struct paca_struct *new_paca, int cpu);
extern void setup_paca(struct paca_struct *new_paca);
+0 −9
Original line number Diff line number Diff line
@@ -181,15 +181,6 @@ int main(void)
	OFFSET(PACAIRQSOFTMASK, paca_struct, irq_soft_mask);
	OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened);
	OFFSET(PACA_FTRACE_ENABLED, paca_struct, ftrace_enabled);
#ifdef CONFIG_PPC_BOOK3S
	OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id);
#ifdef CONFIG_PPC_MM_SLICES
	OFFSET(PACALOWSLICESPSIZE, paca_struct, mm_ctx_low_slices_psize);
	OFFSET(PACAHIGHSLICEPSIZE, paca_struct, mm_ctx_high_slices_psize);
	OFFSET(PACA_SLB_ADDR_LIMIT, paca_struct, mm_ctx_slb_addr_limit);
	DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
#endif /* CONFIG_PPC_MM_SLICES */
#endif

#ifdef CONFIG_PPC_BOOK3E
	OFFSET(PACAPGD, paca_struct, pgd);
+0 −22
Original line number Diff line number Diff line
@@ -258,25 +258,3 @@ void __init free_unused_pacas(void)
	printk(KERN_DEBUG "Allocated %u bytes for %u pacas\n",
			paca_ptrs_size + paca_struct_size, nr_cpu_ids);
}

void copy_mm_to_paca(struct mm_struct *mm)
{
#ifdef CONFIG_PPC_BOOK3S
	mm_context_t *context = &mm->context;

	get_paca()->mm_ctx_id = context->id;
#ifdef CONFIG_PPC_MM_SLICES
	VM_BUG_ON(!mm->context.slb_addr_limit);
	get_paca()->mm_ctx_slb_addr_limit = mm->context.slb_addr_limit;
	memcpy(&get_paca()->mm_ctx_low_slices_psize,
	       &context->low_slices_psize, sizeof(context->low_slices_psize));
	memcpy(&get_paca()->mm_ctx_high_slices_psize,
	       &context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm));
#else /* CONFIG_PPC_MM_SLICES */
	get_paca()->mm_ctx_user_psize = context->user_psize;
	get_paca()->mm_ctx_sllp = context->sllp;
#endif
#else /* !CONFIG_PPC_BOOK3S */
	return;
#endif
}
+11 −35
Original line number Diff line number Diff line
@@ -1088,16 +1088,16 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
}

#ifdef CONFIG_PPC_MM_SLICES
static unsigned int get_paca_psize(unsigned long addr)
static unsigned int get_psize(struct mm_struct *mm, unsigned long addr)
{
	unsigned char *psizes;
	unsigned long index, mask_index;

	if (addr < SLICE_LOW_TOP) {
		psizes = get_paca()->mm_ctx_low_slices_psize;
		psizes = mm->context.low_slices_psize;
		index = GET_LOW_SLICE_INDEX(addr);
	} else {
		psizes = get_paca()->mm_ctx_high_slices_psize;
		psizes = mm->context.high_slices_psize;
		index = GET_HIGH_SLICE_INDEX(addr);
	}
	mask_index = index & 0x1;
@@ -1105,9 +1105,9 @@ static unsigned int get_paca_psize(unsigned long addr)
}

#else
unsigned int get_paca_psize(unsigned long addr)
unsigned int get_psize(struct mm_struct *mm, unsigned long addr)
{
	return get_paca()->mm_ctx_user_psize;
	return mm->context.user_psize;
}
#endif

@@ -1118,15 +1118,11 @@ unsigned int get_paca_psize(unsigned long addr)
#ifdef CONFIG_PPC_64K_PAGES
void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
{
	if (get_slice_psize(mm, addr) == MMU_PAGE_4K)
	if (get_psize(mm, addr) == MMU_PAGE_4K)
		return;
	slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K);
	copro_flush_all_slbs(mm);
	if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) {

		copy_mm_to_paca(mm);
		slb_flush_and_rebolt();
	}
	core_flush_all_slbs(mm);
}
#endif /* CONFIG_PPC_64K_PAGES */

@@ -1191,22 +1187,6 @@ void hash_failure_debug(unsigned long ea, unsigned long access,
		trap, vsid, ssize, psize, lpsize, pte);
}

static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
			     int psize, bool user_region)
{
	if (user_region) {
		if (psize != get_paca_psize(ea)) {
			copy_mm_to_paca(mm);
			slb_flush_and_rebolt();
		}
	} else if (get_paca()->vmalloc_sllp !=
		   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
		get_paca()->vmalloc_sllp =
			mmu_psize_defs[mmu_vmalloc_psize].sllp;
		slb_vmalloc_update();
	}
}

/* Result code is:
 *  0 - handled
 *  1 - normal page fault
@@ -1239,7 +1219,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
			rc = 1;
			goto bail;
		}
		psize = get_slice_psize(mm, ea);
		psize = get_psize(mm, ea);
		ssize = user_segment_size(ea);
		vsid = get_user_vsid(&mm->context, ea, ssize);
		break;
@@ -1327,9 +1307,6 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
			WARN_ON(1);
		}
#endif
		if (current->mm == mm)
			check_paca_psize(ea, mm, psize, user_region);

		goto bail;
	}

@@ -1364,15 +1341,14 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
			       "to 4kB pages because of "
			       "non-cacheable mapping\n");
			psize = mmu_vmalloc_psize = MMU_PAGE_4K;
			slb_vmalloc_update();
			copro_flush_all_slbs(mm);
			core_flush_all_slbs(mm);
		}
	}

#endif /* CONFIG_PPC_64K_PAGES */

	if (current->mm == mm)
		check_paca_psize(ea, mm, psize, user_region);

#ifdef CONFIG_PPC_64K_PAGES
	if (psize == MMU_PAGE_64K)
		rc = __hash_page_64K(ea, access, vsid, ptep, trap,
@@ -1460,7 +1436,7 @@ int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap,
#ifdef CONFIG_PPC_MM_SLICES
static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
{
	int psize = get_slice_psize(mm, ea);
	int psize = get_psize(mm, ea);

	/* We only prefault standard pages for now */
	if (unlikely(psize != mm->context.user_psize))
Loading