1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This part of the file contains the mdb support for dcmds: 31*7c478bd9Sstevel@tonic-gate * ::memseg_list 32*7c478bd9Sstevel@tonic-gate * ::page_num2pp 33*7c478bd9Sstevel@tonic-gate * and walkers for: 34*7c478bd9Sstevel@tonic-gate * memseg - a memseg list walker for ::memseg_list 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/machparam.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/controlregs.h> 41*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 44*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_target.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include <vm/page.h> 47*7c478bd9Sstevel@tonic-gate #include <vm/hat_i86.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate struct pfn2pp { 50*7c478bd9Sstevel@tonic-gate pfn_t pfn; 51*7c478bd9Sstevel@tonic-gate page_t *pp; 52*7c478bd9Sstevel@tonic-gate }; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static int do_va2pfn(uintptr_t, struct as *, int, physaddr_t *); 55*7c478bd9Sstevel@tonic-gate static void get_mmu(void); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate int 58*7c478bd9Sstevel@tonic-gate platform_vtop(uintptr_t addr, struct as *asp, physaddr_t *pap) 59*7c478bd9Sstevel@tonic-gate { 60*7c478bd9Sstevel@tonic-gate if (asp == NULL) 61*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* 64*7c478bd9Sstevel@tonic-gate * The kernel has to at least have made it thru mmu_init() 65*7c478bd9Sstevel@tonic-gate */ 66*7c478bd9Sstevel@tonic-gate get_mmu(); 67*7c478bd9Sstevel@tonic-gate if (mmu.num_level == 0) 68*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate return (do_va2pfn(addr, asp, 0, pap)); 71*7c478bd9Sstevel@tonic-gate } 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 75*7c478bd9Sstevel@tonic-gate int 76*7c478bd9Sstevel@tonic-gate page_num2pp_cb(uintptr_t addr, void *ignored, uintptr_t *data) 77*7c478bd9Sstevel@tonic-gate { 78*7c478bd9Sstevel@tonic-gate struct memseg ms, *msp = &ms; 79*7c478bd9Sstevel@tonic-gate struct pfn2pp *p = (struct pfn2pp *)data; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate if (mdb_vread(msp, sizeof (struct memseg), addr) == -1) { 82*7c478bd9Sstevel@tonic-gate mdb_warn("can't read memseg at %#lx", addr); 83*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate if (p->pfn >= msp->pages_base && p->pfn < msp->pages_end) { 87*7c478bd9Sstevel@tonic-gate p->pp = msp->pages + (p->pfn - msp->pages_base); 88*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * ::page_num2pp dcmd 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 98*7c478bd9Sstevel@tonic-gate int 99*7c478bd9Sstevel@tonic-gate page_num2pp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 100*7c478bd9Sstevel@tonic-gate { 101*7c478bd9Sstevel@tonic-gate struct pfn2pp pfn2pp; 102*7c478bd9Sstevel@tonic-gate page_t page; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) { 105*7c478bd9Sstevel@tonic-gate mdb_warn("page frame number missing\n"); 106*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate pfn2pp.pfn = (pfn_t)addr; 110*7c478bd9Sstevel@tonic-gate pfn2pp.pp = NULL; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate if (mdb_walk("memseg", (mdb_walk_cb_t)page_num2pp_cb, 113*7c478bd9Sstevel@tonic-gate (void *)&pfn2pp) == -1) { 114*7c478bd9Sstevel@tonic-gate mdb_warn("can't walk memseg"); 115*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (pfn2pp.pp == NULL) 119*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate mdb_printf("%x has page at %p\n", pfn2pp.pfn, pfn2pp.pp); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate if (mdb_vread(&page, sizeof (page_t), 124*7c478bd9Sstevel@tonic-gate (uintptr_t)pfn2pp.pp) == -1) { 125*7c478bd9Sstevel@tonic-gate mdb_warn("can't read page at %p", &page); 126*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (page.p_pagenum != pfn2pp.pfn) { 130*7c478bd9Sstevel@tonic-gate mdb_warn("WARNING! Found page structure contains " 131*7c478bd9Sstevel@tonic-gate "different pagenumber %x\n", page.p_pagenum); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * ::memseg_list dcmd and walker to implement it. 143*7c478bd9Sstevel@tonic-gate */ 144*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 145*7c478bd9Sstevel@tonic-gate int 146*7c478bd9Sstevel@tonic-gate memseg_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate struct memseg ms; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 151*7c478bd9Sstevel@tonic-gate if (mdb_pwalk_dcmd("memseg", "memseg_list", 152*7c478bd9Sstevel@tonic-gate 0, NULL, 0) == -1) { 153*7c478bd9Sstevel@tonic-gate mdb_warn("can't walk memseg"); 154*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (DCMD_HDRSPEC(flags)) 160*7c478bd9Sstevel@tonic-gate mdb_printf("%<u>%?s %?s %?s %?s %?s%</u>\n", "ADDR", 161*7c478bd9Sstevel@tonic-gate "PAGES", "EPAGES", "BASE", "END"); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate if (mdb_vread(&ms, sizeof (struct memseg), addr) == -1) { 164*7c478bd9Sstevel@tonic-gate mdb_warn("can't read memseg at %#lx", addr); 165*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate mdb_printf("%0?lx %0?lx %0?lx %0?lx %0?lx\n", addr, 169*7c478bd9Sstevel@tonic-gate ms.pages, ms.epages, ms.pages_base, ms.pages_end); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate /* 175*7c478bd9Sstevel@tonic-gate * walk the memseg structures 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate int 178*7c478bd9Sstevel@tonic-gate memseg_walk_init(mdb_walk_state_t *wsp) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr != NULL) { 181*7c478bd9Sstevel@tonic-gate mdb_warn("memseg only supports global walks\n"); 182*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate if (mdb_readvar(&wsp->walk_addr, "memsegs") == -1) { 186*7c478bd9Sstevel@tonic-gate mdb_warn("symbol 'memsegs' not found"); 187*7c478bd9Sstevel@tonic-gate return (WALK_ERR); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate wsp->walk_data = mdb_alloc(sizeof (struct memseg), UM_SLEEP); 191*7c478bd9Sstevel@tonic-gate return (WALK_NEXT); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate int 196*7c478bd9Sstevel@tonic-gate memseg_walk_step(mdb_walk_state_t *wsp) 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate int status; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate if (wsp->walk_addr == 0) { 201*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (mdb_vread(wsp->walk_data, sizeof (struct memseg), 205*7c478bd9Sstevel@tonic-gate wsp->walk_addr) == -1) { 206*7c478bd9Sstevel@tonic-gate mdb_warn("failed to read struct memseg at %p", wsp->walk_addr); 207*7c478bd9Sstevel@tonic-gate return (WALK_DONE); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 211*7c478bd9Sstevel@tonic-gate wsp->walk_cbdata); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)(((struct memseg *)wsp->walk_data)->next); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate return (status); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate void 219*7c478bd9Sstevel@tonic-gate memseg_walk_fini(mdb_walk_state_t *wsp) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (struct memseg)); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * HAT related dcmds: 226*7c478bd9Sstevel@tonic-gate * 227*7c478bd9Sstevel@tonic-gate * ::pte [-p XXXXXXXX] [-l 0/1/2/3] 228*7c478bd9Sstevel@tonic-gate * 229*7c478bd9Sstevel@tonic-gate * dcmd that interprets the -p argument as a page table entry and 230*7c478bd9Sstevel@tonic-gate * prints it in more human readable form. The PTE is assumed to be in 231*7c478bd9Sstevel@tonic-gate * a level 0 page table, unless -l specifies another level. 232*7c478bd9Sstevel@tonic-gate * 233*7c478bd9Sstevel@tonic-gate * ::vatopfn [-v] [-a as] 234*7c478bd9Sstevel@tonic-gate * 235*7c478bd9Sstevel@tonic-gate * Given a virtual address, returns the PFN, if any, mapped at the address. 236*7c478bd9Sstevel@tonic-gate * -v shows the intermediate htable/page table entries used to resolve the 237*7c478bd9Sstevel@tonic-gate * mapping. By default the virtual address is assumed to be in the kernel's 238*7c478bd9Sstevel@tonic-gate * address space. -a is used to specify a different address space. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate struct hat *khat; /* value of kas.a_hat */ 242*7c478bd9Sstevel@tonic-gate struct hat_mmu_info mmu; 243*7c478bd9Sstevel@tonic-gate uintptr_t kernelbase; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * read mmu parameters from kernel 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate static void 249*7c478bd9Sstevel@tonic-gate get_mmu(void) 250*7c478bd9Sstevel@tonic-gate { 251*7c478bd9Sstevel@tonic-gate struct as kas; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if (mmu.num_level != 0) 254*7c478bd9Sstevel@tonic-gate return; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate if (mdb_readsym(&mmu, sizeof (mmu), "mmu") == -1) 257*7c478bd9Sstevel@tonic-gate mdb_warn("Can't use HAT information before mmu_init()\n"); 258*7c478bd9Sstevel@tonic-gate if (mdb_readsym(&kas, sizeof (kas), "kas") == -1) 259*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't find kas - kernel's struct as\n"); 260*7c478bd9Sstevel@tonic-gate if (mdb_readsym(&kernelbase, sizeof (kernelbase), "kernelbase") == -1) 261*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't find kernelbase\n"); 262*7c478bd9Sstevel@tonic-gate khat = kas.a_hat; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * Print a PTE in more human friendly way. The PTE is assumed to be in 267*7c478bd9Sstevel@tonic-gate * a level 0 page table, unless -l specifies another level. 268*7c478bd9Sstevel@tonic-gate * 269*7c478bd9Sstevel@tonic-gate * The PTE value can be specified as the -p option, since on a 32 bit kernel 270*7c478bd9Sstevel@tonic-gate * with PAE running it's larger than a uintptr_t. 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate static int 273*7c478bd9Sstevel@tonic-gate do_pte_dcmd(int level, uint64_t pte) 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate static char *attr[] = { 276*7c478bd9Sstevel@tonic-gate "wrback", "wrthru", "uncached", "uncached", 277*7c478bd9Sstevel@tonic-gate "wrback", "wrthru", "wrcombine", "uncached"}; 278*7c478bd9Sstevel@tonic-gate int pat_index = 0; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate mdb_printf("PTE=%llx: ", pte); 281*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, mmu.pt_nx)) 282*7c478bd9Sstevel@tonic-gate mdb_printf("noexec "); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate mdb_printf("page=0x%llx ", PTE2PFN(pte, level)); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_NOCONSIST)) 287*7c478bd9Sstevel@tonic-gate mdb_printf("noconsist "); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_NOSYNC)) 290*7c478bd9Sstevel@tonic-gate mdb_printf("nosync "); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, mmu.pt_global)) 293*7c478bd9Sstevel@tonic-gate mdb_printf("global "); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (level > 0 && PTE_GET(pte, PT_PAGESIZE)) 296*7c478bd9Sstevel@tonic-gate mdb_printf("largepage "); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate if (level > 0 && PTE_GET(pte, PT_MOD)) 299*7c478bd9Sstevel@tonic-gate mdb_printf("mod "); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (level > 0 && PTE_GET(pte, PT_REF)) 302*7c478bd9Sstevel@tonic-gate mdb_printf("ref "); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_USER)) 305*7c478bd9Sstevel@tonic-gate mdb_printf("user "); 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_WRITABLE)) 308*7c478bd9Sstevel@tonic-gate mdb_printf("write "); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * Report non-standard cacheability 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate pat_index = 0; 314*7c478bd9Sstevel@tonic-gate if (level > 0) { 315*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_PAGESIZE) && PTE_GET(pte, PT_PAT_LARGE)) 316*7c478bd9Sstevel@tonic-gate pat_index += 4; 317*7c478bd9Sstevel@tonic-gate } else { 318*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_PAT_4K)) 319*7c478bd9Sstevel@tonic-gate pat_index += 4; 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_NOCACHE)) 323*7c478bd9Sstevel@tonic-gate pat_index += 2; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_WRITETHRU)) 326*7c478bd9Sstevel@tonic-gate pat_index += 1; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (pat_index != 0) 329*7c478bd9Sstevel@tonic-gate mdb_printf("%s", attr[pat_index]); 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate if (PTE_GET(pte, PT_VALID) == 0) 332*7c478bd9Sstevel@tonic-gate mdb_printf(" !VALID "); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate mdb_printf("\n"); 335*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * Print a PTE in more human friendly way. The PTE is assumed to be in 340*7c478bd9Sstevel@tonic-gate * a level 0 page table, unless -l specifies another level. 341*7c478bd9Sstevel@tonic-gate * 342*7c478bd9Sstevel@tonic-gate * The PTE value can be specified as the -p option, since on a 32 bit kernel 343*7c478bd9Sstevel@tonic-gate * with PAE running it's larger than a uintptr_t. 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 346*7c478bd9Sstevel@tonic-gate int 347*7c478bd9Sstevel@tonic-gate pte_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate int level = 0; 350*7c478bd9Sstevel@tonic-gate uint64_t pte = 0; 351*7c478bd9Sstevel@tonic-gate char *level_str = NULL; 352*7c478bd9Sstevel@tonic-gate char *pte_str = NULL; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * The kernel has to at least have made it thru mmu_init() 356*7c478bd9Sstevel@tonic-gate */ 357*7c478bd9Sstevel@tonic-gate get_mmu(); 358*7c478bd9Sstevel@tonic-gate if (mmu.num_level == 0) 359*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv, 362*7c478bd9Sstevel@tonic-gate 'p', MDB_OPT_STR, &pte_str, 363*7c478bd9Sstevel@tonic-gate 'l', MDB_OPT_STR, &level_str) != argc) 364*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * parse the PTE to decode, if it's 0, we don't do anything 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate if (pte_str != NULL) { 370*7c478bd9Sstevel@tonic-gate pte = mdb_strtoull(pte_str); 371*7c478bd9Sstevel@tonic-gate } else { 372*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 373*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 374*7c478bd9Sstevel@tonic-gate pte = addr; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate if (pte == 0) 377*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * parse the level if supplied 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate if (level_str != NULL) { 383*7c478bd9Sstevel@tonic-gate level = mdb_strtoull(level_str); 384*7c478bd9Sstevel@tonic-gate if (level < 0 || level > mmu.max_level) 385*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate return (do_pte_dcmd(level, pte)); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate static int 392*7c478bd9Sstevel@tonic-gate do_va2pfn(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate struct as as; 395*7c478bd9Sstevel@tonic-gate struct hat *hatp; 396*7c478bd9Sstevel@tonic-gate struct hat hat; 397*7c478bd9Sstevel@tonic-gate htable_t *ht; 398*7c478bd9Sstevel@tonic-gate htable_t htable; 399*7c478bd9Sstevel@tonic-gate uintptr_t base; 400*7c478bd9Sstevel@tonic-gate int h; 401*7c478bd9Sstevel@tonic-gate int level; 402*7c478bd9Sstevel@tonic-gate int found = 0; 403*7c478bd9Sstevel@tonic-gate x86pte_t pte; 404*7c478bd9Sstevel@tonic-gate x86pte_t buf; 405*7c478bd9Sstevel@tonic-gate x86pte32_t *pte32 = (x86pte32_t *)&buf; 406*7c478bd9Sstevel@tonic-gate physaddr_t paddr; 407*7c478bd9Sstevel@tonic-gate size_t len; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate if (asp != NULL) { 410*7c478bd9Sstevel@tonic-gate if (mdb_vread(&as, sizeof (as), (uintptr_t)asp) == -1) { 411*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read struct as\n"); 412*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate hatp = as.a_hat; 415*7c478bd9Sstevel@tonic-gate } else { 416*7c478bd9Sstevel@tonic-gate hatp = khat; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * read the hat and its hash table 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate if (mdb_vread(&hat, sizeof (hat), (uintptr_t)hatp) == -1) { 423*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read struct hat\n"); 424*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * read the htable hashtable 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate *pap = 0; 431*7c478bd9Sstevel@tonic-gate for (level = 0; level <= mmu.max_level; ++level) { 432*7c478bd9Sstevel@tonic-gate if (level == mmu.max_level) 433*7c478bd9Sstevel@tonic-gate base = 0; 434*7c478bd9Sstevel@tonic-gate else 435*7c478bd9Sstevel@tonic-gate base = addr & mmu.level_mask[level + 1]; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate for (h = 0; h < hat.hat_num_hash; ++h) { 438*7c478bd9Sstevel@tonic-gate if (mdb_vread(&ht, sizeof (htable_t *), 439*7c478bd9Sstevel@tonic-gate (uintptr_t)(hat.hat_ht_hash + h)) == -1) { 440*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 441*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate for (; ht != NULL; ht = htable.ht_next) { 444*7c478bd9Sstevel@tonic-gate if (mdb_vread(&htable, sizeof (htable_t), 445*7c478bd9Sstevel@tonic-gate (uintptr_t)ht) == -1) { 446*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 447*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate if (htable.ht_vaddr != base || 450*7c478bd9Sstevel@tonic-gate htable.ht_level != level) 451*7c478bd9Sstevel@tonic-gate continue; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * found - read the page table entry 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate paddr = htable.ht_pfn << MMU_PAGESHIFT; 457*7c478bd9Sstevel@tonic-gate paddr += ((addr - base) >> 458*7c478bd9Sstevel@tonic-gate mmu.level_shift[level]) << 459*7c478bd9Sstevel@tonic-gate mmu.pte_size_shift; 460*7c478bd9Sstevel@tonic-gate len = mdb_pread(&buf, mmu.pte_size, paddr); 461*7c478bd9Sstevel@tonic-gate if (len != mmu.pte_size) 462*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 463*7c478bd9Sstevel@tonic-gate if (mmu.pte_size == sizeof (x86pte_t)) 464*7c478bd9Sstevel@tonic-gate pte = buf; 465*7c478bd9Sstevel@tonic-gate else 466*7c478bd9Sstevel@tonic-gate pte = *pte32; 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate if (!found) { 469*7c478bd9Sstevel@tonic-gate if (PTE_IS_LGPG(pte, level)) 470*7c478bd9Sstevel@tonic-gate paddr = pte & PT_PADDR_LGPG; 471*7c478bd9Sstevel@tonic-gate else 472*7c478bd9Sstevel@tonic-gate paddr = pte & PT_PADDR; 473*7c478bd9Sstevel@tonic-gate paddr += addr & mmu.level_offset[level]; 474*7c478bd9Sstevel@tonic-gate *pap = paddr; 475*7c478bd9Sstevel@tonic-gate found = 1; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate if (print_level == 0) 478*7c478bd9Sstevel@tonic-gate continue; 479*7c478bd9Sstevel@tonic-gate mdb_printf("\tlevel=%d htable=%p pte=%llx\n", 480*7c478bd9Sstevel@tonic-gate level, ht, pte); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate done: 486*7c478bd9Sstevel@tonic-gate if (!found) 487*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 488*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate int 492*7c478bd9Sstevel@tonic-gate va2pfn_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate uintptr_t addrspace; 495*7c478bd9Sstevel@tonic-gate char *addrspace_str = NULL; 496*7c478bd9Sstevel@tonic-gate uint64_t physaddr; 497*7c478bd9Sstevel@tonic-gate int rc; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* 500*7c478bd9Sstevel@tonic-gate * The kernel has to at least have made it thru mmu_init() 501*7c478bd9Sstevel@tonic-gate */ 502*7c478bd9Sstevel@tonic-gate get_mmu(); 503*7c478bd9Sstevel@tonic-gate if (mmu.num_level == 0) 504*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if (mdb_getopts(argc, argv, 507*7c478bd9Sstevel@tonic-gate 'a', MDB_OPT_STR, &addrspace_str) != argc) 508*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 511*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate /* 514*7c478bd9Sstevel@tonic-gate * parse the address space 515*7c478bd9Sstevel@tonic-gate */ 516*7c478bd9Sstevel@tonic-gate if (addrspace_str != NULL) 517*7c478bd9Sstevel@tonic-gate addrspace = mdb_strtoull(addrspace_str); 518*7c478bd9Sstevel@tonic-gate else 519*7c478bd9Sstevel@tonic-gate addrspace = 0; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate rc = do_va2pfn(addr, (struct as *)addrspace, 1, &physaddr); 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate if (rc == DCMD_OK) 524*7c478bd9Sstevel@tonic-gate mdb_printf("Virtual %p maps Physical %llx\n", addr, physaddr); 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate return (rc); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* 530*7c478bd9Sstevel@tonic-gate * Report all hat's that either use PFN as a page table or that map the page. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate static int 533*7c478bd9Sstevel@tonic-gate do_report_maps(pfn_t pfn) 534*7c478bd9Sstevel@tonic-gate { 535*7c478bd9Sstevel@tonic-gate struct hat *hatp, *end; 536*7c478bd9Sstevel@tonic-gate struct hat hat; 537*7c478bd9Sstevel@tonic-gate htable_t *ht; 538*7c478bd9Sstevel@tonic-gate htable_t htable; 539*7c478bd9Sstevel@tonic-gate uintptr_t base; 540*7c478bd9Sstevel@tonic-gate int h; 541*7c478bd9Sstevel@tonic-gate int level; 542*7c478bd9Sstevel@tonic-gate int entry; 543*7c478bd9Sstevel@tonic-gate x86pte_t pte; 544*7c478bd9Sstevel@tonic-gate x86pte_t buf; 545*7c478bd9Sstevel@tonic-gate x86pte32_t *pte32 = (x86pte32_t *)&buf; 546*7c478bd9Sstevel@tonic-gate physaddr_t paddr; 547*7c478bd9Sstevel@tonic-gate size_t len; 548*7c478bd9Sstevel@tonic-gate int count; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate if (mdb_vread(&hat, sizeof (hat), (uintptr_t)khat) == -1) { 551*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read khat\n"); 552*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate end = hat.hat_next; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* 558*7c478bd9Sstevel@tonic-gate * The hats are kept in a circular list with khat at the head, but 559*7c478bd9Sstevel@tonic-gate * not part of the list proper. Accordingly, we know when we pass 560*7c478bd9Sstevel@tonic-gate * knat.hat_next a second time that we've iterated through every 561*7c478bd9Sstevel@tonic-gate * hat structure. 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate for (hatp = khat, count = 0; hatp != end || count++ == 0; 564*7c478bd9Sstevel@tonic-gate hatp = hat.hat_next) { 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * read the hat and its hash table 567*7c478bd9Sstevel@tonic-gate */ 568*7c478bd9Sstevel@tonic-gate if (mdb_vread(&hat, sizeof (hat), (uintptr_t)hatp) == -1) { 569*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read struct hat\n"); 570*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate /* 574*7c478bd9Sstevel@tonic-gate * read the htable hashtable 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate paddr = 0; 577*7c478bd9Sstevel@tonic-gate for (h = 0; h < hat.hat_num_hash; ++h) { 578*7c478bd9Sstevel@tonic-gate if (mdb_vread(&ht, sizeof (htable_t *), 579*7c478bd9Sstevel@tonic-gate (uintptr_t)(hat.hat_ht_hash + h)) == -1) { 580*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 581*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate for (; ht != NULL; ht = htable.ht_next) { 584*7c478bd9Sstevel@tonic-gate if (mdb_vread(&htable, sizeof (htable_t), 585*7c478bd9Sstevel@tonic-gate (uintptr_t)ht) == -1) { 586*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 587*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * only report kernel addresses once 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate if (hatp != khat && 594*7c478bd9Sstevel@tonic-gate htable.ht_vaddr >= kernelbase) 595*7c478bd9Sstevel@tonic-gate continue; 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* 598*7c478bd9Sstevel@tonic-gate * Is the PFN a pagetable itself? 599*7c478bd9Sstevel@tonic-gate */ 600*7c478bd9Sstevel@tonic-gate if (htable.ht_pfn == pfn) { 601*7c478bd9Sstevel@tonic-gate mdb_printf("Pagetable for " 602*7c478bd9Sstevel@tonic-gate "hat=%p htable=%p\n", hatp, ht); 603*7c478bd9Sstevel@tonic-gate continue; 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* 607*7c478bd9Sstevel@tonic-gate * otherwise, examine page mappings 608*7c478bd9Sstevel@tonic-gate */ 609*7c478bd9Sstevel@tonic-gate level = htable.ht_level; 610*7c478bd9Sstevel@tonic-gate if (level > mmu.max_page_level) 611*7c478bd9Sstevel@tonic-gate continue; 612*7c478bd9Sstevel@tonic-gate paddr = htable.ht_pfn << MMU_PAGESHIFT; 613*7c478bd9Sstevel@tonic-gate for (entry = 0; entry < htable.ht_num_ptes; 614*7c478bd9Sstevel@tonic-gate ++entry) { 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate base = htable.ht_vaddr + entry * 617*7c478bd9Sstevel@tonic-gate mmu.level_size[level]; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate /* 620*7c478bd9Sstevel@tonic-gate * only report kernel addresses once 621*7c478bd9Sstevel@tonic-gate */ 622*7c478bd9Sstevel@tonic-gate if (hatp != khat && 623*7c478bd9Sstevel@tonic-gate base >= kernelbase) 624*7c478bd9Sstevel@tonic-gate continue; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate len = mdb_pread(&buf, mmu.pte_size, 627*7c478bd9Sstevel@tonic-gate paddr + entry * mmu.pte_size); 628*7c478bd9Sstevel@tonic-gate if (len != mmu.pte_size) 629*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 630*7c478bd9Sstevel@tonic-gate if (mmu.pte_size == sizeof (x86pte_t)) 631*7c478bd9Sstevel@tonic-gate pte = buf; 632*7c478bd9Sstevel@tonic-gate else 633*7c478bd9Sstevel@tonic-gate pte = *pte32; 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate if ((pte & PT_VALID) == 0) 636*7c478bd9Sstevel@tonic-gate continue; 637*7c478bd9Sstevel@tonic-gate if (level == 0 || !(pte & PT_PAGESIZE)) 638*7c478bd9Sstevel@tonic-gate pte &= PT_PADDR; 639*7c478bd9Sstevel@tonic-gate else 640*7c478bd9Sstevel@tonic-gate pte &= PT_PADDR_LGPG; 641*7c478bd9Sstevel@tonic-gate if ((pte >> MMU_PAGESHIFT) != pfn) 642*7c478bd9Sstevel@tonic-gate continue; 643*7c478bd9Sstevel@tonic-gate mdb_printf("hat=%p maps addr=%p\n", 644*7c478bd9Sstevel@tonic-gate hatp, (caddr_t)base); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate done: 651*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * given a PFN as its address argument, prints out the uses of it 656*7c478bd9Sstevel@tonic-gate */ 657*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 658*7c478bd9Sstevel@tonic-gate int 659*7c478bd9Sstevel@tonic-gate report_maps_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate /* 662*7c478bd9Sstevel@tonic-gate * The kernel has to at least have made it thru mmu_init() 663*7c478bd9Sstevel@tonic-gate */ 664*7c478bd9Sstevel@tonic-gate get_mmu(); 665*7c478bd9Sstevel@tonic-gate if (mmu.num_level == 0) 666*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 669*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate return (do_report_maps((pfn_t)addr)); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* 675*7c478bd9Sstevel@tonic-gate * Dump the page table at the given PFN 676*7c478bd9Sstevel@tonic-gate */ 677*7c478bd9Sstevel@tonic-gate static int 678*7c478bd9Sstevel@tonic-gate do_ptable_dcmd(pfn_t pfn) 679*7c478bd9Sstevel@tonic-gate { 680*7c478bd9Sstevel@tonic-gate struct hat *hatp, *end; 681*7c478bd9Sstevel@tonic-gate struct hat hat; 682*7c478bd9Sstevel@tonic-gate htable_t *ht; 683*7c478bd9Sstevel@tonic-gate htable_t htable; 684*7c478bd9Sstevel@tonic-gate uintptr_t base; 685*7c478bd9Sstevel@tonic-gate int h; 686*7c478bd9Sstevel@tonic-gate int level; 687*7c478bd9Sstevel@tonic-gate int entry; 688*7c478bd9Sstevel@tonic-gate uintptr_t pagesize; 689*7c478bd9Sstevel@tonic-gate x86pte_t pte; 690*7c478bd9Sstevel@tonic-gate x86pte_t buf; 691*7c478bd9Sstevel@tonic-gate x86pte32_t *pte32 = (x86pte32_t *)&buf; 692*7c478bd9Sstevel@tonic-gate physaddr_t paddr; 693*7c478bd9Sstevel@tonic-gate size_t len; 694*7c478bd9Sstevel@tonic-gate int count; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate if (mdb_vread(&hat, sizeof (hat), (uintptr_t)khat) == -1) { 697*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read khat\n"); 698*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate end = hat.hat_next; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* 704*7c478bd9Sstevel@tonic-gate * The hats are kept in a circular list with khat at the head, but 705*7c478bd9Sstevel@tonic-gate * not part of the list proper. Accordingly, we know when we pass 706*7c478bd9Sstevel@tonic-gate * knat.hat_next a second time that we've iterated through every 707*7c478bd9Sstevel@tonic-gate * hat structure. 708*7c478bd9Sstevel@tonic-gate */ 709*7c478bd9Sstevel@tonic-gate for (hatp = khat, count = 0; hatp != end || count++ == 0; 710*7c478bd9Sstevel@tonic-gate hatp = hat.hat_next) { 711*7c478bd9Sstevel@tonic-gate /* 712*7c478bd9Sstevel@tonic-gate * read the hat and its hash table 713*7c478bd9Sstevel@tonic-gate */ 714*7c478bd9Sstevel@tonic-gate if (mdb_vread(&hat, sizeof (hat), (uintptr_t)hatp) == -1) { 715*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read struct hat\n"); 716*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate /* 720*7c478bd9Sstevel@tonic-gate * read the htable hashtable 721*7c478bd9Sstevel@tonic-gate */ 722*7c478bd9Sstevel@tonic-gate paddr = 0; 723*7c478bd9Sstevel@tonic-gate for (h = 0; h < hat.hat_num_hash; ++h) { 724*7c478bd9Sstevel@tonic-gate if (mdb_vread(&ht, sizeof (htable_t *), 725*7c478bd9Sstevel@tonic-gate (uintptr_t)(hat.hat_ht_hash + h)) == -1) { 726*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 727*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate for (; ht != NULL; ht = htable.ht_next) { 730*7c478bd9Sstevel@tonic-gate if (mdb_vread(&htable, sizeof (htable_t), 731*7c478bd9Sstevel@tonic-gate (uintptr_t)ht) == -1) { 732*7c478bd9Sstevel@tonic-gate mdb_warn("Couldn't read htable\n"); 733*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate /* 737*7c478bd9Sstevel@tonic-gate * Is this the PFN for this htable 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate if (htable.ht_pfn == pfn) 740*7c478bd9Sstevel@tonic-gate goto found_it; 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate found_it: 746*7c478bd9Sstevel@tonic-gate if (htable.ht_pfn == pfn) { 747*7c478bd9Sstevel@tonic-gate mdb_printf("htable=%p\n", ht); 748*7c478bd9Sstevel@tonic-gate level = htable.ht_level; 749*7c478bd9Sstevel@tonic-gate base = htable.ht_vaddr; 750*7c478bd9Sstevel@tonic-gate pagesize = mmu.level_size[level]; 751*7c478bd9Sstevel@tonic-gate } else { 752*7c478bd9Sstevel@tonic-gate mdb_printf("Unknown pagetable - assuming level/addr 0"); 753*7c478bd9Sstevel@tonic-gate level = 0; /* assume level == 0 for PFN */ 754*7c478bd9Sstevel@tonic-gate base = 0; 755*7c478bd9Sstevel@tonic-gate pagesize = MMU_PAGESIZE; 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate paddr = pfn << MMU_PAGESHIFT; 759*7c478bd9Sstevel@tonic-gate for (entry = 0; entry < mmu.ptes_per_table; ++entry) { 760*7c478bd9Sstevel@tonic-gate len = mdb_pread(&buf, mmu.pte_size, 761*7c478bd9Sstevel@tonic-gate paddr + entry * mmu.pte_size); 762*7c478bd9Sstevel@tonic-gate if (len != mmu.pte_size) 763*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 764*7c478bd9Sstevel@tonic-gate if (mmu.pte_size == sizeof (x86pte_t)) 765*7c478bd9Sstevel@tonic-gate pte = buf; 766*7c478bd9Sstevel@tonic-gate else 767*7c478bd9Sstevel@tonic-gate pte = *pte32; 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate if (pte == 0) 770*7c478bd9Sstevel@tonic-gate continue; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate mdb_printf("[%3d] va=%p ", entry, base + entry * pagesize); 773*7c478bd9Sstevel@tonic-gate do_pte_dcmd(level, pte); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate done: 777*7c478bd9Sstevel@tonic-gate return (DCMD_OK); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate /* 781*7c478bd9Sstevel@tonic-gate * given a PFN as its address argument, prints out the uses of it 782*7c478bd9Sstevel@tonic-gate */ 783*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 784*7c478bd9Sstevel@tonic-gate int 785*7c478bd9Sstevel@tonic-gate ptable_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 786*7c478bd9Sstevel@tonic-gate { 787*7c478bd9Sstevel@tonic-gate /* 788*7c478bd9Sstevel@tonic-gate * The kernel has to at least have made it thru mmu_init() 789*7c478bd9Sstevel@tonic-gate */ 790*7c478bd9Sstevel@tonic-gate get_mmu(); 791*7c478bd9Sstevel@tonic-gate if (mmu.num_level == 0) 792*7c478bd9Sstevel@tonic-gate return (DCMD_ERR); 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate if ((flags & DCMD_ADDRSPEC) == 0) 795*7c478bd9Sstevel@tonic-gate return (DCMD_USAGE); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate return (do_ptable_dcmd((pfn_t)addr)); 798*7c478bd9Sstevel@tonic-gate } 799