Message ID | 1565796812-25870-1-git-send-email-bmeng.cn@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4] riscv: hmp: Add a command to show virtual memory mappings | expand |
On Wed, Aug 14, 2019 at 11:33 PM Bin Meng <bmeng.cn@gmail.com> wrote: > > This adds 'info mem' command for RISC-V, to show virtual memory > mappings that aids debugging. > > Rather than showing every valid PTE, the command compacts the > output by merging all contiguous physical address mappings into > one block and only shows the merged block mapping details. > > Signed-off-by: Bin Meng <bmeng.cn@gmail.com> > Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > Reviewed-by: Palmer Dabbelt <palmer@sifive.com> > > --- > > Changes in v4: > - restore to v2, that does not print all harts's PTE, since we > should switch to a cpu context via the 'cpu' command > > Changes in v3: > - print PTEs for all harts instead of just current hart > > Changes in v2: > - promote ppn to hwaddr when doing page table address calculation > > hmp-commands-info.hx | 2 +- > target/riscv/Makefile.objs | 4 + > target/riscv/monitor.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 234 insertions(+), 1 deletion(-) > create mode 100644 target/riscv/monitor.c > Ping? What's the status of this patch? Regards, Bin
On Sun, 18 Aug 2019 22:59:54 PDT (-0700), bmeng.cn@gmail.com wrote: > On Wed, Aug 14, 2019 at 11:33 PM Bin Meng <bmeng.cn@gmail.com> wrote: >> >> This adds 'info mem' command for RISC-V, to show virtual memory >> mappings that aids debugging. >> >> Rather than showing every valid PTE, the command compacts the >> output by merging all contiguous physical address mappings into >> one block and only shows the merged block mapping details. >> >> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> >> Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> >> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> >> >> --- >> >> Changes in v4: >> - restore to v2, that does not print all harts's PTE, since we >> should switch to a cpu context via the 'cpu' command >> >> Changes in v3: >> - print PTEs for all harts instead of just current hart >> >> Changes in v2: >> - promote ppn to hwaddr when doing page table address calculation >> >> hmp-commands-info.hx | 2 +- >> target/riscv/Makefile.objs | 4 + >> target/riscv/monitor.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 234 insertions(+), 1 deletion(-) >> create mode 100644 target/riscv/monitor.c >> > > Ping? > > What's the status of this patch? This is in my patch queue (for-master on github). I'm still a bit backed up on email, but when I get caught back up I'll send a PR.
Hi Palmer, On Wed, Aug 28, 2019 at 7:18 AM Palmer Dabbelt <palmer@sifive.com> wrote: > > On Sun, 18 Aug 2019 22:59:54 PDT (-0700), bmeng.cn@gmail.com wrote: > > On Wed, Aug 14, 2019 at 11:33 PM Bin Meng <bmeng.cn@gmail.com> wrote: > >> > >> This adds 'info mem' command for RISC-V, to show virtual memory > >> mappings that aids debugging. > >> > >> Rather than showing every valid PTE, the command compacts the > >> output by merging all contiguous physical address mappings into > >> one block and only shows the merged block mapping details. > >> > >> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> > >> Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > >> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> > >> > >> --- > >> > >> Changes in v4: > >> - restore to v2, that does not print all harts's PTE, since we > >> should switch to a cpu context via the 'cpu' command > >> > >> Changes in v3: > >> - print PTEs for all harts instead of just current hart > >> > >> Changes in v2: > >> - promote ppn to hwaddr when doing page table address calculation > >> > >> hmp-commands-info.hx | 2 +- > >> target/riscv/Makefile.objs | 4 + > >> target/riscv/monitor.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ > >> 3 files changed, 234 insertions(+), 1 deletion(-) > >> create mode 100644 target/riscv/monitor.c > >> > > > > Ping? > > > > What's the status of this patch? > > This is in my patch queue (for-master on github). I'm still a bit backed up on > email, but when I get caught back up I'll send a PR. I double checked your git repo, and found you applied an older version of this patch. Please drop that, and apply this v4 one. http://patchwork.ozlabs.org/patch/1147104/ Regards, Bin
On Tue, 27 Aug 2019 18:31:18 PDT (-0700), bmeng.cn@gmail.com wrote: > Hi Palmer, > > On Wed, Aug 28, 2019 at 7:18 AM Palmer Dabbelt <palmer@sifive.com> wrote: >> >> On Sun, 18 Aug 2019 22:59:54 PDT (-0700), bmeng.cn@gmail.com wrote: >> > On Wed, Aug 14, 2019 at 11:33 PM Bin Meng <bmeng.cn@gmail.com> wrote: >> >> >> >> This adds 'info mem' command for RISC-V, to show virtual memory >> >> mappings that aids debugging. >> >> >> >> Rather than showing every valid PTE, the command compacts the >> >> output by merging all contiguous physical address mappings into >> >> one block and only shows the merged block mapping details. >> >> >> >> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> >> >> Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> >> >> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> >> >> >> >> --- >> >> >> >> Changes in v4: >> >> - restore to v2, that does not print all harts's PTE, since we >> >> should switch to a cpu context via the 'cpu' command >> >> >> >> Changes in v3: >> >> - print PTEs for all harts instead of just current hart >> >> >> >> Changes in v2: >> >> - promote ppn to hwaddr when doing page table address calculation >> >> >> >> hmp-commands-info.hx | 2 +- >> >> target/riscv/Makefile.objs | 4 + >> >> target/riscv/monitor.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ >> >> 3 files changed, 234 insertions(+), 1 deletion(-) >> >> create mode 100644 target/riscv/monitor.c >> >> >> > >> > Ping? >> > >> > What's the status of this patch? >> >> This is in my patch queue (for-master on github). I'm still a bit backed up on >> email, but when I get caught back up I'll send a PR. > > I double checked your git repo, and found you applied an older version > of this patch. > > Please drop that, and apply this v4 one. > http://patchwork.ozlabs.org/patch/1147104/ Sorry about that, it should be fixed now.
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index c59444c..257ee7d 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -249,7 +249,7 @@ STEXI Show virtual to physical memory mappings. ETEXI -#if defined(TARGET_I386) +#if defined(TARGET_I386) || defined(TARGET_RISCV) { .name = "mem", .args_type = "", diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs index b1c79bc..a8ceccd 100644 --- a/target/riscv/Makefile.objs +++ b/target/riscv/Makefile.objs @@ -1,5 +1,9 @@ obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o +ifeq ($(CONFIG_SOFTMMU),y) +obj-y += monitor.o +endif + DECODETREE = $(SRC_PATH)/scripts/decodetree.py decode32-y = $(SRC_PATH)/target/riscv/insn32.decode diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c new file mode 100644 index 0000000..d725a7a --- /dev/null +++ b/target/riscv/monitor.c @@ -0,0 +1,229 @@ +/* + * QEMU monitor for RISC-V + * + * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com> + * + * RISC-V specific monitor commands implementation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "cpu_bits.h" +#include "monitor/monitor.h" +#include "monitor/hmp-target.h" + +#ifdef TARGET_RISCV64 +#define PTE_HEADER_FIELDS "vaddr paddr "\ + "size attr\n" +#define PTE_HEADER_DELIMITER "---------------- ---------------- "\ + "---------------- -------\n" +#else +#define PTE_HEADER_FIELDS "vaddr paddr size attr\n" +#define PTE_HEADER_DELIMITER "-------- ---------------- -------- -------\n" +#endif + +/* Perform linear address sign extension */ +static target_ulong addr_canonical(int va_bits, target_ulong addr) +{ +#ifdef TARGET_RISCV64 + if (addr & (1UL << (va_bits - 1))) { + addr |= (hwaddr)-(1L << va_bits); + } +#endif + + return addr; +} + +static void print_pte_header(Monitor *mon) +{ + monitor_printf(mon, PTE_HEADER_FIELDS); + monitor_printf(mon, PTE_HEADER_DELIMITER); +} + +static void print_pte(Monitor *mon, int va_bits, target_ulong vaddr, + hwaddr paddr, target_ulong size, int attr) +{ + /* santity check on vaddr */ + if (vaddr >= (1UL << va_bits)) { + return; + } + + if (!size) { + return; + } + + monitor_printf(mon, TARGET_FMT_lx " " TARGET_FMT_plx " " TARGET_FMT_lx + " %c%c%c%c%c%c%c\n", + addr_canonical(va_bits, vaddr), + paddr, size, + attr & PTE_R ? 'r' : '-', + attr & PTE_W ? 'w' : '-', + attr & PTE_X ? 'x' : '-', + attr & PTE_U ? 'u' : '-', + attr & PTE_G ? 'g' : '-', + attr & PTE_A ? 'a' : '-', + attr & PTE_D ? 'd' : '-'); +} + +static void walk_pte(Monitor *mon, hwaddr base, target_ulong start, + int level, int ptidxbits, int ptesize, int va_bits, + target_ulong *vbase, hwaddr *pbase, hwaddr *last_paddr, + target_ulong *last_size, int *last_attr) +{ + hwaddr pte_addr; + hwaddr paddr; + target_ulong pgsize; + target_ulong pte; + int ptshift; + int attr; + int idx; + + if (level < 0) { + return; + } + + ptshift = level * ptidxbits; + pgsize = 1UL << (PGSHIFT + ptshift); + + for (idx = 0; idx < (1UL << ptidxbits); idx++) { + pte_addr = base + idx * ptesize; + cpu_physical_memory_read(pte_addr, &pte, ptesize); + + paddr = (hwaddr)(pte >> PTE_PPN_SHIFT) << PGSHIFT; + attr = pte & 0xff; + + /* PTE has to be valid */ + if (attr & PTE_V) { + if (attr & (PTE_R | PTE_W | PTE_X)) { + /* + * A leaf PTE has been found + * + * If current PTE's permission bits differ from the last one, + * or current PTE's ppn does not make a contiguous physical + * address block together with the last one, print out the last + * contiguous mapped block details. + */ + if ((*last_attr != attr) || + (*last_paddr + *last_size != paddr)) { + print_pte(mon, va_bits, *vbase, *pbase, + *last_paddr + *last_size - *pbase, *last_attr); + + *vbase = start; + *pbase = paddr; + *last_attr = attr; + } + + *last_paddr = paddr; + *last_size = pgsize; + } else { + /* pointer to the next level of the page table */ + walk_pte(mon, paddr, start, level - 1, ptidxbits, ptesize, + va_bits, vbase, pbase, last_paddr, + last_size, last_attr); + } + } + + start += pgsize; + } + +} + +static void mem_info_svxx(Monitor *mon, CPUArchState *env) +{ + int levels, ptidxbits, ptesize, vm, va_bits; + hwaddr base; + target_ulong vbase; + hwaddr pbase; + hwaddr last_paddr; + target_ulong last_size; + int last_attr; + + base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT; + + vm = get_field(env->satp, SATP_MODE); + switch (vm) { + case VM_1_10_SV32: + levels = 2; + ptidxbits = 10; + ptesize = 4; + break; + case VM_1_10_SV39: + levels = 3; + ptidxbits = 9; + ptesize = 8; + break; + case VM_1_10_SV48: + levels = 4; + ptidxbits = 9; + ptesize = 8; + break; + case VM_1_10_SV57: + levels = 5; + ptidxbits = 9; + ptesize = 8; + break; + default: + g_assert_not_reached(); + break; + } + + /* calculate virtual address bits */ + va_bits = PGSHIFT + levels * ptidxbits; + + /* print header */ + print_pte_header(mon); + + vbase = -1; + pbase = -1; + last_paddr = -1; + last_size = 0; + last_attr = 0; + + /* walk page tables, starting from address 0 */ + walk_pte(mon, base, 0, levels - 1, ptidxbits, ptesize, va_bits, + &vbase, &pbase, &last_paddr, &last_size, &last_attr); + + /* don't forget the last one */ + print_pte(mon, va_bits, vbase, pbase, + last_paddr + last_size - pbase, last_attr); +} + +void hmp_info_mem(Monitor *mon, const QDict *qdict) +{ + CPUArchState *env; + + env = mon_get_cpu_env(); + if (!env) { + monitor_printf(mon, "No CPU available\n"); + return; + } + + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + monitor_printf(mon, "S-mode MMU unavailable\n"); + return; + } + + if (env->priv_ver < PRIV_VERSION_1_10_0) { + monitor_printf(mon, "Privileged mode < 1.10 unsupported\n"); + return; + } + + if (!(env->satp & SATP_MODE)) { + monitor_printf(mon, "No translation or protection\n"); + return; + } + + mem_info_svxx(mon, env); +}