]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - arch/powerpc/mm/slb.c
powerpc/pseries: Dump the SLB contents on SLB MCE errors.
[mirror_ubuntu-focal-kernel.git] / arch / powerpc / mm / slb.c
index 0b095fa540491845ca390be4f06a794f2c6f4c0f..e941189d9bd6386f087550507f69aba65c3b64cc 100644 (file)
@@ -70,7 +70,7 @@ static inline void slb_shadow_update(unsigned long ea, int ssize,
 
 static inline void slb_shadow_clear(enum slb_index index)
 {
-       WRITE_ONCE(get_slb_shadow()->save_area[index].esid, 0);
+       WRITE_ONCE(get_slb_shadow()->save_area[index].esid, cpu_to_be64(index));
 }
 
 static inline void create_shadowed_slbe(unsigned long ea, int ssize,
@@ -184,6 +184,76 @@ void slb_flush_and_rebolt(void)
        get_paca()->slb_cache_ptr = 0;
 }
 
+void slb_save_contents(struct slb_entry *slb_ptr)
+{
+       int i;
+       unsigned long e, v;
+
+       /* Save slb_cache_ptr value. */
+       get_paca()->slb_save_cache_ptr = get_paca()->slb_cache_ptr;
+
+       if (!slb_ptr)
+               return;
+
+       for (i = 0; i < mmu_slb_size; i++) {
+               asm volatile("slbmfee  %0,%1" : "=r" (e) : "r" (i));
+               asm volatile("slbmfev  %0,%1" : "=r" (v) : "r" (i));
+               slb_ptr->esid = e;
+               slb_ptr->vsid = v;
+               slb_ptr++;
+       }
+}
+
+void slb_dump_contents(struct slb_entry *slb_ptr)
+{
+       int i, n;
+       unsigned long e, v;
+       unsigned long llp;
+
+       if (!slb_ptr)
+               return;
+
+       pr_err("SLB contents of cpu 0x%x\n", smp_processor_id());
+       pr_err("Last SLB entry inserted at slot %lld\n", get_paca()->stab_rr);
+
+       for (i = 0; i < mmu_slb_size; i++) {
+               e = slb_ptr->esid;
+               v = slb_ptr->vsid;
+               slb_ptr++;
+
+               if (!e && !v)
+                       continue;
+
+               pr_err("%02d %016lx %016lx\n", i, e, v);
+
+               if (!(e & SLB_ESID_V)) {
+                       pr_err("\n");
+                       continue;
+               }
+               llp = v & SLB_VSID_LLP;
+               if (v & SLB_VSID_B_1T) {
+                       pr_err("  1T  ESID=%9lx  VSID=%13lx LLP:%3lx\n",
+                              GET_ESID_1T(e),
+                              (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, llp);
+               } else {
+                       pr_err(" 256M ESID=%9lx  VSID=%13lx LLP:%3lx\n",
+                              GET_ESID(e),
+                              (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT, llp);
+               }
+       }
+       pr_err("----------------------------------\n");
+
+       /* Dump slb cache entires as well. */
+       pr_err("SLB cache ptr value = %d\n", get_paca()->slb_save_cache_ptr);
+       pr_err("Valid SLB cache entries:\n");
+       n = min_t(int, get_paca()->slb_save_cache_ptr, SLB_CACHE_ENTRIES);
+       for (i = 0; i < n; i++)
+               pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
+       pr_err("Rest of SLB cache entries:\n");
+       for (i = n; i < SLB_CACHE_ENTRIES; i++)
+               pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]);
+}
+
 void slb_vmalloc_update(void)
 {
        unsigned long vflags;