Nicholas Piggin <npig...@gmail.com> writes: > Allow the LPID bit width and partition table size to be set at runtime > from the device tree. > > Move the PID bit width detection into the same place. > > KVM does not support using different sizes yet, this is mainly required > to get the PTCR register values correct. > > Signed-off-by: Nicholas Piggin <npig...@gmail.com>
Reviewed-by: Fabiano Rosas <faro...@linux.ibm.com> > --- > arch/powerpc/include/asm/book3s/64/mmu.h | 9 +++-- > arch/powerpc/mm/book3s64/pgtable.c | 5 --- > arch/powerpc/mm/book3s64/radix_pgtable.c | 13 +------ > arch/powerpc/mm/init_64.c | 47 +++++++++++++++++++++++- > 4 files changed, 52 insertions(+), 22 deletions(-) > > diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h > b/arch/powerpc/include/asm/book3s/64/mmu.h > index c02f42d1031e..8c500dd6fee4 100644 > --- a/arch/powerpc/include/asm/book3s/64/mmu.h > +++ b/arch/powerpc/include/asm/book3s/64/mmu.h > @@ -62,6 +62,9 @@ extern struct patb_entry *partition_tb; > #define PRTS_MASK 0x1f /* process table size field */ > #define PRTB_MASK 0x0ffffffffffff000UL > > +/* Number of supported LPID bits */ > +extern unsigned int mmu_lpid_bits; > + > /* Number of supported PID bits */ > extern unsigned int mmu_pid_bits; > > @@ -76,10 +79,8 @@ extern unsigned long __ro_after_init radix_mem_block_size; > #define PRTB_SIZE_SHIFT (mmu_pid_bits + 4) > #define PRTB_ENTRIES (1ul << mmu_pid_bits) > > -/* > - * Power9 currently only support 64K partition table size. > - */ > -#define PATB_SIZE_SHIFT 16 > +#define PATB_SIZE_SHIFT (mmu_lpid_bits + 4) > +#define PATB_ENTRIES (1ul << mmu_lpid_bits) > > typedef unsigned long mm_context_id_t; > struct spinlock; > diff --git a/arch/powerpc/mm/book3s64/pgtable.c > b/arch/powerpc/mm/book3s64/pgtable.c > index 9e16c7b1a6c5..13d1fbddecb9 100644 > --- a/arch/powerpc/mm/book3s64/pgtable.c > +++ b/arch/powerpc/mm/book3s64/pgtable.c > @@ -207,17 +207,12 @@ void __init mmu_partition_table_init(void) > unsigned long patb_size = 1UL << PATB_SIZE_SHIFT; > unsigned long ptcr; > > - BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too > large."); > /* Initialize the Partition Table with no entries */ > partition_tb = memblock_alloc(patb_size, patb_size); > if (!partition_tb) > panic("%s: Failed to allocate %lu bytes align=0x%lx\n", > __func__, patb_size, patb_size); > > - /* > - * update partition table control register, > - * 64 K size. > - */ > ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12); > set_ptcr_when_no_uv(ptcr); > powernv_set_nmmu_ptcr(ptcr); > diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c > b/arch/powerpc/mm/book3s64/radix_pgtable.c > index ae20add7954a..1c855434f8dc 100644 > --- a/arch/powerpc/mm/book3s64/radix_pgtable.c > +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c > @@ -33,7 +33,6 @@ > > #include <trace/events/thp.h> > > -unsigned int mmu_pid_bits; > unsigned int mmu_base_pid; > unsigned long radix_mem_block_size __ro_after_init; > > @@ -357,18 +356,13 @@ static void __init radix_init_pgtable(void) > -1, PAGE_KERNEL)); > } > > - /* Find out how many PID bits are supported */ > if (!cpu_has_feature(CPU_FTR_HVMODE) && > cpu_has_feature(CPU_FTR_P9_RADIX_PREFETCH_BUG)) { > /* > * Older versions of KVM on these machines perfer if the > * guest only uses the low 19 PID bits. > */ > - if (!mmu_pid_bits) > - mmu_pid_bits = 19; > - } else { > - if (!mmu_pid_bits) > - mmu_pid_bits = 20; > + mmu_pid_bits = 19; > } > mmu_base_pid = 1; > > @@ -449,11 +443,6 @@ static int __init radix_dt_scan_page_sizes(unsigned long > node, > if (type == NULL || strcmp(type, "cpu") != 0) > return 0; > > - /* Find MMU PID size */ > - prop = of_get_flat_dt_prop(node, "ibm,mmu-pid-bits", &size); > - if (prop && size == 4) > - mmu_pid_bits = be32_to_cpup(prop); > - > /* Grab page size encodings */ > prop = of_get_flat_dt_prop(node, "ibm,processor-radix-AP-encodings", > &size); > if (!prop) > diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c > index 386be136026e..04f45fcb1222 100644 > --- a/arch/powerpc/mm/init_64.c > +++ b/arch/powerpc/mm/init_64.c > @@ -370,6 +370,9 @@ void register_page_bootmem_memmap(unsigned long > section_nr, > #endif /* CONFIG_SPARSEMEM_VMEMMAP */ > > #ifdef CONFIG_PPC_BOOK3S_64 > +unsigned int mmu_lpid_bits; > +unsigned int mmu_pid_bits; > + > static bool disable_radix = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); > > static int __init parse_disable_radix(char *p) > @@ -437,19 +440,61 @@ static void __init early_check_vec5(void) > } > } > > +static int __init dt_scan_mmu_pid_width(unsigned long node, > + const char *uname, int depth, > + void *data) > +{ > + int size = 0; > + const __be32 *prop; > + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); > + > + /* We are scanning "cpu" nodes only */ > + if (type == NULL || strcmp(type, "cpu") != 0) > + return 0; > + > + /* Find MMU LPID, PID register size */ > + prop = of_get_flat_dt_prop(node, "ibm,mmu-lpid-bits", &size); > + if (prop && size == 4) > + mmu_lpid_bits = be32_to_cpup(prop); > + > + prop = of_get_flat_dt_prop(node, "ibm,mmu-pid-bits", &size); > + if (prop && size == 4) > + mmu_pid_bits = be32_to_cpup(prop); > + > + if (!mmu_pid_bits && !mmu_lpid_bits) > + return 0; > + > + return 1; > +} > + > void __init mmu_early_init_devtree(void) > { > + int rc; > + bool hvmode = !!(mfmsr() & MSR_HV); > + > /* Disable radix mode based on kernel command line. */ > if (disable_radix) > cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX; > > + rc = of_scan_flat_dt(dt_scan_mmu_pid_width, NULL); > + if (hvmode && !mmu_lpid_bits) { > + if (early_cpu_has_feature(CPU_FTR_ARCH_207S)) > + mmu_lpid_bits = 12; /* POWER8-10 */ > + else > + mmu_lpid_bits = 10; /* POWER7 */ > + } > + if (!mmu_pid_bits) { > + if (early_cpu_has_feature(CPU_FTR_ARCH_300)) > + mmu_pid_bits = 20; /* POWER9-10 */ > + } > + > /* > * Check /chosen/ibm,architecture-vec-5 if running as a guest. > * When running bare-metal, we can use radix if we like > * even though the ibm,architecture-vec-5 property created by > * skiboot doesn't have the necessary bits set. > */ > - if (!(mfmsr() & MSR_HV)) > + if (!hvmode) > early_check_vec5(); > > if (early_radix_enabled()) {