Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2b26c92 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

powerpc/book3e: Adjust the page sizes list based on MMU config



Use the MMU config registers to scan for available direct and
indirect page sizes and print out the result. Will be needed
for future hugetlbfs implementation.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 03247157
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -193,6 +193,10 @@ struct mmu_psize_def
{
	unsigned int	shift;	/* number of bits */
	unsigned int	enc;	/* PTE encoding */
	unsigned int    ind;    /* Corresponding indirect page size shift */
	unsigned int	flags;
#define MMU_PAGE_SIZE_DIRECT	0x1	/* Supported as a direct size */
#define MMU_PAGE_SIZE_INDIRECT	0x2	/* Supported as an indirect size */
};
extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];

+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@
#define SPRN_TLB0PS	0x158	/* TLB 0 Page Size Register */
#define SPRN_MAS5_MAS6	0x15c	/* MMU Assist Register 5 || 6 */
#define SPRN_MAS8_MAS1	0x15d	/* MMU Assist Register 8 || 1 */
#define SPRN_EPTCFG	0x15e	/* Embedded Page Table Config */
#define SPRN_MAS7_MAS3	0x174	/* MMU Assist Register 7 || 3 */
#define SPRN_MAS0_MAS1	0x175	/* MMU Assist Register 0 || 1 */
#define SPRN_IVOR0	0x190	/* Interrupt Vector Offset Register 0 */
+104 −32
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
	[MMU_PAGE_4K] = {
		.shift	= 12,
		.ind	= 20,
		.enc	= BOOK3E_PAGESZ_4K,
	},
	[MMU_PAGE_16K] = {
@@ -54,6 +55,7 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
	},
	[MMU_PAGE_64K] = {
		.shift	= 16,
		.ind	= 28,
		.enc	= BOOK3E_PAGESZ_64K,
	},
	[MMU_PAGE_1M] = {
@@ -62,6 +64,7 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
	},
	[MMU_PAGE_16M] = {
		.shift	= 24,
		.ind	= 36,
		.enc	= BOOK3E_PAGESZ_16M,
	},
	[MMU_PAGE_256M] = {
@@ -344,31 +347,76 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address)
	}
}

/*
 * Early initialization of the MMU TLB code
static void setup_page_sizes(void)
{
	unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);
	unsigned int tlb0ps = mfspr(SPRN_TLB0PS);
	unsigned int eptcfg = mfspr(SPRN_EPTCFG);
	int i, psize;

	/* Look for supported direct sizes */
	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
		struct mmu_psize_def *def = &mmu_psize_defs[psize];

		if (tlb0ps & (1U << (def->shift - 10)))
			def->flags |= MMU_PAGE_SIZE_DIRECT;
	}

	/* Indirect page sizes supported ? */
	if ((tlb0cfg & TLBnCFG_IND) == 0)
		goto no_indirect;

	/* Now, we only deal with one IND page size for each
	 * direct size. Hopefully all implementations today are
	 * unambiguous, but we might want to be careful in the
	 * future.
	 */
static void __early_init_mmu(int boot_cpu)
	for (i = 0; i < 3; i++) {
		unsigned int ps, sps;

		sps = eptcfg & 0x1f;
		eptcfg >>= 5;
		ps = eptcfg & 0x1f;
		eptcfg >>= 5;
		if (!ps || !sps)
			continue;
		for (psize = 0; psize < MMU_PAGE_COUNT; psize++) {
			struct mmu_psize_def *def = &mmu_psize_defs[psize];

			if (ps == (def->shift - 10))
				def->flags |= MMU_PAGE_SIZE_INDIRECT;
			if (sps == (def->shift - 10))
				def->ind = ps + 10;
		}
	}
 no_indirect:

	/* Cleanup array and print summary */
	pr_info("MMU: Supported page sizes\n");
	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
		struct mmu_psize_def *def = &mmu_psize_defs[psize];
		const char *__page_type_names[] = {
			"unsupported",
			"direct",
			"indirect",
			"direct & indirect"
		};
		if (def->flags == 0) {
			def->shift = 0;	
			continue;
		}
		pr_info("  %8ld KB as %s\n", 1ul << (def->shift - 10),
			__page_type_names[def->flags & 0x3]);
	}
}

static void setup_mmu_htw(void)
{
	extern unsigned int interrupt_base_book3e;
	extern unsigned int exc_data_tlb_miss_htw_book3e;
	extern unsigned int exc_instruction_tlb_miss_htw_book3e;

	unsigned int *ibase = &interrupt_base_book3e;
	unsigned int mas4;

	/* XXX This will have to be decided at runtime, but right
	 * now our boot and TLB miss code hard wires it. Ideally
	 * we should find out a suitable page size and patch the
	 * TLB miss code (either that or use the PACA to store
	 * the value we want)
	 */
	mmu_linear_psize = MMU_PAGE_1G;

	/* XXX This should be decided at runtime based on supported
	 * page sizes in the TLB, but for now let's assume 16M is
	 * always there and a good fit (which it probably is)
	 */
	mmu_vmemmap_psize = MMU_PAGE_16M;

	/* Check if HW tablewalk is present, and if yes, enable it by:
	 *
@@ -376,19 +424,9 @@ static void __early_init_mmu(int boot_cpu)
	 *   one dedicates to it
	 *
	 * - setting the global book3e_htw_enabled
	 *
	 * - Set MAS4:INDD and default page size
	 */

	/* XXX This code only checks for TLB 0 capabilities and doesn't
	 *     check what page size combos are supported by the HW. It
	 *     also doesn't handle the case where a separate array holds
	 *     the IND entries from the array loaded by the PT.
       	 */
	if (boot_cpu) {
	unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);

		/* Check if HW loader is supported */
	if ((tlb0cfg & TLBnCFG_IND) &&
	    (tlb0cfg & TLBnCFG_PT)) {
		/* Our exceptions vectors start with a NOP and -then- a branch
@@ -406,6 +444,40 @@ static void __early_init_mmu(int boot_cpu)
		book3e_htw_enabled ? "Enabled" : "Disabled");
}

/*
 * Early initialization of the MMU TLB code
 */
static void __early_init_mmu(int boot_cpu)
{
	unsigned int mas4;

	/* XXX This will have to be decided at runtime, but right
	 * now our boot and TLB miss code hard wires it. Ideally
	 * we should find out a suitable page size and patch the
	 * TLB miss code (either that or use the PACA to store
	 * the value we want)
	 */
	mmu_linear_psize = MMU_PAGE_1G;

	/* XXX This should be decided at runtime based on supported
	 * page sizes in the TLB, but for now let's assume 16M is
	 * always there and a good fit (which it probably is)
	 */
	mmu_vmemmap_psize = MMU_PAGE_16M;

	/* XXX This code only checks for TLB 0 capabilities and doesn't
	 *     check what page size combos are supported by the HW. It
	 *     also doesn't handle the case where a separate array holds
	 *     the IND entries from the array loaded by the PT.
	 */
	if (boot_cpu) {
		/* Look for supported page sizes */
		setup_page_sizes();

		/* Look for HW tablewalk support */
		setup_mmu_htw();
	}

	/* Set MAS4 based on page table setting */

	mas4 = 0x4 << MAS4_WIMGED_SHIFT;