Merge tag 'powerpc-4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 Jun 2016 21:20:22 +0000 (14:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 Jun 2016 21:20:22 +0000 (14:20 -0700)
Pull powerpc fixes from Michael Ellerman:
 - Handle RTAS delay requests in configure_bridge from Russell Currey
 - Refactor the configure_bridge RTAS tokens from Russell Currey
 - Fix definition of SIAR and SDAR registers from Thomas Huth
 - Use privileged SPR number for MMCR2 from Thomas Huth
 - Update LPCR only if it is powernv from Aneesh Kumar K.V
 - Fix the reference bit update when handling hash fault from Aneesh
   Kumar K.V
 - Add missing tlb flush from Aneesh Kumar K.V
 - Add POWER8NVL support to ibm,client-architecture-support call from
   Thomas Huth

* tag 'powerpc-4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/pseries: Add POWER8NVL support to ibm,client-architecture-support call
  powerpc/mm/radix: Add missing tlb flush
  powerpc/mm/hash: Fix the reference bit update when handling hash fault
  powerpc/mm/radix: Update LPCR only if it is powernv
  powerpc: Use privileged SPR number for MMCR2
  powerpc: Fix definition of SIAR and SDAR registers
  powerpc/pseries/eeh: Refactor the configure_bridge RTAS tokens
  powerpc/pseries/eeh: Handle RTAS delay requests in configure_bridge

arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/prom_init.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/platforms/pseries/eeh_pseries.c

index c1e82e968506302dbbf81ddf4345fc4bf26b15c5..a0948f40bc7bc96d60cf15d93fd252ef6d3d01f4 100644 (file)
 #define   MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
 #define   MMCR0_FCHV   0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1     798
-#define SPRN_MMCR2     769
+#define SPRN_MMCR2     785
 #define SPRN_MMCRA     0x312
 #define   MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SDAR_DCACHE_MISS 0x40000000UL
 #define SPRN_PMC6      792
 #define SPRN_PMC7      793
 #define SPRN_PMC8      794
-#define SPRN_SIAR      780
-#define SPRN_SDAR      781
 #define SPRN_SIER      784
 #define   SIER_SIPR            0x2000000       /* Sampled MSR_PR */
 #define   SIER_SIHV            0x1000000       /* Sampled MSR_HV */
 #define   SIER_SIAR_VALID      0x0400000       /* SIAR contents valid */
 #define   SIER_SDAR_VALID      0x0200000       /* SDAR contents valid */
+#define SPRN_SIAR      796
+#define SPRN_SDAR      797
 #define SPRN_TACR      888
 #define SPRN_TCSCR     889
 #define SPRN_CSIGR     890
index da5192590c445f89c2a8466128b570c87a133470..ccd2037c797f9e48c82b545ed4eb5febf03d95f6 100644 (file)
@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
        W(0xffff0000), W(0x003e0000),   /* POWER6 */
        W(0xffff0000), W(0x003f0000),   /* POWER7 */
        W(0xffff0000), W(0x004b0000),   /* POWER8E */
+       W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
        W(0xffff0000), W(0x004d0000),   /* POWER8 */
        W(0xffffffff), W(0x0f000004),   /* all 2.07-compliant */
        W(0xffffffff), W(0x0f000003),   /* all 2.06-compliant */
index 59268969a0bc7b0d02e8c10b28f5b214f6209006..b2740c67e1729628045dcc41fe50ecada6bac3ae 100644 (file)
@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = {
        },
 };
 
+/*
+ * 'R' and 'C' update notes:
+ *  - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
+ *     create writeable HPTEs without C set, because the hcall H_PROTECT
+ *     that we use in that case will not update C
+ *  - The above is however not a problem, because we also don't do that
+ *     fancy "no flush" variant of eviction and we use H_REMOVE which will
+ *     do the right thing and thus we don't have the race I described earlier
+ *
+ *    - Under bare metal,  we do have the race, so we need R and C set
+ *    - We make sure R is always set and never lost
+ *    - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
+ */
 unsigned long htab_convert_pte_flags(unsigned long pteflags)
 {
        unsigned long rflags = 0;
@@ -186,9 +199,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
                        rflags |= 0x1;
        }
        /*
-        * Always add "C" bit for perf. Memory coherence is always enabled
+        * We can't allow hardware to update hpte bits. Hence always
+        * set 'R' bit and set 'C' if it is a write fault
+        * Memory coherence is always enabled
         */
-       rflags |=  HPTE_R_C | HPTE_R_M;
+       rflags |=  HPTE_R_R | HPTE_R_M;
+
+       if (pteflags & _PAGE_DIRTY)
+               rflags |= HPTE_R_C;
        /*
         * Add in WIG bits
         */
index eb44511447462e41c36ce25b03be1026edca4a56..670318766545c6fb029e4acfb7711be5ca7fe90d 100644 (file)
@@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
        changed = !pmd_same(*(pmdp), entry);
        if (changed) {
                __ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
-               /*
-                * Since we are not supporting SW TLB systems, we don't
-                * have any thing similar to flush_tlb_page_nohash()
-                */
+               flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
        }
        return changed;
 }
index 18b2c11604fa7804f7e7101a9a4dee9204f5f62e..c939e6e57a9e83eda7918dc7e279d879c7fe432b 100644 (file)
@@ -296,11 +296,6 @@ found:
 void __init radix__early_init_mmu(void)
 {
        unsigned long lpcr;
-       /*
-        * setup LPCR UPRT based on mmu_features
-        */
-       lpcr = mfspr(SPRN_LPCR);
-       mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
 
 #ifdef CONFIG_PPC_64K_PAGES
        /* PAGE_SIZE mappings */
@@ -343,8 +338,11 @@ void __init radix__early_init_mmu(void)
        __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
 
        radix_init_page_sizes();
-       if (!firmware_has_feature(FW_FEATURE_LPAR))
+       if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+               lpcr = mfspr(SPRN_LPCR);
+               mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
                radix_init_partition_table();
+       }
 
        radix_init_pgtable();
 }
@@ -353,16 +351,15 @@ void radix__early_init_mmu_secondary(void)
 {
        unsigned long lpcr;
        /*
-        * setup LPCR UPRT based on mmu_features
+        * update partition table control register and UPRT
         */
-       lpcr = mfspr(SPRN_LPCR);
-       mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
-       /*
-        * update partition table control register, 64 K size.
-        */
-       if (!firmware_has_feature(FW_FEATURE_LPAR))
+       if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+               lpcr = mfspr(SPRN_LPCR);
+               mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
+
                mtspr(SPRN_PTCR,
                      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+       }
 }
 
 void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
index ac3ffd97e0596626a1c72c930d76ac994c683b82..3998e0f9a03bc89e51ab041d87836a4db587933b 100644 (file)
@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2;
 static int ibm_slot_error_detail;
 static int ibm_get_config_addr_info;
 static int ibm_get_config_addr_info2;
-static int ibm_configure_bridge;
 static int ibm_configure_pe;
 
 /*
@@ -81,7 +80,14 @@ static int pseries_eeh_init(void)
        ibm_get_config_addr_info2       = rtas_token("ibm,get-config-addr-info2");
        ibm_get_config_addr_info        = rtas_token("ibm,get-config-addr-info");
        ibm_configure_pe                = rtas_token("ibm,configure-pe");
-       ibm_configure_bridge            = rtas_token("ibm,configure-bridge");
+
+       /*
+        * ibm,configure-pe and ibm,configure-bridge have the same semantics,
+        * however ibm,configure-pe can be faster.  If we can't find
+        * ibm,configure-pe then fall back to using ibm,configure-bridge.
+        */
+       if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE)
+               ibm_configure_pe        = rtas_token("ibm,configure-bridge");
 
        /*
         * Necessary sanity check. We needn't check "get-config-addr-info"
@@ -93,8 +99,7 @@ static int pseries_eeh_init(void)
            (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
             ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) ||
            ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE       ||
-           (ibm_configure_pe == RTAS_UNKNOWN_SERVICE           &&
-            ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) {
+           ibm_configure_pe == RTAS_UNKNOWN_SERVICE) {
                pr_info("EEH functionality not supported\n");
                return -EINVAL;
        }
@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
 {
        int config_addr;
        int ret;
+       /* Waiting 0.2s maximum before skipping configuration */
+       int max_wait = 200;
 
        /* Figure out the PE address */
        config_addr = pe->config_addr;
        if (pe->addr)
                config_addr = pe->addr;
 
-       /* Use new configure-pe function, if supported */
-       if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+       while (max_wait > 0) {
                ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
                                config_addr, BUID_HI(pe->phb->buid),
                                BUID_LO(pe->phb->buid));
-       } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
-               ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-                               config_addr, BUID_HI(pe->phb->buid),
-                               BUID_LO(pe->phb->buid));
-       } else {
-               return -EFAULT;
-       }
 
-       if (ret)
-               pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
-                       __func__, pe->phb->global_number, pe->addr, ret);
+               if (!ret)
+                       return ret;
+
+               /*
+                * If RTAS returns a delay value that's above 100ms, cut it
+                * down to 100ms in case firmware made a mistake.  For more
+                * on how these delay values work see rtas_busy_delay_time
+                */
+               if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+                   ret <= RTAS_EXTENDED_DELAY_MAX)
+                       ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+               max_wait -= rtas_busy_delay_time(ret);
+
+               if (max_wait < 0)
+                       break;
+
+               rtas_busy_delay(ret);
+       }
 
+       pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+               __func__, pe->phb->global_number, pe->addr, ret);
        return ret;
 }