powerpc/64: Make type of partition table flush depend on partition type
authorPaul Mackerras <paulus@ozlabs.org>
Mon, 30 Jan 2017 10:21:39 +0000 (21:21 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 31 Jan 2017 08:11:46 +0000 (19:11 +1100)
When changing a partition table entry on POWER9, we do a particular
form of the tlbie instruction which flushes all TLBs and caches of
the partition table for a given logical partition ID (LPID).
This instruction has a field in the instruction word, labelled R
(radix), which should be 1 if the partition was previously a radix
partition and 0 if it was a HPT partition.  This implements that
logic.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/mm/pgtable_64.c

index 8bca7f5..d6b5e5c 100644 (file)
@@ -454,13 +454,23 @@ void __init mmu_partition_table_init(void)
 void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
                                   unsigned long dw1)
 {
+       unsigned long old = be64_to_cpu(partition_tb[lpid].patb0);
+
        partition_tb[lpid].patb0 = cpu_to_be64(dw0);
        partition_tb[lpid].patb1 = cpu_to_be64(dw1);
 
-       /* Global flush of TLBs and partition table caches for this lpid */
+       /*
+        * Global flush of TLBs and partition table caches for this lpid.
+        * The type of flush (hash or radix) depends on what the previous
+        * use of this partition ID was, not the new use.
+        */
        asm volatile("ptesync" : : : "memory");
-       asm volatile(PPC_TLBIE_5(%0,%1,2,0,0) : :
-                    "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
+       if (old & PATB_HR)
+               asm volatile(PPC_TLBIE_5(%0,%1,2,0,1) : :
+                            "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
+       else
+               asm volatile(PPC_TLBIE_5(%0,%1,2,0,0) : :
+                            "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
        asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 }
 EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);