[PATCH v1] powerpc/64s: Get LPID bit width from device tree
Nicholas Piggin
npiggin at gmail.com
Wed Nov 10 18:02:06 AEDT 2021
Excerpts from Fabiano Rosas's message of November 10, 2021 7:19 am:
> Nicholas Piggin <npiggin at 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 the extra bits yet, this is mainly required
>> to get the PTCR register values correct.
>>
>> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
>> ---
>> arch/powerpc/include/asm/book3s/64/mmu.h | 9 ++---
>> arch/powerpc/include/asm/kvm_book3s_asm.h | 6 +++-
>> arch/powerpc/include/asm/reg.h | 2 --
>> arch/powerpc/mm/book3s64/pgtable.c | 5 ---
>> arch/powerpc/mm/book3s64/radix_pgtable.c | 13 +------
>> arch/powerpc/mm/init_64.c | 44 +++++++++++++++++++++++
>> 6 files changed, 55 insertions(+), 24 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/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
>> index b6d31bff5209..4d93e09a1ab9 100644
>> --- a/arch/powerpc/include/asm/kvm_book3s_asm.h
>> +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
>> @@ -15,7 +15,11 @@
>> #define XICS_IPI 2 /* interrupt source # for IPIs */
>>
>> /* LPIDs we support with this build -- runtime limit may be lower */
>> -#define KVMPPC_NR_LPIDS (LPID_RSVD + 1)
>> +#define KVMPPC_NR_LPIDS (1ul << 12)
>> +
>> +/* Reserved LPID for partn switching */
>> +#define LPID_RSVD_POWER7 ((1ul << 10) - 1)
>> +#define LPID_RSVD (KVMPPC_NR_LPIDS - 1)
>>
>> /* Maximum number of threads per physical core */
>> #define MAX_SMT_THREADS 8
>> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
>> index e9d27265253b..30983f2fd6a4 100644
>> --- a/arch/powerpc/include/asm/reg.h
>> +++ b/arch/powerpc/include/asm/reg.h
>> @@ -474,8 +474,6 @@
>> #ifndef SPRN_LPID
>> #define SPRN_LPID 0x13F /* Logical Partition Identifier */
>> #endif
>> -#define LPID_RSVD_POWER7 0x3ff /* Reserved LPID for partn switching */
>> -#define LPID_RSVD 0xfff /* Reserved LPID for partn switching */
>> #define SPRN_HMER 0x150 /* Hypervisor maintenance exception reg */
>> #define HMER_DEBUG_TRIG (1ul << (63 - 17)) /* Debug trigger */
>> #define SPRN_HMEER 0x151 /* Hyp maintenance exception enable reg */
>> 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..7d5a6cb7c76d 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,12 +440,53 @@ 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;
>
> What if only one of the properties is present?
Ah that may be a problem because the below fallback would not set the
other one that was not found (e.g., some firmware might only give us
ibm,mmu-pid-bits because that was defined earlier).
I will respin.
Thanks,
Nick
More information about the Linuxppc-dev
mailing list