Ejemplo n.º 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);
}
Ejemplo n.º 2
0
static int
do_va2pa(uintptr_t addr, struct as *asp, int print_level, physaddr_t *pap,
    pfn_t *mfnp)
{
	struct as as;
	struct hat *hatp;
	struct hat hat;
	htable_t *ht;
	htable_t htable;
	uintptr_t base;
	int h;
	int level;
	int found = 0;
	x86pte_t pte;
	physaddr_t paddr;

	if (asp != NULL) {
		if (mdb_vread(&as, sizeof (as), (uintptr_t)asp) == -1) {
			mdb_warn("Couldn't read struct as\n");
			return (DCMD_ERR);
		}
		hatp = as.a_hat;
	} else {
		hatp = khat;
	}

	/*
	 * read the hat and its hash table
	 */
	if (mdb_vread(&hat, sizeof (hat), (uintptr_t)hatp) == -1) {
		mdb_warn("Couldn't read struct hat\n");
		return (DCMD_ERR);
	}

	/*
	 * read the htable hashtable
	 */
	for (level = 0; level <= mmu.max_level; ++level) {
		if (level == TOP_LEVEL(&hat))
			base = 0;
		else
			base = addr & mmu.level_mask[level + 1];

		for (h = 0; h < hat.hat_num_hash; ++h) {
			if (mdb_vread(&ht, sizeof (htable_t *),
			    (uintptr_t)(hat.hat_ht_hash + h)) == -1) {
				mdb_warn("Couldn't read htable\n");
				return (DCMD_ERR);
			}
			for (; ht != NULL; ht = htable.ht_next) {
				if (mdb_vread(&htable, sizeof (htable_t),
				    (uintptr_t)ht) == -1) {
					mdb_warn("Couldn't read htable\n");
					return (DCMD_ERR);
				}

				if (htable.ht_vaddr != base ||
				    htable.ht_level != level)
					continue;

				pte = get_pte(&hat, &htable, addr);

				if (print_level) {
					mdb_printf("\tlevel=%d htable=%p "
					    "pte=%llr\n", level, ht, pte);
				}

				if (!PTE_ISVALID(pte)) {
					mdb_printf("Address %p is unmapped.\n",
					    addr);
					return (DCMD_ERR);
				}

				if (found)
					continue;

				if (PTE_IS_LGPG(pte, level))
					paddr = mdb_ma_to_pa(pte &
					    PT_PADDR_LGPG);
				else
					paddr = mdb_ma_to_pa(pte & PT_PADDR);
				paddr += addr & mmu.level_offset[level];
				if (pap != NULL)
					*pap = paddr;
				if (mfnp != NULL)
					*mfnp = pte2mfn(pte, level);
				found = 1;
			}
		}
	}

done:
	if (!found)
		return (DCMD_ERR);
	return (DCMD_OK);
}
Ejemplo n.º 3
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);
}