Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
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>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>

@@ -18,11 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
  */
 
 #include <mdb/mdb_modapi.h>
 #include <mdb/mdb_ctf.h>
 #include <sys/cpuvar.h>

@@ -407,10 +407,11 @@
 };
 
 typedef struct ttrace_dcmd {
         processorid_t ttd_cpu;
         uint_t ttd_extended;
+        uintptr_t ttd_kthread;
         trap_trace_ctl_t ttd_ttc[NCPU];
 } ttrace_dcmd_t;
 
 #if defined(__amd64)
 

@@ -429,10 +430,13 @@
         mdb_printf(THREEREGS, DUMP(r13), DUMP(r14), DUMP(r15));
         mdb_printf(THREEREGS, DUMP(ds), DUMP(es), DUMP(fs));
         mdb_printf(THREEREGS, DUMP(gs), "trp", regs->r_trapno, DUMP(err));
         mdb_printf(THREEREGS, DUMP(rip), DUMP(cs), DUMP(rfl));
         mdb_printf(THREEREGS, DUMP(rsp), DUMP(ss), "cr2", rec->ttr_cr2);
+        mdb_printf("         %3s: %16lx %3s: %16lx\n",
+            "fsb", regs->__r_fsbase,
+            "gsb", regs->__r_gsbase);
         mdb_printf("\n");
 }
 
 #else
 

@@ -476,10 +480,14 @@
         }
 
         if (dcmd->ttd_cpu != -1 && cpu != dcmd->ttd_cpu)
                 return (WALK_NEXT);
 
+        if (dcmd->ttd_kthread != 0 &&
+            dcmd->ttd_kthread != rec->ttr_curthread)
+                return (WALK_NEXT);
+
         mdb_printf("%3d %15llx ", cpu, rec->ttr_stamp);
 
         for (i = 0; ttrace_hdlr[i].t_hdlr != NULL; i++) {
                 if (rec->ttr_marker != ttrace_hdlr[i].t_marker)
                         continue;

@@ -535,11 +543,12 @@
                     "non-TRAPTRACE kernel?\n");
                 return (DCMD_ERR);
         }
 
         if (mdb_getopts(argc, argv,
-            'x', MDB_OPT_SETBITS, TRUE, &dcmd.ttd_extended, NULL) != argc)
+            'x', MDB_OPT_SETBITS, TRUE, &dcmd.ttd_extended,
+            't', MDB_OPT_UINTPTR, &dcmd.ttd_kthread, NULL) != argc)
                 return (DCMD_USAGE);
 
         if (DCMD_HDRSPEC(flags)) {
                 mdb_printf("%3s %15s %4s %2s %-*s%s\n", "CPU",
                     "TIMESTAMP", "TYPE", "Vec", TT_HDLR_WIDTH, "HANDLER",

@@ -745,13 +754,24 @@
 {
         mdb_printf(
             "Given a PFN holding a page table, print its contents, and\n"
             "the address of the corresponding htable structure.\n"
             "\n"
-            "-m Interpret the PFN as an MFN (machine frame number)\n");
+            "-m Interpret the PFN as an MFN (machine frame number)\n"
+            "-l force page table level (3 is top)\n");
 }
 
+static void
+ptmap_help(void)
+{
+        mdb_printf(
+            "Report all mappings represented by the page table hierarchy\n"
+            "rooted at the given cr3 value / physical address.\n"
+            "\n"
+            "-w run ::whatis on mapping start addresses\n");
+}
+
 /*
  * NSEC_SHIFT is replicated here (it is not defined in a header file),
  * but for amusement, the reader is directed to the comment that explains
  * the rationale for this particular value on x86.  Spoiler:  the value is
  * selected to accommodate 60 MHz Pentiums!  (And a confession:  if the voice

@@ -884,11 +904,11 @@
 #ifdef _KMDB
 /* ARGSUSED */
 static int
 crregs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 {
-        ulong_t cr0, cr4;
+        ulong_t cr0, cr2, cr3, cr4;
         static const mdb_bitmask_t cr0_flag_bits[] = {
                 { "PE",         CR0_PE,         CR0_PE },
                 { "MP",         CR0_MP,         CR0_MP },
                 { "EM",         CR0_EM,         CR0_EM },
                 { "TS",         CR0_TS,         CR0_TS },

@@ -900,10 +920,16 @@
                 { "CD",         CR0_CD,         CR0_CD },
                 { "PG",         CR0_PG,         CR0_PG },
                 { NULL,         0,              0 }
         };
 
+        static const mdb_bitmask_t cr3_flag_bits[] = {
+                { "PCD",        CR3_PCD,        CR3_PCD },
+                { "PWT",        CR3_PWT,        CR3_PWT },
+                { NULL,         0,              0, }
+        };
+
         static const mdb_bitmask_t cr4_flag_bits[] = {
                 { "VME",        CR4_VME,        CR4_VME },
                 { "PVI",        CR4_PVI,        CR4_PVI },
                 { "TSD",        CR4_TSD,        CR4_TSD },
                 { "DE",         CR4_DE,         CR4_DE },

@@ -914,38 +940,54 @@
                 { "PCE",        CR4_PCE,        CR4_PCE },
                 { "OSFXSR",     CR4_OSFXSR,     CR4_OSFXSR },
                 { "OSXMMEXCPT", CR4_OSXMMEXCPT, CR4_OSXMMEXCPT },
                 { "VMXE",       CR4_VMXE,       CR4_VMXE },
                 { "SMXE",       CR4_SMXE,       CR4_SMXE },
+                { "PCIDE",      CR4_PCIDE,      CR4_PCIDE },
                 { "OSXSAVE",    CR4_OSXSAVE,    CR4_OSXSAVE },
                 { "SMEP",       CR4_SMEP,       CR4_SMEP },
                 { "SMAP",       CR4_SMAP,       CR4_SMAP },
                 { NULL,         0,              0 }
         };
 
         cr0 = kmdb_unix_getcr0();
+        cr2 = kmdb_unix_getcr2();
+        cr3 = kmdb_unix_getcr3();
         cr4 = kmdb_unix_getcr4();
-        mdb_printf("%%cr0 = 0x%08x <%b>\n", cr0, cr0, cr0_flag_bits);
-        mdb_printf("%%cr4 = 0x%08x <%b>\n", cr4, cr4, cr4_flag_bits);
+        mdb_printf("%%cr0 = 0x%lx <%b>\n", cr0, cr0, cr0_flag_bits);
+        mdb_printf("%%cr2 = 0x%lx <%a>\n", cr2, cr2);
+
+        if ((cr4 & CR4_PCIDE)) {
+                mdb_printf("%%cr3 = 0x%lx <pfn:0x%lx pcid:%lu>\n", cr3,
+                    cr3 >> MMU_PAGESHIFT, cr3 & MMU_PAGEOFFSET);
+        } else {
+                mdb_printf("%%cr3 = 0x%lx <pfn:0x%lx flags:%b>\n", cr3,
+                    cr3 >> MMU_PAGESHIFT, cr3, cr3_flag_bits);
+        }
+
+        mdb_printf("%%cr4 = 0x%lx <%b>\n", cr4, cr4, cr4_flag_bits);
+
         return (DCMD_OK);
 }
 #endif
 
 static const mdb_dcmd_t dcmds[] = {
         { "gate_desc", ":", "dump a gate descriptor", gate_desc },
         { "idt", ":[-v]", "dump an IDT", idt },
-        { "ttrace", "[-x]", "dump trap trace buffers", ttrace },
+        { "ttrace", "[-x] [-t kthread]", "dump trap trace buffers", ttrace },
         { "vatopfn", ":[-a as]", "translate address to physical page",
             va2pfn_dcmd },
         { "report_maps", ":[-m]",
             "Given PFN, report mappings / page table usage",
             report_maps_dcmd, report_maps_help },
         { "htables", "", "Given hat_t *, lists all its htable_t * values",
             htables_dcmd, htables_help },
-        { "ptable", ":[-m]", "Given PFN, dump contents of a page table",
+        { "ptable", ":[-lm]", "Given PFN, dump contents of a page table",
             ptable_dcmd, ptable_help },
-        { "pte", ":[-p XXXXX] [-l N]", "print human readable page table entry",
+        { "ptmap", ":", "Given a cr3 value, dump all mappings",
+            ptmap_dcmd, ptmap_help },
+        { "pte", ":[-l N]", "print human readable page table entry",
             pte_dcmd },
         { "pfntomfn", ":", "convert physical page to hypervisor machine page",
             pfntomfn_dcmd },
         { "mfntopfn", ":", "convert hypervisor machine page to physical page",
             mfntopfn_dcmd },