Message ID | 20220123120043.3586018-3-npiggin@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | KVM: PPC: Book3S: Make LPID/nested LPID allocations dynamic | expand |
Nicholas Piggin <npiggin@gmail.com> writes: > The LPID allocator init is changed to: > - use mmu_lpid_bits rather than hard-coding; > - use KVM_MAX_NESTED_GUESTS for nested hypervisors; > - not reserve the top LPID on POWER9 and newer CPUs. > > The reserved LPID is made a POWER7/8-specific detail. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> > --- Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com> > arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +- > arch/powerpc/include/asm/reg.h | 2 -- > arch/powerpc/kvm/book3s_64_mmu_hv.c | 29 ++++++++++++++++------- > arch/powerpc/kvm/book3s_hv_rmhandlers.S | 8 +++++++ > arch/powerpc/mm/init_64.c | 3 +++ > 5 files changed, 33 insertions(+), 11 deletions(-) > > diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h > index b6d31bff5209..e6bda70b1d93 100644 > --- a/arch/powerpc/include/asm/kvm_book3s_asm.h > +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h > @@ -15,7 +15,7 @@ > #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) > > /* 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 1e14324c5190..1e8b2e04e626 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -473,8 +473,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/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c > index 09fc52b6f390..5be92d5bc099 100644 > --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c > +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c > @@ -256,7 +256,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, > > int kvmppc_mmu_hv_init(void) > { > - unsigned long rsvd_lpid; > + unsigned long nr_lpids; > > if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) > return -EINVAL; > @@ -264,16 +264,29 @@ int kvmppc_mmu_hv_init(void) > if (cpu_has_feature(CPU_FTR_HVMODE)) { > if (WARN_ON(mfspr(SPRN_LPID) != 0)) > return -EINVAL; > + nr_lpids = 1UL << mmu_lpid_bits; > + } else { > + nr_lpids = KVM_MAX_NESTED_GUESTS; > } > > - /* POWER8 and above have 12-bit LPIDs (10-bit in POWER7) */ > - if (cpu_has_feature(CPU_FTR_ARCH_207S)) > - rsvd_lpid = LPID_RSVD; > - else > - rsvd_lpid = LPID_RSVD_POWER7; > + if (nr_lpids > KVMPPC_NR_LPIDS) > + nr_lpids = KVMPPC_NR_LPIDS; > + > + if (!cpu_has_feature(CPU_FTR_ARCH_300)) { > + /* POWER7 has 10-bit LPIDs, POWER8 has 12-bit LPIDs */ > + if (cpu_has_feature(CPU_FTR_ARCH_207S)) > + WARN_ON(nr_lpids != 1UL << 12); > + else > + WARN_ON(nr_lpids != 1UL << 10); > + > + /* > + * Reserve the last implemented LPID use in partition > + * switching for POWER7 and POWER8. > + */ > + nr_lpids -= 1; > + } > > - /* rsvd_lpid is reserved for use in partition switching */ > - kvmppc_init_lpid(rsvd_lpid); > + kvmppc_init_lpid(nr_lpids); > > return 0; > } > diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > index d185dee26026..0c552885a032 100644 > --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S > +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S > @@ -50,6 +50,14 @@ > #define STACK_SLOT_UAMOR (SFS-88) > #define STACK_SLOT_FSCR (SFS-96) > > +/* > + * Use the last LPID (all implemented LPID bits = 1) for partition switching. > + * This is reserved in the LPID allocator. POWER7 only implements 0x3ff, but > + * we write 0xfff into the LPID SPR anyway, which seems to work and just > + * ignores the top bits. > + */ > +#define LPID_RSVD 0xfff > + > /* > * Call kvmppc_hv_entry in real mode. > * Must be called with interrupts hard-disabled. > diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c > index 35f46bf54281..ad1a41e3ff1c 100644 > --- a/arch/powerpc/mm/init_64.c > +++ b/arch/powerpc/mm/init_64.c > @@ -371,6 +371,9 @@ void register_page_bootmem_memmap(unsigned long section_nr, > > #ifdef CONFIG_PPC_BOOK3S_64 > unsigned int mmu_lpid_bits; > +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE > +EXPORT_SYMBOL_GPL(mmu_lpid_bits); > +#endif > unsigned int mmu_pid_bits; > > static bool disable_radix = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index b6d31bff5209..e6bda70b1d93 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -15,7 +15,7 @@ #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) /* 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 1e14324c5190..1e8b2e04e626 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -473,8 +473,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/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 09fc52b6f390..5be92d5bc099 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -256,7 +256,7 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, int kvmppc_mmu_hv_init(void) { - unsigned long rsvd_lpid; + unsigned long nr_lpids; if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) return -EINVAL; @@ -264,16 +264,29 @@ int kvmppc_mmu_hv_init(void) if (cpu_has_feature(CPU_FTR_HVMODE)) { if (WARN_ON(mfspr(SPRN_LPID) != 0)) return -EINVAL; + nr_lpids = 1UL << mmu_lpid_bits; + } else { + nr_lpids = KVM_MAX_NESTED_GUESTS; } - /* POWER8 and above have 12-bit LPIDs (10-bit in POWER7) */ - if (cpu_has_feature(CPU_FTR_ARCH_207S)) - rsvd_lpid = LPID_RSVD; - else - rsvd_lpid = LPID_RSVD_POWER7; + if (nr_lpids > KVMPPC_NR_LPIDS) + nr_lpids = KVMPPC_NR_LPIDS; + + if (!cpu_has_feature(CPU_FTR_ARCH_300)) { + /* POWER7 has 10-bit LPIDs, POWER8 has 12-bit LPIDs */ + if (cpu_has_feature(CPU_FTR_ARCH_207S)) + WARN_ON(nr_lpids != 1UL << 12); + else + WARN_ON(nr_lpids != 1UL << 10); + + /* + * Reserve the last implemented LPID use in partition + * switching for POWER7 and POWER8. + */ + nr_lpids -= 1; + } - /* rsvd_lpid is reserved for use in partition switching */ - kvmppc_init_lpid(rsvd_lpid); + kvmppc_init_lpid(nr_lpids); return 0; } diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index d185dee26026..0c552885a032 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -50,6 +50,14 @@ #define STACK_SLOT_UAMOR (SFS-88) #define STACK_SLOT_FSCR (SFS-96) +/* + * Use the last LPID (all implemented LPID bits = 1) for partition switching. + * This is reserved in the LPID allocator. POWER7 only implements 0x3ff, but + * we write 0xfff into the LPID SPR anyway, which seems to work and just + * ignores the top bits. + */ +#define LPID_RSVD 0xfff + /* * Call kvmppc_hv_entry in real mode. * Must be called with interrupts hard-disabled. diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 35f46bf54281..ad1a41e3ff1c 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -371,6 +371,9 @@ void register_page_bootmem_memmap(unsigned long section_nr, #ifdef CONFIG_PPC_BOOK3S_64 unsigned int mmu_lpid_bits; +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +EXPORT_SYMBOL_GPL(mmu_lpid_bits); +#endif unsigned int mmu_pid_bits; static bool disable_radix = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
The LPID allocator init is changed to: - use mmu_lpid_bits rather than hard-coding; - use KVM_MAX_NESTED_GUESTS for nested hypervisors; - not reserve the top LPID on POWER9 and newer CPUs. The reserved LPID is made a POWER7/8-specific detail. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- arch/powerpc/include/asm/kvm_book3s_asm.h | 2 +- arch/powerpc/include/asm/reg.h | 2 -- arch/powerpc/kvm/book3s_64_mmu_hv.c | 29 ++++++++++++++++------- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 8 +++++++ arch/powerpc/mm/init_64.c | 3 +++ 5 files changed, 33 insertions(+), 11 deletions(-)