コード例 #1
0
ファイル: kvm_minidump_arm.c プロジェクト: mulichao/freebsd
static int
_arm_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
{
	struct vmstate *vm;
	arm_pt_entry_t pte;
	arm_physaddr_t offset, a;
	kvaddr_t pteindex;
	off_t ofs;
	arm_pt_entry_t *ptemap;

	if (ISALIVE(kd)) {
		_kvm_err(kd, 0, "_arm_minidump_kvatop called in live kernel!");
		return (0);
	}

	vm = kd->vmst;
	ptemap = vm->ptemap;

	if (va >= vm->hdr.kernbase) {
		pteindex = (va - vm->hdr.kernbase) >> ARM_PAGE_SHIFT;
		if (pteindex >= vm->hdr.ptesize / sizeof(*ptemap))
			goto invalid;
		pte = _kvm32toh(kd, ptemap[pteindex]);
		if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_INV) {
			_kvm_err(kd, kd->program,
			    "_arm_minidump_kvatop: pte not valid");
			goto invalid;
		}
		if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_L) {
			/* 64K page -> convert to be like 4K page */
			offset = va & ARM_L2_S_OFFSET;
			a = (pte & ARM_L2_L_FRAME) +
			    (va & ARM_L2_L_OFFSET & ARM_L2_S_FRAME);
		} else {
			if (kd->vmst->hdr.mmuformat == MINIDUMP_MMU_FORMAT_V4 &&
			    (pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_T) {
				_kvm_err(kd, kd->program,
				    "_arm_minidump_kvatop: pte not supported");
				goto invalid;
			}
			/* 4K page */
			offset = va & ARM_L2_S_OFFSET;
			a = pte & ARM_L2_S_FRAME;
		}

		ofs = _kvm_pt_find(kd, a);
		if (ofs == -1) {
			_kvm_err(kd, kd->program, "_arm_minidump_kvatop: "
			    "physical address 0x%jx not in minidump",
			    (uintmax_t)a);
			goto invalid;
		}

		*pa = ofs + offset;
		return (ARM_PAGE_SIZE - offset);
	} else
コード例 #2
0
ファイル: kvm_arm.c プロジェクト: mulichao/freebsd
static int
_arm_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
{
	struct vmstate *vm = kd->vmst;
	arm_pd_entry_t pd;
	arm_pt_entry_t pte;
	arm_physaddr_t pte_pa;
	off_t pte_off;

	if (vm->l1pt == NULL)
		return (_kvm_pa2off(kd, va, pa, ARM_PAGE_SIZE));
	pd = _kvm32toh(kd, vm->l1pt[ARM_L1_IDX(va)]);
	if (!l1pte_valid(pd))
		goto invalid;
	if (l1pte_section_p(pd)) {
		/* 1MB section mapping. */
		*pa = (pd & ARM_L1_S_ADDR_MASK) + (va & ARM_L1_S_OFFSET);
		return  (_kvm_pa2off(kd, *pa, pa, ARM_L1_S_SIZE));
	}
	pte_pa = (pd & ARM_L1_C_ADDR_MASK) + l2pte_index(va) * sizeof(pte);
	_kvm_pa2off(kd, pte_pa, &pte_off, ARM_L1_S_SIZE);
	if (pread(kd->pmfd, &pte, sizeof(pte), pte_off) != sizeof(pte)) {
		_kvm_syserr(kd, kd->program, "_arm_kvatop: pread");
		goto invalid;
	}
	pte = _kvm32toh(kd, pte);
	if (!l2pte_valid(pte)) {
		goto invalid;
	}
	if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_L) {
		*pa = (pte & ARM_L2_L_FRAME) | (va & ARM_L2_L_OFFSET);
		return (_kvm_pa2off(kd, *pa, pa, ARM_L2_L_SIZE));
	}
	*pa = (pte & ARM_L2_S_FRAME) | (va & ARM_L2_S_OFFSET);
	return (_kvm_pa2off(kd, *pa, pa, ARM_PAGE_SIZE));
invalid:
	_kvm_err(kd, 0, "Invalid address (%jx)", (uintmax_t)va);
	return 0;
}
コード例 #3
0
static int
_mips_minidump_initvtop(kvm_t *kd)
{
	struct vmstate *vmst;
	off_t off, sparse_off;

	vmst = _kvm_malloc(kd, sizeof(*vmst));
	if (vmst == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate vm");
		return (-1);
	}

	kd->vmst = vmst;

	if (kd->nlehdr.e_ident[EI_CLASS] == ELFCLASS64 ||
	    kd->nlehdr.e_flags & EF_MIPS_ABI2)
		vmst->pte_size = 64;
	else
		vmst->pte_size = 32;

	if (pread(kd->pmfd, &vmst->hdr,
	    sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) {
		_kvm_err(kd, kd->program, "cannot read dump header");
		return (-1);
	}

	if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic,
	    sizeof(vmst->hdr.magic)) != 0) {
		_kvm_err(kd, kd->program, "not a minidump for this platform");
		return (-1);
	}
	vmst->hdr.version = _kvm32toh(kd, vmst->hdr.version);
	if (vmst->hdr.version != MINIDUMP_VERSION) {
		_kvm_err(kd, kd->program, "wrong minidump version. "
		    "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version);
		return (-1);
	}
	vmst->hdr.msgbufsize = _kvm32toh(kd, vmst->hdr.msgbufsize);
	vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize);
	vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize);
	vmst->hdr.kernbase = _kvm64toh(kd, vmst->hdr.kernbase);
	vmst->hdr.dmapbase = _kvm64toh(kd, vmst->hdr.dmapbase);
	vmst->hdr.dmapend = _kvm64toh(kd, vmst->hdr.dmapend);

	/* Skip header and msgbuf */
	off = MIPS_PAGE_SIZE + mips_round_page(vmst->hdr.msgbufsize);

	sparse_off = off + mips_round_page(vmst->hdr.bitmapsize) +
	    mips_round_page(vmst->hdr.ptesize);
	if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off,
	    MIPS_PAGE_SIZE, sizeof(uint32_t)) == -1) {
		return (-1);
	}
	off += mips_round_page(vmst->hdr.bitmapsize);

	if (_kvm_pmap_init(kd, vmst->hdr.ptesize, off) == -1) {
		return (-1);
	}
	off += mips_round_page(vmst->hdr.ptesize);

	return (0);
}
コード例 #4
0
ファイル: kvm_minidump_arm.c プロジェクト: mulichao/freebsd
static int
_arm_minidump_initvtop(kvm_t *kd)
{
	struct vmstate *vmst;
	off_t off, sparse_off;

	vmst = _kvm_malloc(kd, sizeof(*vmst));
	if (vmst == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate vm");
		return (-1);
	}

	kd->vmst = vmst;

	if (pread(kd->pmfd, &vmst->hdr,
	    sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) {
		_kvm_err(kd, kd->program, "cannot read dump header");
		return (-1);
	}

	if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic,
	    sizeof(vmst->hdr.magic)) != 0) {
		_kvm_err(kd, kd->program, "not a minidump for this platform");
		return (-1);
	}
	vmst->hdr.version = _kvm32toh(kd, vmst->hdr.version);
	if (vmst->hdr.version != MINIDUMP_VERSION) {
		_kvm_err(kd, kd->program, "wrong minidump version. "
		    "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version);
		return (-1);
	}
	vmst->hdr.msgbufsize = _kvm32toh(kd, vmst->hdr.msgbufsize);
	vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize);
	vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize);
	vmst->hdr.kernbase = _kvm32toh(kd, vmst->hdr.kernbase);
	vmst->hdr.arch = _kvm32toh(kd, vmst->hdr.arch);
	vmst->hdr.mmuformat = _kvm32toh(kd, vmst->hdr.mmuformat);
	if (vmst->hdr.mmuformat == MINIDUMP_MMU_FORMAT_UNKNOWN) {
		/* This is a safe default as 1K pages are not used. */
		vmst->hdr.mmuformat = MINIDUMP_MMU_FORMAT_V6;
	}

	/* Skip header and msgbuf */
	off = ARM_PAGE_SIZE + arm_round_page(vmst->hdr.msgbufsize);

	sparse_off = off + arm_round_page(vmst->hdr.bitmapsize) +
	    arm_round_page(vmst->hdr.ptesize);
	if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off,
	    ARM_PAGE_SIZE, sizeof(uint32_t)) == -1) {
		_kvm_err(kd, kd->program, "cannot load core bitmap");
		return (-1);
	}
	off += arm_round_page(vmst->hdr.bitmapsize);

	vmst->ptemap = _kvm_malloc(kd, vmst->hdr.ptesize);
	if (vmst->ptemap == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate %d bytes for "
		    "ptemap", vmst->hdr.ptesize);
		return (-1);
	}

	if (pread(kd->pmfd, vmst->ptemap, vmst->hdr.ptesize, off) !=
	    (ssize_t)vmst->hdr.ptesize) {
		_kvm_err(kd, kd->program, "cannot read %d bytes for ptemap",
		    vmst->hdr.ptesize);
		return (-1);
	}
	off += arm_round_page(vmst->hdr.ptesize);

	return (0);
}
コード例 #5
0
ファイル: kvm_minidump_mips.c プロジェクト: 2asoft/freebsd
static int
_mips_minidump_initvtop(kvm_t *kd)
{
	struct vmstate *vmst;
	uint32_t *bitmap;
	off_t off;

	vmst = _kvm_malloc(kd, sizeof(*vmst));
	if (vmst == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate vm");
		return (-1);
	}

	kd->vmst = vmst;

	if (kd->nlehdr.e_ident[EI_CLASS] == ELFCLASS64 ||
	    kd->nlehdr.e_flags & EF_MIPS_ABI2)
		vmst->pte_size = 64;
	else
		vmst->pte_size = 32;

	if (pread(kd->pmfd, &vmst->hdr,
	    sizeof(vmst->hdr), 0) != sizeof(vmst->hdr)) {
		_kvm_err(kd, kd->program, "cannot read dump header");
		return (-1);
	}

	if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic,
	    sizeof(vmst->hdr.magic)) != 0) {
		_kvm_err(kd, kd->program, "not a minidump for this platform");
		return (-1);
	}
	vmst->hdr.version = _kvm32toh(kd, vmst->hdr.version);
	if (vmst->hdr.version != MINIDUMP_VERSION) {
		_kvm_err(kd, kd->program, "wrong minidump version. "
		    "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version);
		return (-1);
	}
	vmst->hdr.msgbufsize = _kvm32toh(kd, vmst->hdr.msgbufsize);
	vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize);
	vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize);
	vmst->hdr.kernbase = _kvm64toh(kd, vmst->hdr.kernbase);
	vmst->hdr.dmapbase = _kvm64toh(kd, vmst->hdr.dmapbase);
	vmst->hdr.dmapend = _kvm64toh(kd, vmst->hdr.dmapend);

	/* Skip header and msgbuf */
	off = MIPS_PAGE_SIZE + mips_round_page(vmst->hdr.msgbufsize);

	bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize);
	if (bitmap == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate %d bytes for "
		    "bitmap", vmst->hdr.bitmapsize);
		return (-1);
	}

	if (pread(kd->pmfd, bitmap, vmst->hdr.bitmapsize, off) !=
	    (ssize_t)vmst->hdr.bitmapsize) {
		_kvm_err(kd, kd->program, "cannot read %d bytes for page bitmap",
		    vmst->hdr.bitmapsize);
		free(bitmap);
		return (-1);
	}
	off += mips_round_page(vmst->hdr.bitmapsize);

	vmst->ptemap = _kvm_malloc(kd, vmst->hdr.ptesize);
	if (vmst->ptemap == NULL) {
		_kvm_err(kd, kd->program, "cannot allocate %d bytes for "
		    "ptemap", vmst->hdr.ptesize);
		free(bitmap);
		return (-1);
	}

	if (pread(kd->pmfd, vmst->ptemap, vmst->hdr.ptesize, off) !=
	    (ssize_t)vmst->hdr.ptesize) {
		_kvm_err(kd, kd->program, "cannot read %d bytes for ptemap",
		    vmst->hdr.ptesize);
		free(bitmap);
		return (-1);
	}

	off += vmst->hdr.ptesize;

	/* Build physical address hash table for sparse pages */
	_kvm_hpt_init(kd, &vmst->hpt, bitmap, vmst->hdr.bitmapsize, off,
	    MIPS_PAGE_SIZE, sizeof(*bitmap));
	free(bitmap);

	return (0);
}
コード例 #6
0
ファイル: kvm_minidump_mips.c プロジェクト: 2asoft/freebsd
static int
_mips_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
{
	struct vmstate *vm;
	uint64_t pte;
	mips_physaddr_t offset, a;
	kvaddr_t pteindex;
	off_t ofs;
	uint32_t *ptemap32;
	uint64_t *ptemap64;

	if (ISALIVE(kd)) {
		_kvm_err(kd, 0, "_mips_minidump_kvatop called in live kernel!");
		return (0);
	}

	offset = va & MIPS_PAGE_MASK;
	/* Operate with page-aligned address */
	va &= ~MIPS_PAGE_MASK;

	vm = kd->vmst;
	ptemap32 = vm->ptemap;
	ptemap64 = vm->ptemap;

	if (kd->nlehdr.e_ident[EI_CLASS] == ELFCLASS64) {
		if (va >= MIPS_XKPHYS_START && va < MIPS_XKPHYS_END) {
			a = va & MIPS_XKPHYS_PHYS_MASK;
			goto found;
		}
		if (va >= MIPS64_KSEG0_START && va < MIPS64_KSEG0_END) {
			a = va & MIPS_KSEG0_PHYS_MASK;
			goto found;
		}
		if (va >= MIPS64_KSEG1_START && va < MIPS64_KSEG1_END) {
			a = va & MIPS_KSEG0_PHYS_MASK;
			goto found;
		}
	} else {
		if (va >= MIPS32_KSEG0_START && va < MIPS32_KSEG0_END) {
			a = va & MIPS_KSEG0_PHYS_MASK;
			goto found;
		}
		if (va >= MIPS32_KSEG1_START && va < MIPS32_KSEG1_END) {
			a = va & MIPS_KSEG0_PHYS_MASK;
			goto found;
		}
	}
	if (va >= vm->hdr.kernbase) {
		pteindex = (va - vm->hdr.kernbase) >> MIPS_PAGE_SHIFT;
		if (vm->pte_size == 64) {
			pte = _kvm64toh(kd, ptemap64[pteindex]);
			a = MIPS64_PTE_TO_PA(pte);
		} else {
			pte = _kvm32toh(kd, ptemap32[pteindex]);
			a = MIPS32_PTE_TO_PA(pte);
		}
		if (!pte) {
			_kvm_err(kd, kd->program, "_mips_minidump_kvatop: pte "
			    "not valid");
			goto invalid;
		}
	} else {