843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * KVM backend for hypervisor domain dumps. We don't use libkvm for
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * such dumps, since they do not have a namelist file or the typical
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * dump structures we expect to aid bootstrapping. Instead, we
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * bootstrap based upon a debug_info structure at a known VA, using the
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * guest's own page tables to resolve to physical addresses, and
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * construct the namelist in a manner similar to ksyms_snapshot().
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Note that there are two formats understood by this module: the older,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * ad hoc format, which we call 'core' within this file, and an
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * ELF-based format, known as 'elf'.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * We only support the older format generated on Solaris dom0: before we
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * fixed it, core dump files were broken whenever a PFN didn't map a
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * real MFN (!).
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_WALK_ALL (XKB_WALK_LOCAL | XKB_WALK_GLOBAL | XKB_WALK_STR)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#if defined(__i386)
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define PTE_IS_LGPG(p, l) ((l) > 0 && ((p) & PT_PAGESIZE))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Either an old-style (3.0.4) core format, or the ELF format.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabtypedef enum {
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const char xkb_shstrtab[] = "\0.symtab\0.strtab\0.shstrtab\0";
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mfn_t xkb_va_to_mfn(xkb_t *, uintptr_t, mfn_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ssize_t xkb_read(xkb_t *, uintptr_t, void *, size_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xkb_read_word(xkb_t *, uintptr_t, uintptr_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *xkb_map_mfn(xkb_t *, mfn_t, mfn_map_t *);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Jump through the hoops we need to to correctly identify a core file
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * of either the old or new format.
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pread64(fd, &header, sizeof (header), 0) != sizeof (header)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sizeof (struct vcpu_guest_context) *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sizeof (struct vcpu_guest_context) *
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif /* _LP64 */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((io = mdb_fdio_create_path(NULL, file, O_RDONLY, 0)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (-1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((gf = mdb_gelf_create(io, ET_NONE, GF_FILE)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((sect = mdb_gelf_sect_by_name(gf, ".note.Xen")) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * The contents of this struct differ between 32 and 64
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * bit; however, not until past the 'xev_capabilities'
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * member, so we can just about get away with this.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * 64-bit hypervisor, but it can still be
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * a 32-bit domain core. 32-bit domain cores
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * are also dumped in Elf64 format, but they
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * have e_machine set to EM_386, not EM_AMD64.
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * 32-bit hypervisor, can only be a 32-bit core.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "assuming 64-bit");
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void *
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_m2p = mdb_alloc((xkb->xkb_max_mfn + 1) * sizeof (xen_pfn_t),
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * With FORMAT_CORE, we can use the table in the dump file directly.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Just to make things fun, they've not page-aligned the p2m table.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * With FORMAT_ELF, we have a set of <pfn,mfn> pairs, which we convert
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * into a linear array indexed by pfn for convenience. We also need to
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * track the mapping between mfn and the offset in the file: a pfn with
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * no mfn will not appear in the core file.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (0);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((p2m = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (0);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (1);
5d2eda970e48f8985448151c73e699614ce9f357John Levon * For HVM images, we don't have the corresponding MFN list; the table
5d2eda970e48f8985448151c73e699614ce9f357John Levon * is just a mapping from page index in the dump to the corresponding
5d2eda970e48f8985448151c73e699614ce9f357John Levon * PFN. To simplify the other code, we'll pretend that these PFNs are
5d2eda970e48f8985448151c73e699614ce9f357John Levon * really MFNs as well, by populating xkb_p2m.
5d2eda970e48f8985448151c73e699614ce9f357John Levon sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pfn");
5d2eda970e48f8985448151c73e699614ce9f357John Levon (void) xkb_fail(xkb, "cannot find section .xen_pfn");
5d2eda970e48f8985448151c73e699614ce9f357John Levon if ((p2pfn = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (p2pfn[i] != PFN_INVALID && p2pfn[i] > xkb->xkb_max_pfn)
5d2eda970e48f8985448151c73e699614ce9f357John Levon size = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Return the MFN of the top-level page table for the given as.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, asp + offsetof(struct as, a_hat), &hatp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, hatp + xkb->xkb_info.di_hat_htable_off,
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, htablep + xkb->xkb_info.di_ht_pfn_off,
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_helper(xkb_t *xkb, struct as *as, int phys, uint64_t addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we're windowed then pread() is much faster.
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_pread(xkb_t *xkb, uint64_t addr, void *buf, size_t size)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_read_helper(xkb, NULL, 1, addr, buf, size));
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_aread(xkb_t *xkb, uintptr_t addr, void *buf, size_t size, struct as *as)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_read_helper(xkb, as, 0, addr, buf, size));
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read(xkb_t *xkb, uintptr_t addr, void *buf, size_t size)
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_word(xkb_t *xkb, uintptr_t addr, uintptr_t *buf)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < 1024; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == 1024) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlev mm->mm_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Resolve the given VA into an MFN, using the provided mfn as a top-level page
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_map_mfn(xkb, mfn, &xkb->xkb_pt_map[level]) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev entry = (va >> mmu->mi_shift[level]) & (mmu->mi_ptes - 1);
5d2eda970e48f8985448151c73e699614ce9f357John Levon pte = xkb_get_pte(mmu, (char *)xkb->xkb_pt_map[level].mm_map +
5d2eda970e48f8985448151c73e699614ce9f357John Levon if ((mfn = xkb_pte_to_base_mfn(pte, level)) == MFN_INVALID)
5d2eda970e48f8985448151c73e699614ce9f357John Levon * Currently 'mfn' refers to the base MFN of the
5d2eda970e48f8985448151c73e699614ce9f357John Levon * large-page mapping. Add on the 4K-sized index into
5d2eda970e48f8985448151c73e699614ce9f357John Levon * the large-page mapping to get the right MFN within
5d2eda970e48f8985448151c73e699614ce9f357John Levon * the mapping.
5d2eda970e48f8985448151c73e699614ce9f357John Levon mfn += (va & ((1 << mmu->mi_shift[level]) - 1)) >>
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_module(xkb_t *xkb, uintptr_t modulep, struct module *module,
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t *sym_addr, uintptr_t *sym_count, uintptr_t *str_addr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, modulep, module, sizeof (struct module)) !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (struct module))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_modsyms(xkb_t *xkb, char **buf, size_t *sizes, int types,
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t sym_addr, uintptr_t str_addr, uintptr_t sym_count)
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < sym_count; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, sym_addr + i * sizeof (sym), &sym,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_walk_syms(xkb_t *xkb, uintptr_t modhead, char **buf,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * empty first symbol
843e19887f64dde75055cf8842fc4db2171eff45johnlev modctl + offsetof(struct modctl, mod_mp), &modulep))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_module(xkb, modulep, &module, &sym_addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_modsyms(xkb, buf, sizes, types, sym_addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev modctl + offsetof(struct modctl, mod_next), &modctl))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Try and prevent us looping forever if we have a broken list.
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Userspace equivalent of ksyms_snapshot(). Since we don't have a namelist
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file for hypervisor images, we fabricate one here using code similar
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to that of /dev/ksyms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, NULL, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xkb->xkb_namelist = mdb_zalloc(xkb->xkb_namesize, UM_SLEEP))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, module + offsetof(struct module, hdr),
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_elf_hdr.e_phoff = offsetof(xkb_namelist_t, kh_text_phdr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_elf_hdr.e_shoff = offsetof(xkb_namelist_t, kh_shdr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_text_phdr.p_memsz = (Word)(info->di_e_text - info->di_s_text);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_data_phdr.p_memsz = (Word)(info->di_e_data - info->di_s_data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_size = sizes[XKB_WALK_LOCAL] + sizes[XKB_WALK_GLOBAL];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_info = sizes[XKB_WALK_LOCAL] / sizeof (Sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_name = 17; /* xkb_shstrtab[17] = ".shstrtab" */
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_offset = offsetof(xkb_namelist_t, shstrings);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(xkb_shstrtab, hdr->shstrings, sizeof (xkb_shstrtab));
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((xkb->xkb_fd = open64(xkb->xkb_path, O_RDONLY)) == -1)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot open %s", xkb->xkb_path));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (pread64(xkb->xkb_fd, &xc->xc_hdr, sizeof (xc->xc_hdr), 0) !=
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * With FORMAT_CORE, all pages are in the dump (non-existing
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * ones are zeroed out).
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (pread64(xkb->xkb_fd, xkb->xkb_vcpu_data, sz,
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Try to map all the data pages. If we can't, fall back to the
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * window/pread() approach, which is significantly slower.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages = mmap(NULL, PAGE_SIZE * xkb->xkb_nr_pages,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab PROT_READ, MAP_SHARED, xkb->xkb_fd, xc->xc_hdr.xch_pages_offset);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * We'd like to adapt for correctness' sake, but we have no way of
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * detecting a PAE guest, since cr4 writes are disallowed.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((notes = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Now we know this is indeed a hypervisor core dump, even if
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * it's corrupted.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "XEN_ELFNOTE_DUMPCORE_HEADER\n"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sizeof (struct xc_elf_header));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (nhdr->n_descsz < sizeof (struct xc_elf_version)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "XEN_ELFNOTE_DUMPCORE_XEN_VERSION\n"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sizeof (struct xc_elf_version));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "version %d (expected 0)\n",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "version %d (expected 1)\n",
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_is_hvm = xe->xe_hdr.xeh_magic == XC_CORE_MAGIC_HVM;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_is_pae = (strstr(xe->xe_version.xev_capabilities,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_prstatus");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot find section .xen_prstatus"));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (sect->gs_shdr.sh_entsize < sizeof (vcpu_guest_context_t))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid section .xen_prstatus"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_nr_vcpus = sect->gs_shdr.sh_size / sect->gs_shdr.sh_entsize;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data = mdb_gelf_sect_load(xe->xe_gelf, sect);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot load section .xen_prstatus"));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data_sz = sect->gs_shdr.sh_size;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * The vcpu_guest_context structures saved in the core file
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * are actually unions of the 64-bit and 32-bit versions.
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * Don't rely on the entry size to match the size of
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * the structure, but set up an array of pointers.
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pages");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot find section .xen_pages"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, ".xen_pages is not page aligned"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Try to map all the data pages. If we can't, fall back to the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * window/pread() approach, which is significantly slower.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages = mmap(NULL, PAGE_SIZE * xkb->xkb_nr_pages,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab PROT_READ, MAP_SHARED, xkb->xkb_fd, xkb->xkb_pages_off);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic void
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*ARGSUSED*/
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_open(const char *namelist, const char *corefile, const char *swapfile,
5d2eda970e48f8985448151c73e699614ce9f357John Levon for (i = 0; i < 4; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "invalid debug info magic %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_info.di_version != DEBUG_INFO_VERSION) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "unknown debug info version %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "cannot construct namelist"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < 4; i++) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = (xkb->xkb_nr_pages * sizeof (mfn_t)) + (PAGE_SIZE * 2);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee mdb_free(xkb->xkb_vcpu_data, xkb->xkb_vcpu_data_sz);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_io_t *io = mdb_memio_create(xkb->xkb_namelist, xkb->xkb_namesize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_warn("failed to create namelist from %s", xkb->xkb_path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_getmregs(xkb_t *xkb, uint_t cpu, struct privmregs *mregs)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&vcpu->ctrlreg, &mregs->pm_cr, 8 * sizeof (ulong_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&vcpu->debugreg, &mregs->pm_dr, 8 * sizeof (ulong_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };