1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018, Christophe Leroy CS S.I. 4 * <christophe.leroy@c-s.fr> 5 * 6 * This dumps the content of BATS 7 */ 8 9 #include <linux/pgtable.h> 10 #include <asm/debugfs.h> 11 #include <asm/cpu_has_feature.h> 12 13 #include "ptdump.h" 14 15 static void bat_show_603(struct seq_file *m, int idx, u32 lower, u32 upper, bool is_d) 16 { 17 u32 bepi = upper & 0xfffe0000; 18 u32 bl = (upper >> 2) & 0x7ff; 19 u32 k = upper & 3; 20 phys_addr_t brpn = PHYS_BAT_ADDR(lower); 21 u32 size = (bl + 1) << 17; 22 23 seq_printf(m, "%d: ", idx); 24 if (k == 0) { 25 seq_puts(m, " -\n"); 26 return; 27 } 28 29 seq_printf(m, "0x%08x-0x%08x ", bepi, bepi + size - 1); 30 #ifdef CONFIG_PHYS_64BIT 31 seq_printf(m, "0x%016llx ", brpn); 32 #else 33 seq_printf(m, "0x%08x ", brpn); 34 #endif 35 pt_dump_size(m, size); 36 37 if (k == 1) 38 seq_puts(m, "User "); 39 else if (k == 2) 40 seq_puts(m, "Kernel "); 41 else 42 seq_puts(m, "Kernel/User "); 43 44 if (lower & BPP_RX) 45 seq_puts(m, is_d ? "r " : " x "); 46 else if (lower & BPP_RW) 47 seq_puts(m, is_d ? "rw " : " x "); 48 else 49 seq_puts(m, is_d ? " " : " "); 50 51 seq_puts(m, lower & _PAGE_WRITETHRU ? "w " : " "); 52 seq_puts(m, lower & _PAGE_NO_CACHE ? "i " : " "); 53 seq_puts(m, lower & _PAGE_COHERENT ? "m " : " "); 54 seq_puts(m, lower & _PAGE_GUARDED ? "g " : " "); 55 seq_puts(m, "\n"); 56 } 57 58 #define BAT_SHOW_603(_m, _n, _l, _u, _d) bat_show_603(_m, _n, mfspr(_l), mfspr(_u), _d) 59 60 static int bats_show_603(struct seq_file *m, void *v) 61 { 62 seq_puts(m, "---[ Instruction Block Address Translation ]---\n"); 63 64 BAT_SHOW_603(m, 0, SPRN_IBAT0L, SPRN_IBAT0U, false); 65 BAT_SHOW_603(m, 1, SPRN_IBAT1L, SPRN_IBAT1U, false); 66 BAT_SHOW_603(m, 2, SPRN_IBAT2L, SPRN_IBAT2U, false); 67 BAT_SHOW_603(m, 3, SPRN_IBAT3L, SPRN_IBAT3U, false); 68 if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) { 69 BAT_SHOW_603(m, 4, SPRN_IBAT4L, SPRN_IBAT4U, false); 70 BAT_SHOW_603(m, 5, SPRN_IBAT5L, SPRN_IBAT5U, false); 71 BAT_SHOW_603(m, 6, SPRN_IBAT6L, SPRN_IBAT6U, false); 72 BAT_SHOW_603(m, 7, SPRN_IBAT7L, SPRN_IBAT7U, false); 73 } 74 75 seq_puts(m, "\n---[ Data Block Address Translation ]---\n"); 76 77 BAT_SHOW_603(m, 0, SPRN_DBAT0L, SPRN_DBAT0U, true); 78 BAT_SHOW_603(m, 1, SPRN_DBAT1L, SPRN_DBAT1U, true); 79 BAT_SHOW_603(m, 2, SPRN_DBAT2L, SPRN_DBAT2U, true); 80 BAT_SHOW_603(m, 3, SPRN_DBAT3L, SPRN_DBAT3U, true); 81 if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) { 82 BAT_SHOW_603(m, 4, SPRN_DBAT4L, SPRN_DBAT4U, true); 83 BAT_SHOW_603(m, 5, SPRN_DBAT5L, SPRN_DBAT5U, true); 84 BAT_SHOW_603(m, 6, SPRN_DBAT6L, SPRN_DBAT6U, true); 85 BAT_SHOW_603(m, 7, SPRN_DBAT7L, SPRN_DBAT7U, true); 86 } 87 88 return 0; 89 } 90 91 static int bats_open(struct inode *inode, struct file *file) 92 { 93 return single_open(file, bats_show_603, NULL); 94 } 95 96 static const struct file_operations bats_fops = { 97 .open = bats_open, 98 .read = seq_read, 99 .llseek = seq_lseek, 100 .release = single_release, 101 }; 102 103 static int __init bats_init(void) 104 { 105 debugfs_create_file("block_address_translation", 0400, 106 powerpc_debugfs_root, NULL, &bats_fops); 107 return 0; 108 } 109 device_initcall(bats_init); 110