Messages in this thread | | | Subject | Re: [PATCH] powerpc/mm: dump block address translation on book3s/32 | From | Christophe LEROY <> | Date | Thu, 15 Nov 2018 12:57:30 +0100 |
| |
Le 15/11/2018 à 12:46, Michael Ellerman a écrit : > Christophe Leroy <christophe.leroy@c-s.fr> writes: > >> This patch adds a debugfs file to dump block address translation: >> >> ~# cat /sys/kernel/debug/block_address_translation > > My instinct is it should be in /sys/kernel/debug/powerpc. But I guess > the other page table dump files are not.
Lol.
Looks like we have the same instinct ...
But you rejected my patch https://patchwork.ozlabs.org/patch/750426/ :)
> >> Instruction Block Address Translations: >> 0: - >> 1: - >> 2: 0xc0000000-0xcfffffff 0x00000000 Kernel EXEC coherent >> 3: 0xd0000000-0xdfffffff 0x10000000 Kernel EXEC coherent >> 4: - >> 5: - >> 6: - >> 7: - >> >> Data Block Address Translations: >> 0: - >> 1: - >> 2: 0xc0000000-0xcfffffff 0x00000000 Kernel RW coherent >> 3: 0xd0000000-0xdfffffff 0x10000000 Kernel RW coherent >> 4: - >> 5: - >> 6: - >> 7: - >> >> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> >> --- >> Tested on mpc8321 aka 603 >> Please review/test the 601 part >> >> arch/powerpc/mm/Makefile | 2 +- >> arch/powerpc/mm/dump_bats.c | 176 ++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 177 insertions(+), 1 deletion(-) >> create mode 100644 arch/powerpc/mm/dump_bats.c >> >> diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile >> index ca96e7be4d0e..2adad10b5856 100644 >> --- a/arch/powerpc/mm/Makefile >> +++ b/arch/powerpc/mm/Makefile >> @@ -47,7 +47,7 @@ ifdef CONFIG_PPC_PTDUMP >> obj-$(CONFIG_4xx) += dump_linuxpagetables-generic.o >> obj-$(CONFIG_PPC_8xx) += dump_linuxpagetables-8xx.o >> obj-$(CONFIG_PPC_BOOK3E_MMU) += dump_linuxpagetables-generic.o >> -obj-$(CONFIG_PPC_BOOK3S_32) += dump_linuxpagetables-generic.o >> +obj-$(CONFIG_PPC_BOOK3S_32) += dump_linuxpagetables-generic.o dump_bats.o > > BOOK3S_32 covers quite a lot of CPUs. > > But below the only check is that you're on 601 or 603. > > So is the 603 code going to work on all other BOOK3S_32 CPUs?
If I understand function setbat() correctly, it should.
See https://elixir.bootlin.com/linux/v4.20-rc1/source/arch/powerpc/mm/ppc_mmu_32.c#L115 Tell me if you see something I missed.
Christophe
> > cheers > >> diff --git a/arch/powerpc/mm/dump_bats.c b/arch/powerpc/mm/dump_bats.c >> new file mode 100644 >> index 000000000000..824a94ee9051 >> --- /dev/null >> +++ b/arch/powerpc/mm/dump_bats.c >> @@ -0,0 +1,176 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> +/* >> + * Copyright 2018, Christophe Leroy CS S.I. >> + * <christophe.leroy@c-s.fr> >> + * >> + * This dumps the content of BATS >> + */ >> + >> +#include <linux/debugfs.h> >> +#include <linux/fs.h> >> +#include <linux/hugetlb.h> >> +#include <linux/io.h> >> +#include <linux/mm.h> >> +#include <linux/sched.h> >> +#include <linux/seq_file.h> >> +#include <asm/fixmap.h> >> +#include <asm/pgtable.h> >> +#include <linux/const.h> >> +#include <asm/page.h> >> +#include <asm/pgalloc.h> >> + >> +#include <asm/book3s/32/mmu-hash.h> >> + >> +static char *pp_601(int k, int pp) >> +{ >> + if (pp == 0) >> + return k ? "NA" : "RWX"; >> + if (pp == 1) >> + return k ? "ROX" : "RWX"; >> + if (pp == 2) >> + return k ? "RWX" : "RWX"; >> + return k ? "ROX" : "ROX"; >> +} >> + >> +static void bat_show_601(struct seq_file *m, int idx, u32 lower, u32 upper) >> +{ >> + u32 blpi = upper & 0xfffe0000; >> + u32 k = (upper >> 2) & 3; >> + u32 pp = upper & 3; >> + u32 pbn = lower & 0xfffe0000; >> + u32 bsm = lower & 0x3ff; >> + u32 size = (bsm + 1) << 17; >> + >> + seq_printf(m, "%d: ", idx); >> + if (!(lower & 0x40)) { >> + seq_puts(m, " -\n"); >> + return; >> + } >> + >> + seq_printf(m, "0x%08x-0x%08x ", blpi, blpi + size - 1); >> + seq_printf(m, "0x%08x ", pbn); >> + >> + seq_printf(m, "Kernel %s User %s", pp_601(k & 2, pp), pp_601(k & 1, pp)); >> + >> + if (lower & _PAGE_WRITETHRU) >> + seq_puts(m, "write through "); >> + if (lower & _PAGE_NO_CACHE) >> + seq_puts(m, "no cache "); >> + if (lower & _PAGE_COHERENT) >> + seq_puts(m, "coherent "); >> + seq_puts(m, "\n"); >> +} >> + >> +#define BAT_SHOW_601(_m, _n, _l, _u) bat_show_601(_m, _n, mfspr(_l), mfspr(_u)) >> + >> +static int bats_show_601(struct seq_file *m, void *v) >> +{ >> + seq_puts(m, "Block Address Translation:\n"); >> + >> + BAT_SHOW_601(m, 0, SPRN_IBAT0L, SPRN_IBAT0U); >> + BAT_SHOW_601(m, 1, SPRN_IBAT1L, SPRN_IBAT1U); >> + BAT_SHOW_601(m, 2, SPRN_IBAT2L, SPRN_IBAT2U); >> + BAT_SHOW_601(m, 3, SPRN_IBAT3L, SPRN_IBAT3U); >> + >> + return 0; >> +} >> + >> +static void bat_show_603(struct seq_file *m, int idx, u32 lower, u32 upper, bool is_d) >> +{ >> + u32 bepi = upper & 0xfffe0000; >> + u32 bl = (upper >> 2) & 0x7ff; >> + u32 k = upper & 3; >> + u32 brpn = lower & 0xfffe0000; >> + u32 size = (bl + 1) << 17; >> + >> + seq_printf(m, "%d: ", idx); >> + if (k == 0) { >> + seq_puts(m, " -\n"); >> + return; >> + } >> + >> + seq_printf(m, "0x%08x-0x%08x ", bepi, bepi + size - 1); >> + seq_printf(m, "0x%08x ", brpn); >> + >> + if (k == 1) >> + seq_puts(m, "User "); >> + else if (k == 2) >> + seq_puts(m, "Kernel "); >> + else >> + seq_puts(m, "Kernel/User "); >> + >> + if (lower & BPP_RX) >> + seq_puts(m, is_d ? "RO " : "EXEC "); >> + else if (lower & BPP_RW) >> + seq_puts(m, is_d ? "RW " : "EXEC "); >> + else >> + seq_puts(m, is_d ? "NA " : "NX "); >> + >> + if (lower & _PAGE_WRITETHRU) >> + seq_puts(m, "write through "); >> + if (lower & _PAGE_NO_CACHE) >> + seq_puts(m, "no cache "); >> + if (lower & _PAGE_COHERENT) >> + seq_puts(m, "coherent "); >> + if (lower & _PAGE_GUARDED) >> + seq_puts(m, "guarded "); >> + seq_puts(m, "\n"); >> +} >> + >> +#define BAT_SHOW_603(_m, _n, _l, _u, _d) bat_show_603(_m, _n, mfspr(_l), mfspr(_u), _d) >> + >> +static int bats_show_603(struct seq_file *m, void *v) >> +{ >> + seq_puts(m, "Instruction Block Address Translation:\n"); >> + >> + BAT_SHOW_603(m, 0, SPRN_IBAT0L, SPRN_IBAT0U, false); >> + BAT_SHOW_603(m, 1, SPRN_IBAT1L, SPRN_IBAT1U, false); >> + BAT_SHOW_603(m, 2, SPRN_IBAT2L, SPRN_IBAT2U, false); >> + BAT_SHOW_603(m, 3, SPRN_IBAT3L, SPRN_IBAT3U, false); >> + if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) { >> + BAT_SHOW_603(m, 4, SPRN_IBAT4L, SPRN_IBAT4U, false); >> + BAT_SHOW_603(m, 5, SPRN_IBAT5L, SPRN_IBAT5U, false); >> + BAT_SHOW_603(m, 6, SPRN_IBAT6L, SPRN_IBAT6U, false); >> + BAT_SHOW_603(m, 7, SPRN_IBAT7L, SPRN_IBAT7U, false); >> + } >> + >> + seq_puts(m, "\nData Block Address Translation:\n"); >> + >> + BAT_SHOW_603(m, 0, SPRN_DBAT0L, SPRN_DBAT0U, true); >> + BAT_SHOW_603(m, 1, SPRN_DBAT1L, SPRN_DBAT1U, true); >> + BAT_SHOW_603(m, 2, SPRN_DBAT2L, SPRN_DBAT2U, true); >> + BAT_SHOW_603(m, 3, SPRN_DBAT3L, SPRN_DBAT3U, true); >> + if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) { >> + BAT_SHOW_603(m, 4, SPRN_DBAT4L, SPRN_DBAT4U, true); >> + BAT_SHOW_603(m, 5, SPRN_DBAT5L, SPRN_DBAT5U, true); >> + BAT_SHOW_603(m, 6, SPRN_DBAT6L, SPRN_DBAT6U, true); >> + BAT_SHOW_603(m, 7, SPRN_DBAT7L, SPRN_DBAT7U, true); >> + } >> + >> + return 0; >> +} >> + >> +static int bats_open(struct inode *inode, struct file *file) >> +{ >> + if (PVR_VER(mfspr(SPRN_PVR)) == 1) >> + return single_open(file, bats_show_601, NULL); >> + >> + return single_open(file, bats_show_603, NULL); >> +} >> + >> +static const struct file_operations bats_fops = { >> + .open = bats_open, >> + .read = seq_read, >> + .llseek = seq_lseek, >> + .release = single_release, >> +}; >> + >> +static int bats_init(void) >> +{ >> + struct dentry *debugfs_file; >> + >> + debugfs_file = debugfs_create_file("block_address_translation", 0400, >> + NULL, NULL, &bats_fops); >> + return debugfs_file ? 0 : -ENOMEM; >> +} >> +device_initcall(bats_init); >> -- >> 2.13.3
| |