Beispiel #1
0
/*
 * Print a PTE in more human friendly way. The PTE is assumed to be in
 * a level 0 page table, unless -l specifies another level.
 *
 * The PTE value can be specified as the -p option, since on a 32 bit kernel
 * with PAE running it's larger than a uintptr_t.
 */
static int
do_pte_dcmd(int level, uint64_t pte)
{
	static char *attr[] = {
	    "wrback", "wrthru", "uncached", "uncached",
	    "wrback", "wrthru", "wrcombine", "uncached"};
	int pat_index = 0;
	pfn_t mfn;

	mdb_printf("pte=%llr: ", pte);
	if (PTE_GET(pte, mmu.pt_nx))
		mdb_printf("noexec ");

	mfn = pte2mfn(pte, level);
	mdb_printf("%s=0x%lr ", is_xpv ? "mfn" : "pfn", mfn);

	if (PTE_GET(pte, PT_NOCONSIST))
		mdb_printf("noconsist ");

	if (PTE_GET(pte, PT_NOSYNC))
		mdb_printf("nosync ");

	if (PTE_GET(pte, mmu.pt_global))
		mdb_printf("global ");

	if (level > 0 && PTE_GET(pte, PT_PAGESIZE))
		mdb_printf("largepage ");

	if (level > 0 && PTE_GET(pte, PT_MOD))
		mdb_printf("mod ");

	if (level > 0 && PTE_GET(pte, PT_REF))
		mdb_printf("ref ");

	if (PTE_GET(pte, PT_USER))
		mdb_printf("user ");

	if (PTE_GET(pte, PT_WRITABLE))
		mdb_printf("write ");

	/*
	 * Report non-standard cacheability
	 */
	pat_index = 0;
	if (level > 0) {
		if (PTE_GET(pte, PT_PAGESIZE) && PTE_GET(pte, PT_PAT_LARGE))
			pat_index += 4;
	} else {
		if (PTE_GET(pte, PT_PAT_4K))
			pat_index += 4;
	}

	if (PTE_GET(pte, PT_NOCACHE))
		pat_index += 2;

	if (PTE_GET(pte, PT_WRITETHRU))
		pat_index += 1;

	if (pat_index != 0)
		mdb_printf("%s", attr[pat_index]);

	if (PTE_GET(pte, PT_VALID) == 0)
		mdb_printf(" !VALID ");

	mdb_printf("\n");
	return (DCMD_OK);
}
Beispiel #2
0
int
ptmap_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	physaddr_t paddrs[MAX_NUM_LEVEL] = { 0, };
	size_t entry[MAX_NUM_LEVEL] = { 0, };
	uintptr_t start = (uintptr_t)-1;
	boolean_t writable = B_FALSE;
	boolean_t user = B_FALSE;
	boolean_t wflag = B_FALSE;
	level_t curlevel;

	if ((flags & DCMD_ADDRSPEC) == 0)
		return (DCMD_USAGE);

	if (mdb_getopts(argc, argv,
	    'w', MDB_OPT_SETBITS, TRUE, &wflag, NULL) != argc)
		return (DCMD_USAGE);

	init_mmu();

	if (mmu.num_level == 0)
		return (DCMD_ERR);

	curlevel = mmu.max_level;

	paddrs[curlevel] = addr & MMU_PAGEMASK;

	for (;;) {
		physaddr_t pte_addr;
		x86pte_t pte;

		pte_addr = paddrs[curlevel] +
		    (entry[curlevel] << mmu.pte_size_shift);

		if (mdb_pread(&pte, sizeof (pte), pte_addr) != sizeof (pte)) {
			mdb_warn("couldn't read pte at %p", pte_addr);
			return (DCMD_ERR);
		}

		if (PTE_GET(pte, PT_VALID) == 0) {
			if (start != (uintptr_t)-1) {
				ptmap_report(entry, start,
				    user, writable, wflag);
				start = (uintptr_t)-1;
			}
		} else if (curlevel == 0 || PTE_GET(pte, PT_PAGESIZE)) {
			if (start == (uintptr_t)-1) {
				start = entry2va(entry);
				user = PTE_GET(pte, PT_USER);
				writable = PTE_GET(pte, PT_WRITABLE);
			} else if (user != PTE_GET(pte, PT_USER) ||
			    writable != PTE_GET(pte, PT_WRITABLE)) {
				ptmap_report(entry, start,
				    user, writable, wflag);
				start = entry2va(entry);
				user = PTE_GET(pte, PT_USER);
				writable = PTE_GET(pte, PT_WRITABLE);
			}
		} else {
			/* Descend a level. */
			physaddr_t pa = mmu_ptob(pte2mfn(pte, curlevel));
			paddrs[--curlevel] = pa;
			entry[curlevel] = 0;
			continue;
		}

		while (++entry[curlevel] == mmu.ptes_per_table) {
			/* Ascend back up. */
			entry[curlevel] = 0;
			if (curlevel == mmu.max_level) {
				if (start != (uintptr_t)-1) {
					ptmap_report(entry, start,
					    user, writable, wflag);
				}
				goto out;
			}

			curlevel++;
		}
	}

out:
	return (DCMD_OK);
}