1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2018, Christophe Leroy CS S.I.
4 * <christophe.leroy@c-s.fr>
6 * This dumps the content of BATS
9 #include <linux/pgtable.h>
10 #include <asm/debugfs.h>
11 #include <asm/cpu_has_feature.h>
15 static char *pp_601(int k
, int pp
)
18 return k
? " " : "rwx";
20 return k
? "r x" : "rwx";
26 static void bat_show_601(struct seq_file
*m
, int idx
, u32 lower
, u32 upper
)
28 u32 blpi
= upper
& 0xfffe0000;
29 u32 k
= (upper
>> 2) & 3;
31 phys_addr_t pbn
= PHYS_BAT_ADDR(lower
);
32 u32 bsm
= lower
& 0x3ff;
33 u32 size
= (bsm
+ 1) << 17;
35 seq_printf(m
, "%d: ", idx
);
36 if (!(lower
& 0x40)) {
41 seq_printf(m
, "0x%08x-0x%08x ", blpi
, blpi
+ size
- 1);
42 #ifdef CONFIG_PHYS_64BIT
43 seq_printf(m
, "0x%016llx ", pbn
);
45 seq_printf(m
, "0x%08x ", pbn
);
47 pt_dump_size(m
, size
);
49 seq_printf(m
, "Kernel %s User %s", pp_601(k
& 2, pp
), pp_601(k
& 1, pp
));
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 " : " ");
57 #define BAT_SHOW_601(_m, _n, _l, _u) bat_show_601(_m, _n, mfspr(_l), mfspr(_u))
59 static int bats_show_601(struct seq_file
*m
, void *v
)
61 seq_puts(m
, "---[ Block Address Translation ]---\n");
63 BAT_SHOW_601(m
, 0, SPRN_IBAT0L
, SPRN_IBAT0U
);
64 BAT_SHOW_601(m
, 1, SPRN_IBAT1L
, SPRN_IBAT1U
);
65 BAT_SHOW_601(m
, 2, SPRN_IBAT2L
, SPRN_IBAT2U
);
66 BAT_SHOW_601(m
, 3, SPRN_IBAT3L
, SPRN_IBAT3U
);
71 static void bat_show_603(struct seq_file
*m
, int idx
, u32 lower
, u32 upper
, bool is_d
)
73 u32 bepi
= upper
& 0xfffe0000;
74 u32 bl
= (upper
>> 2) & 0x7ff;
76 phys_addr_t brpn
= PHYS_BAT_ADDR(lower
);
77 u32 size
= (bl
+ 1) << 17;
79 seq_printf(m
, "%d: ", idx
);
85 seq_printf(m
, "0x%08x-0x%08x ", bepi
, bepi
+ size
- 1);
86 #ifdef CONFIG_PHYS_64BIT
87 seq_printf(m
, "0x%016llx ", brpn
);
89 seq_printf(m
, "0x%08x ", brpn
);
91 pt_dump_size(m
, size
);
96 seq_puts(m
, "Kernel ");
98 seq_puts(m
, "Kernel/User ");
101 seq_puts(m
, is_d
? "r " : " x ");
102 else if (lower
& BPP_RW
)
103 seq_puts(m
, is_d
? "rw " : " x ");
105 seq_puts(m
, is_d
? " " : " ");
107 seq_puts(m
, lower
& _PAGE_WRITETHRU
? "w " : " ");
108 seq_puts(m
, lower
& _PAGE_NO_CACHE
? "i " : " ");
109 seq_puts(m
, lower
& _PAGE_COHERENT
? "m " : " ");
110 seq_puts(m
, lower
& _PAGE_GUARDED
? "g " : " ");
114 #define BAT_SHOW_603(_m, _n, _l, _u, _d) bat_show_603(_m, _n, mfspr(_l), mfspr(_u), _d)
116 static int bats_show_603(struct seq_file
*m
, void *v
)
118 seq_puts(m
, "---[ Instruction Block Address Translation ]---\n");
120 BAT_SHOW_603(m
, 0, SPRN_IBAT0L
, SPRN_IBAT0U
, false);
121 BAT_SHOW_603(m
, 1, SPRN_IBAT1L
, SPRN_IBAT1U
, false);
122 BAT_SHOW_603(m
, 2, SPRN_IBAT2L
, SPRN_IBAT2U
, false);
123 BAT_SHOW_603(m
, 3, SPRN_IBAT3L
, SPRN_IBAT3U
, false);
124 if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS
)) {
125 BAT_SHOW_603(m
, 4, SPRN_IBAT4L
, SPRN_IBAT4U
, false);
126 BAT_SHOW_603(m
, 5, SPRN_IBAT5L
, SPRN_IBAT5U
, false);
127 BAT_SHOW_603(m
, 6, SPRN_IBAT6L
, SPRN_IBAT6U
, false);
128 BAT_SHOW_603(m
, 7, SPRN_IBAT7L
, SPRN_IBAT7U
, false);
131 seq_puts(m
, "\n---[ Data Block Address Translation ]---\n");
133 BAT_SHOW_603(m
, 0, SPRN_DBAT0L
, SPRN_DBAT0U
, true);
134 BAT_SHOW_603(m
, 1, SPRN_DBAT1L
, SPRN_DBAT1U
, true);
135 BAT_SHOW_603(m
, 2, SPRN_DBAT2L
, SPRN_DBAT2U
, true);
136 BAT_SHOW_603(m
, 3, SPRN_DBAT3L
, SPRN_DBAT3U
, true);
137 if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS
)) {
138 BAT_SHOW_603(m
, 4, SPRN_DBAT4L
, SPRN_DBAT4U
, true);
139 BAT_SHOW_603(m
, 5, SPRN_DBAT5L
, SPRN_DBAT5U
, true);
140 BAT_SHOW_603(m
, 6, SPRN_DBAT6L
, SPRN_DBAT6U
, true);
141 BAT_SHOW_603(m
, 7, SPRN_DBAT7L
, SPRN_DBAT7U
, true);
147 static int bats_open(struct inode
*inode
, struct file
*file
)
149 if (IS_ENABLED(CONFIG_PPC_BOOK3S_601
))
150 return single_open(file
, bats_show_601
, NULL
);
152 return single_open(file
, bats_show_603
, NULL
);
155 static const struct file_operations bats_fops
= {
159 .release
= single_release
,
162 static int __init
bats_init(void)
164 debugfs_create_file("block_address_translation", 0400,
165 powerpc_debugfs_root
, NULL
, &bats_fops
);
168 device_initcall(bats_init
);