Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/64s/pseries: radix flush translations before MMU is enabled at boot

Radix guests are responsible for managing their own translation caches,
so make them match bare metal radix and hash, and make each CPU flush
all its translations right before enabling its MMU.

Radix guests may not flush partition scope translations, so in
tlbiel_all, make these flushes conditional on CPU_FTR_HVMODE. Process
scope translations are the only type visible to the guest.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190902152931.17840-5-npiggin@gmail.com

authored by

Nicholas Piggin and committed by
Michael Ellerman
7e71c428 fd13daea

+10 -8
+2 -4
arch/powerpc/mm/book3s64/radix_pgtable.c
··· 616 616 617 617 /* Switch to the guard PID before turning on MMU */ 618 618 radix__switch_mmu_context(NULL, &init_mm); 619 - if (cpu_has_feature(CPU_FTR_HVMODE)) 620 - tlbiel_all(); 619 + tlbiel_all(); 621 620 } 622 621 623 622 void radix__early_init_mmu_secondary(void) ··· 636 637 } 637 638 638 639 radix__switch_mmu_context(NULL, &init_mm); 639 - if (cpu_has_feature(CPU_FTR_HVMODE)) 640 - tlbiel_all(); 640 + tlbiel_all(); 641 641 } 642 642 643 643 void radix__mmu_cleanup_all(void)
+8 -4
arch/powerpc/mm/book3s64/radix_tlb.c
··· 51 51 * and partition table entries. Then flush the remaining sets of the 52 52 * TLB. 53 53 */ 54 - tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 0); 55 - for (set = 1; set < num_sets; set++) 56 - tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 0); 57 54 58 - /* Do the same for process scoped entries. */ 55 + if (early_cpu_has_feature(CPU_FTR_HVMODE)) { 56 + /* MSR[HV] should flush partition scope translations first. */ 57 + tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 0); 58 + for (set = 1; set < num_sets; set++) 59 + tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 0); 60 + } 61 + 62 + /* Flush process scoped entries. */ 59 63 tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 1); 60 64 for (set = 1; set < num_sets; set++) 61 65 tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 1);