Print this page
9210 remove KMDB branch debugging support
9211 ::crregs could do with cr2/cr3 support
9209 ::ttrace should be able to filter by thread
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Joyent, Inc.
  24  */
  25 
  26 #include <mdb/mdb_modapi.h>
  27 #include <mdb/mdb_ctf.h>
  28 #include <sys/cpuvar.h>
  29 #include <sys/systm.h>
  30 #include <sys/traptrace.h>
  31 #include <sys/x_call.h>
  32 #include <sys/xc_levels.h>
  33 #include <sys/avintr.h>
  34 #include <sys/systm.h>
  35 #include <sys/trap.h>
  36 #include <sys/mutex.h>
  37 #include <sys/mutex_impl.h>
  38 #include "i86mmu.h"
  39 #include "unix_sup.h"
  40 #include <sys/apix.h>
  41 #include <sys/x86_archext.h>
  42 #include <sys/bitmap.h>
  43 #include <sys/controlregs.h>


 392 }
 393 
 394 static struct {
 395         uchar_t t_marker;
 396         char *t_name;
 397         int (*t_hdlr)(trap_trace_rec_t *);
 398 } ttrace_hdlr[] = {
 399         { TT_SYSCALL, "sysc", ttrace_syscall },
 400         { TT_SYSENTER, "syse", ttrace_syscall },
 401         { TT_SYSC, "asys", ttrace_syscall },
 402         { TT_SYSC64, "sc64", ttrace_syscall },
 403         { TT_INTERRUPT, "intr", ttrace_interrupt },
 404         { TT_TRAP, "trap", ttrace_trap },
 405         { TT_EVENT, "evnt", ttrace_trap },
 406         { 0, NULL, NULL }
 407 };
 408 
 409 typedef struct ttrace_dcmd {
 410         processorid_t ttd_cpu;
 411         uint_t ttd_extended;

 412         trap_trace_ctl_t ttd_ttc[NCPU];
 413 } ttrace_dcmd_t;
 414 
 415 #if defined(__amd64)
 416 
 417 #define DUMP(reg) #reg, regs->r_##reg
 418 #define THREEREGS       "         %3s: %16lx %3s: %16lx %3s: %16lx\n"
 419 
 420 static void
 421 ttrace_dumpregs(trap_trace_rec_t *rec)
 422 {
 423         struct regs *regs = &rec->ttr_regs;
 424 
 425         mdb_printf(THREEREGS, DUMP(rdi), DUMP(rsi), DUMP(rdx));
 426         mdb_printf(THREEREGS, DUMP(rcx), DUMP(r8), DUMP(r9));
 427         mdb_printf(THREEREGS, DUMP(rax), DUMP(rbx), DUMP(rbp));
 428         mdb_printf(THREEREGS, DUMP(r10), DUMP(r11), DUMP(r12));
 429         mdb_printf(THREEREGS, DUMP(r13), DUMP(r14), DUMP(r15));
 430         mdb_printf(THREEREGS, DUMP(ds), DUMP(es), DUMP(fs));
 431         mdb_printf(THREEREGS, DUMP(gs), "trp", regs->r_trapno, DUMP(err));


 461 {
 462         struct regs *regs = &rec->ttr_regs;
 463         processorid_t cpu = -1, i;
 464 
 465         for (i = 0; i < NCPU; i++) {
 466                 if (addr >= dcmd->ttd_ttc[i].ttc_first &&
 467                     addr < dcmd->ttd_ttc[i].ttc_limit) {
 468                         cpu = i;
 469                         break;
 470                 }
 471         }
 472 
 473         if (cpu == -1) {
 474                 mdb_warn("couldn't find %p in any trap trace ctl\n", addr);
 475                 return (WALK_ERR);
 476         }
 477 
 478         if (dcmd->ttd_cpu != -1 && cpu != dcmd->ttd_cpu)
 479                 return (WALK_NEXT);
 480 




 481         mdb_printf("%3d %15llx ", cpu, rec->ttr_stamp);
 482 
 483         for (i = 0; ttrace_hdlr[i].t_hdlr != NULL; i++) {
 484                 if (rec->ttr_marker != ttrace_hdlr[i].t_marker)
 485                         continue;
 486                 mdb_printf("%4s ", ttrace_hdlr[i].t_name);
 487                 if (ttrace_hdlr[i].t_hdlr(rec) == -1)
 488                         return (WALK_ERR);
 489         }
 490 
 491         mdb_printf(" %a\n", regs->r_pc);
 492 
 493         if (dcmd->ttd_extended == FALSE)
 494                 return (WALK_NEXT);
 495 
 496         if (rec->ttr_marker == TT_INTERRUPT)
 497                 ttrace_intr_detail(rec);
 498         else
 499                 ttrace_dumpregs(rec);
 500 


 520 {
 521         ttrace_dcmd_t dcmd;
 522         trap_trace_ctl_t *ttc = dcmd.ttd_ttc;
 523         trap_trace_rec_t rec;
 524         size_t ttc_size = sizeof (trap_trace_ctl_t) * NCPU;
 525 
 526         if (!ttrace_ttr_size_check())
 527                 return (WALK_ERR);
 528 
 529         bzero(&dcmd, sizeof (dcmd));
 530         dcmd.ttd_cpu = -1;
 531         dcmd.ttd_extended = FALSE;
 532 
 533         if (mdb_readsym(ttc, ttc_size, "trap_trace_ctl") == -1) {
 534                 mdb_warn("symbol 'trap_trace_ctl' not found; "
 535                     "non-TRAPTRACE kernel?\n");
 536                 return (DCMD_ERR);
 537         }
 538 
 539         if (mdb_getopts(argc, argv,
 540             'x', MDB_OPT_SETBITS, TRUE, &dcmd.ttd_extended, NULL) != argc)

 541                 return (DCMD_USAGE);
 542 
 543         if (DCMD_HDRSPEC(flags)) {
 544                 mdb_printf("%3s %15s %4s %2s %-*s%s\n", "CPU",
 545                     "TIMESTAMP", "TYPE", "Vec", TT_HDLR_WIDTH, "HANDLER",
 546                     " EIP");
 547         }
 548 
 549         if (flags & DCMD_ADDRSPEC) {
 550                 if (addr >= NCPU) {
 551                         if (mdb_vread(&rec, sizeof (rec), addr) == -1) {
 552                                 mdb_warn("couldn't read trap trace record "
 553                                     "at %p", addr);
 554                                 return (DCMD_ERR);
 555                         }
 556 
 557                         if (ttrace_walk(addr, &rec, &dcmd) == WALK_ERR)
 558                                 return (DCMD_ERR);
 559 
 560                         return (DCMD_OK);


 869                         return (DCMD_ERR);
 870                 }
 871 
 872                 if (mdb_readstr(name, sizeof (name), nptr) == -1) {
 873                         mdb_warn("failed to read feature %d", ii);
 874                         mdb_free(fset, sz);
 875                         return (DCMD_ERR);
 876                 }
 877                 mdb_printf("%s\n", name);
 878         }
 879 
 880         mdb_free(fset, sz);
 881         return (DCMD_OK);
 882 }
 883 
 884 #ifdef _KMDB
 885 /* ARGSUSED */
 886 static int
 887 crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 888 {
 889         ulong_t cr0, cr4;
 890         static const mdb_bitmask_t cr0_flag_bits[] = {
 891                 { "PE",         CR0_PE,         CR0_PE },
 892                 { "MP",         CR0_MP,         CR0_MP },
 893                 { "EM",         CR0_EM,         CR0_EM },
 894                 { "TS",         CR0_TS,         CR0_TS },
 895                 { "ET",         CR0_ET,         CR0_ET },
 896                 { "NE",         CR0_NE,         CR0_NE },
 897                 { "WP",         CR0_WP,         CR0_WP },
 898                 { "AM",         CR0_AM,         CR0_AM },
 899                 { "NW",         CR0_NW,         CR0_NW },
 900                 { "CD",         CR0_CD,         CR0_CD },
 901                 { "PG",         CR0_PG,         CR0_PG },
 902                 { NULL,         0,              0 }
 903         };
 904 






 905         static const mdb_bitmask_t cr4_flag_bits[] = {
 906                 { "VME",        CR4_VME,        CR4_VME },
 907                 { "PVI",        CR4_PVI,        CR4_PVI },
 908                 { "TSD",        CR4_TSD,        CR4_TSD },
 909                 { "DE",         CR4_DE,         CR4_DE },
 910                 { "PSE",        CR4_PSE,        CR4_PSE },
 911                 { "PAE",        CR4_PAE,        CR4_PAE },
 912                 { "MCE",        CR4_MCE,        CR4_MCE },
 913                 { "PGE",        CR4_PGE,        CR4_PGE },
 914                 { "PCE",        CR4_PCE,        CR4_PCE },
 915                 { "OSFXSR",     CR4_OSFXSR,     CR4_OSFXSR },
 916                 { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT },
 917                 { "VMXE",       CR4_VMXE,       CR4_VMXE },
 918                 { "SMXE",       CR4_SMXE,       CR4_SMXE },

 919                 { "OSXSAVE",    CR4_OSXSAVE,    CR4_OSXSAVE },
 920                 { "SMEP",       CR4_SMEP,       CR4_SMEP },
 921                 { "SMAP",       CR4_SMAP,       CR4_SMAP },
 922                 { NULL,         0,              0 }
 923         };
 924 
 925         cr0 = kmdb_unix_getcr0();


 926         cr4 = kmdb_unix_getcr4();
 927         mdb_printf("%%cr0 = 0x%08x <%b>\n", cr0, cr0, cr0_flag_bits);










 928         mdb_printf("%%cr4 = 0x%08x <%b>\n", cr4, cr4, cr4_flag_bits);

 929         return (DCMD_OK);
 930 }
 931 #endif
 932 
 933 static const mdb_dcmd_t dcmds[] = {
 934         { "gate_desc", ":", "dump a gate descriptor", gate_desc },
 935         { "idt", ":[-v]", "dump an IDT", idt },
 936         { "ttrace", "[-x]", "dump trap trace buffers", ttrace },
 937         { "vatopfn", ":[-a as]", "translate address to physical page",
 938             va2pfn_dcmd },
 939         { "report_maps", ":[-m]",
 940             "Given PFN, report mappings / page table usage",
 941             report_maps_dcmd, report_maps_help },
 942         { "htables", "", "Given hat_t *, lists all its htable_t * values",
 943             htables_dcmd, htables_help },
 944         { "ptable", ":[-m]", "Given PFN, dump contents of a page table",
 945             ptable_dcmd, ptable_help },
 946         { "pte", ":[-p XXXXX] [-l N]", "print human readable page table entry",
 947             pte_dcmd },
 948         { "pfntomfn", ":", "convert physical page to hypervisor machine page",
 949             pfntomfn_dcmd },
 950         { "mfntopfn", ":", "convert hypervisor machine page to physical page",
 951             mfntopfn_dcmd },
 952         { "memseg_list", ":", "show memseg list", memseg_list },
 953         { "scalehrtime", ":",
 954             "scale an unscaled high-res time", scalehrtime_cmd },
 955         { "x86_featureset", NULL, "dump the x86_featureset vector",
 956                 x86_featureset_cmd },




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Joyent, Inc.
  24  */
  25 
  26 #include <mdb/mdb_modapi.h>
  27 #include <mdb/mdb_ctf.h>
  28 #include <sys/cpuvar.h>
  29 #include <sys/systm.h>
  30 #include <sys/traptrace.h>
  31 #include <sys/x_call.h>
  32 #include <sys/xc_levels.h>
  33 #include <sys/avintr.h>
  34 #include <sys/systm.h>
  35 #include <sys/trap.h>
  36 #include <sys/mutex.h>
  37 #include <sys/mutex_impl.h>
  38 #include "i86mmu.h"
  39 #include "unix_sup.h"
  40 #include <sys/apix.h>
  41 #include <sys/x86_archext.h>
  42 #include <sys/bitmap.h>
  43 #include <sys/controlregs.h>


 392 }
 393 
 394 static struct {
 395         uchar_t t_marker;
 396         char *t_name;
 397         int (*t_hdlr)(trap_trace_rec_t *);
 398 } ttrace_hdlr[] = {
 399         { TT_SYSCALL, "sysc", ttrace_syscall },
 400         { TT_SYSENTER, "syse", ttrace_syscall },
 401         { TT_SYSC, "asys", ttrace_syscall },
 402         { TT_SYSC64, "sc64", ttrace_syscall },
 403         { TT_INTERRUPT, "intr", ttrace_interrupt },
 404         { TT_TRAP, "trap", ttrace_trap },
 405         { TT_EVENT, "evnt", ttrace_trap },
 406         { 0, NULL, NULL }
 407 };
 408 
 409 typedef struct ttrace_dcmd {
 410         processorid_t ttd_cpu;
 411         uint_t ttd_extended;
 412         uintptr_t ttd_kthread;
 413         trap_trace_ctl_t ttd_ttc[NCPU];
 414 } ttrace_dcmd_t;
 415 
 416 #if defined(__amd64)
 417 
 418 #define DUMP(reg) #reg, regs->r_##reg
 419 #define THREEREGS       "         %3s: %16lx %3s: %16lx %3s: %16lx\n"
 420 
 421 static void
 422 ttrace_dumpregs(trap_trace_rec_t *rec)
 423 {
 424         struct regs *regs = &rec->ttr_regs;
 425 
 426         mdb_printf(THREEREGS, DUMP(rdi), DUMP(rsi), DUMP(rdx));
 427         mdb_printf(THREEREGS, DUMP(rcx), DUMP(r8), DUMP(r9));
 428         mdb_printf(THREEREGS, DUMP(rax), DUMP(rbx), DUMP(rbp));
 429         mdb_printf(THREEREGS, DUMP(r10), DUMP(r11), DUMP(r12));
 430         mdb_printf(THREEREGS, DUMP(r13), DUMP(r14), DUMP(r15));
 431         mdb_printf(THREEREGS, DUMP(ds), DUMP(es), DUMP(fs));
 432         mdb_printf(THREEREGS, DUMP(gs), "trp", regs->r_trapno, DUMP(err));


 462 {
 463         struct regs *regs = &rec->ttr_regs;
 464         processorid_t cpu = -1, i;
 465 
 466         for (i = 0; i < NCPU; i++) {
 467                 if (addr >= dcmd->ttd_ttc[i].ttc_first &&
 468                     addr < dcmd->ttd_ttc[i].ttc_limit) {
 469                         cpu = i;
 470                         break;
 471                 }
 472         }
 473 
 474         if (cpu == -1) {
 475                 mdb_warn("couldn't find %p in any trap trace ctl\n", addr);
 476                 return (WALK_ERR);
 477         }
 478 
 479         if (dcmd->ttd_cpu != -1 && cpu != dcmd->ttd_cpu)
 480                 return (WALK_NEXT);
 481 
 482         if (dcmd->ttd_kthread != 0 &&
 483             dcmd->ttd_kthread != rec->ttr_curthread)
 484                 return (WALK_NEXT);
 485 
 486         mdb_printf("%3d %15llx ", cpu, rec->ttr_stamp);
 487 
 488         for (i = 0; ttrace_hdlr[i].t_hdlr != NULL; i++) {
 489                 if (rec->ttr_marker != ttrace_hdlr[i].t_marker)
 490                         continue;
 491                 mdb_printf("%4s ", ttrace_hdlr[i].t_name);
 492                 if (ttrace_hdlr[i].t_hdlr(rec) == -1)
 493                         return (WALK_ERR);
 494         }
 495 
 496         mdb_printf(" %a\n", regs->r_pc);
 497 
 498         if (dcmd->ttd_extended == FALSE)
 499                 return (WALK_NEXT);
 500 
 501         if (rec->ttr_marker == TT_INTERRUPT)
 502                 ttrace_intr_detail(rec);
 503         else
 504                 ttrace_dumpregs(rec);
 505 


 525 {
 526         ttrace_dcmd_t dcmd;
 527         trap_trace_ctl_t *ttc = dcmd.ttd_ttc;
 528         trap_trace_rec_t rec;
 529         size_t ttc_size = sizeof (trap_trace_ctl_t) * NCPU;
 530 
 531         if (!ttrace_ttr_size_check())
 532                 return (WALK_ERR);
 533 
 534         bzero(&dcmd, sizeof (dcmd));
 535         dcmd.ttd_cpu = -1;
 536         dcmd.ttd_extended = FALSE;
 537 
 538         if (mdb_readsym(ttc, ttc_size, "trap_trace_ctl") == -1) {
 539                 mdb_warn("symbol 'trap_trace_ctl' not found; "
 540                     "non-TRAPTRACE kernel?\n");
 541                 return (DCMD_ERR);
 542         }
 543 
 544         if (mdb_getopts(argc, argv,
 545             'x', MDB_OPT_SETBITS, TRUE, &dcmd.ttd_extended,
 546             't', MDB_OPT_UINTPTR, &dcmd.ttd_kthread, NULL) != argc)
 547                 return (DCMD_USAGE);
 548 
 549         if (DCMD_HDRSPEC(flags)) {
 550                 mdb_printf("%3s %15s %4s %2s %-*s%s\n", "CPU",
 551                     "TIMESTAMP", "TYPE", "Vec", TT_HDLR_WIDTH, "HANDLER",
 552                     " EIP");
 553         }
 554 
 555         if (flags & DCMD_ADDRSPEC) {
 556                 if (addr >= NCPU) {
 557                         if (mdb_vread(&rec, sizeof (rec), addr) == -1) {
 558                                 mdb_warn("couldn't read trap trace record "
 559                                     "at %p", addr);
 560                                 return (DCMD_ERR);
 561                         }
 562 
 563                         if (ttrace_walk(addr, &rec, &dcmd) == WALK_ERR)
 564                                 return (DCMD_ERR);
 565 
 566                         return (DCMD_OK);


 875                         return (DCMD_ERR);
 876                 }
 877 
 878                 if (mdb_readstr(name, sizeof (name), nptr) == -1) {
 879                         mdb_warn("failed to read feature %d", ii);
 880                         mdb_free(fset, sz);
 881                         return (DCMD_ERR);
 882                 }
 883                 mdb_printf("%s\n", name);
 884         }
 885 
 886         mdb_free(fset, sz);
 887         return (DCMD_OK);
 888 }
 889 
 890 #ifdef _KMDB
 891 /* ARGSUSED */
 892 static int
 893 crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 894 {
 895         ulong_t cr0, cr2, cr3, cr4;
 896         static const mdb_bitmask_t cr0_flag_bits[] = {
 897                 { "PE",         CR0_PE,         CR0_PE },
 898                 { "MP",         CR0_MP,         CR0_MP },
 899                 { "EM",         CR0_EM,         CR0_EM },
 900                 { "TS",         CR0_TS,         CR0_TS },
 901                 { "ET",         CR0_ET,         CR0_ET },
 902                 { "NE",         CR0_NE,         CR0_NE },
 903                 { "WP",         CR0_WP,         CR0_WP },
 904                 { "AM",         CR0_AM,         CR0_AM },
 905                 { "NW",         CR0_NW,         CR0_NW },
 906                 { "CD",         CR0_CD,         CR0_CD },
 907                 { "PG",         CR0_PG,         CR0_PG },
 908                 { NULL,         0,              0 }
 909         };
 910 
 911         static const mdb_bitmask_t cr3_flag_bits[] = {
 912                 { "PCD",        CR3_PCD,        CR3_PCD },
 913                 { "PWT",        CR3_PWT,        CR3_PWT },
 914                 { NULL,         0,              0, }
 915         };
 916 
 917         static const mdb_bitmask_t cr4_flag_bits[] = {
 918                 { "VME",        CR4_VME,        CR4_VME },
 919                 { "PVI",        CR4_PVI,        CR4_PVI },
 920                 { "TSD",        CR4_TSD,        CR4_TSD },
 921                 { "DE",         CR4_DE,         CR4_DE },
 922                 { "PSE",        CR4_PSE,        CR4_PSE },
 923                 { "PAE",        CR4_PAE,        CR4_PAE },
 924                 { "MCE",        CR4_MCE,        CR4_MCE },
 925                 { "PGE",        CR4_PGE,        CR4_PGE },
 926                 { "PCE",        CR4_PCE,        CR4_PCE },
 927                 { "OSFXSR",     CR4_OSFXSR,     CR4_OSFXSR },
 928                 { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT },
 929                 { "VMXE",       CR4_VMXE,       CR4_VMXE },
 930                 { "SMXE",       CR4_SMXE,       CR4_SMXE },
 931                 { "PCIDE",      CR4_PCIDE,      CR4_PCIDE },
 932                 { "OSXSAVE",    CR4_OSXSAVE,    CR4_OSXSAVE },
 933                 { "SMEP",       CR4_SMEP,       CR4_SMEP },
 934                 { "SMAP",       CR4_SMAP,       CR4_SMAP },
 935                 { NULL,         0,              0 }
 936         };
 937 
 938         cr0 = kmdb_unix_getcr0();
 939         cr2 = kmdb_unix_getcr2();
 940         cr3 = kmdb_unix_getcr3();
 941         cr4 = kmdb_unix_getcr4();
 942         mdb_printf("%%cr0 = 0x%08x <%b>\n", cr0, cr0, cr0_flag_bits);
 943         mdb_printf("%%cr2 = 0x%08x <%a>\n", cr2, cr2);
 944 
 945         if ((cr4 & CR4_PCIDE)) {
 946                 mdb_printf("%%cr3 = 0x%08x <pfn:%lu pcid:%u>\n",
 947                     cr3 >> MMU_PAGESHIFT, cr3 & MMU_PAGEOFFSET);
 948         } else {
 949                 mdb_printf("%%cr3 = 0x%08x <pfn:%lu flags:%b>\n", cr3,
 950                     cr3 >> MMU_PAGESHIFT, cr3, cr3_flag_bits);
 951         }
 952 
 953         mdb_printf("%%cr4 = 0x%08x <%b>\n", cr4, cr4, cr4_flag_bits);
 954 
 955         return (DCMD_OK);
 956 }
 957 #endif
 958 
 959 static const mdb_dcmd_t dcmds[] = {
 960         { "gate_desc", ":", "dump a gate descriptor", gate_desc },
 961         { "idt", ":[-v]", "dump an IDT", idt },
 962         { "ttrace", "[-x] [-t kthread]", "dump trap trace buffers", ttrace },
 963         { "vatopfn", ":[-a as]", "translate address to physical page",
 964             va2pfn_dcmd },
 965         { "report_maps", ":[-m]",
 966             "Given PFN, report mappings / page table usage",
 967             report_maps_dcmd, report_maps_help },
 968         { "htables", "", "Given hat_t *, lists all its htable_t * values",
 969             htables_dcmd, htables_help },
 970         { "ptable", ":[-m]", "Given PFN, dump contents of a page table",
 971             ptable_dcmd, ptable_help },
 972         { "pte", ":[-p XXXXX] [-l N]", "print human readable page table entry",
 973             pte_dcmd },
 974         { "pfntomfn", ":", "convert physical page to hypervisor machine page",
 975             pfntomfn_dcmd },
 976         { "mfntopfn", ":", "convert hypervisor machine page to physical page",
 977             mfntopfn_dcmd },
 978         { "memseg_list", ":", "show memseg list", memseg_list },
 979         { "scalehrtime", ":",
 980             "scale an unscaled high-res time", scalehrtime_cmd },
 981         { "x86_featureset", NULL, "dump the x86_featureset vector",
 982                 x86_featureset_cmd },