843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
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 *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
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 *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
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 *
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 *
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 */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <strings.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <stdio.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <stdlib.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <stddef.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <stdarg.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <unistd.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <fcntl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <gelf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <errno.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/mman.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/stat.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/debug_info.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/xen_mmu.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/elf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/machelf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/modctl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/kobj.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/kobj_impl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sysmacros.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/privmregs.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <vm/as.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <mdb/mdb_io.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <mdb/mdb_kb.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <mdb/mdb_target_impl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/public/xen.h>
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include <xen/public/version.h>
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#include <xen/public/elfnote.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_SHDR_NULL 0
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_SHDR_SYMTAB 1
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_SHDR_STRTAB 2
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_SHDR_SHSTRTAB 3
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_SHDR_NUM 4
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_WALK_LOCAL 0x1
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_WALK_GLOBAL 0x2
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_WALK_STR 0x4
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XKB_WALK_ALL (XKB_WALK_LOCAL | XKB_WALK_GLOBAL | XKB_WALK_STR)
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#if defined(__i386)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#define DEBUG_INFO 0xf4bff000
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define DEBUG_INFO_HVM 0xfe7ff000
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#elif defined(__amd64)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#define DEBUG_INFO 0xfffffffffb7ff000
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define DEBUG_INFO_HVM 0xfffffffffb7ff000
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#endif
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PAGE_SIZE 0x1000
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PAGE_SHIFT 12
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PAGE_OFFSET(a) ((a) & (PAGE_SIZE - 1))
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PAGE_MASK(a) ((a) & ~(PAGE_SIZE - 1))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#define PAGE_ALIGNED(a) (((a) & (PAGE_SIZE -1)) == 0)
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define PT_PADDR_LGPG 0x000fffffffffe000ull
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PT_PADDR 0x000ffffffffff000ull
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PT_VALID 0x1
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define PT_PAGESIZE 0x080
5d2eda970e48f8985448151c73e699614ce9f357John Levon#define PTE_IS_LGPG(p, l) ((l) > 0 && ((p) & PT_PAGESIZE))
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XC_CORE_MAGIC 0xF00FEBED
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XC_CORE_MAGIC_HVM 0xF00FEBEE
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define VGCF_HVM_GUEST (1<<1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct xc_core_header {
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_magic;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_nr_vcpus;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_nr_pages;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_ctxt_offset;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_index_offset;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int xch_pages_offset;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} xc_core_header_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstruct xc_elf_header {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xeh_magic;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xeh_nr_vcpus;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xeh_nr_pages;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xeh_page_size;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab};
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstruct xc_elf_version {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xev_major;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xev_minor;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_extraversion_t xev_extra;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_compile_info_t xev_compile_info;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_capabilities_info_t xev_capabilities;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_changeset_info_t xev_changeset;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_platform_parameters_t xev_platform_parameters;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t xev_pagesize;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab};
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Either an old-style (3.0.4) core format, or the ELF format.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabtypedef enum {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab XKB_FORMAT_UNKNOWN = 0,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab XKB_FORMAT_CORE = 1,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab XKB_FORMAT_ELF = 2
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab} xkb_type_t;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct mfn_map {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_t mm_mfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *mm_map;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} mfn_map_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct mmu_info {
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t mi_max;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t mi_shift[4];
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t mi_ptes;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t mi_ptesize;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} mmu_info_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabtypedef struct xkb_core {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xc_core_header_t xc_hdr;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab void *xc_p2m_buf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab} xkb_core_t;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabtypedef struct xkb_elf {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_file_t *xe_gelf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t *xe_off;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct xc_elf_header xe_hdr;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct xc_elf_version xe_version;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab} xkb_elf_t;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct xkb {
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xkb_path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int xkb_fd;
5d2eda970e48f8985448151c73e699614ce9f357John Levon int xkb_is_hvm;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_type_t xkb_type;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_core_t xkb_core;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_elf_t xkb_elf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t xkb_nr_vcpus;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t xkb_nr_pages;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t xkb_pages_off;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xen_pfn_t xkb_max_pfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_t xkb_max_mfn;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int xkb_is_pae;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev mmu_info_t xkb_mmu;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab debug_info_t xkb_info;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee void *xkb_vcpu_data;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee size_t xkb_vcpu_data_sz;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee struct vcpu_guest_context **xkb_vcpus;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *xkb_pages;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_t *xkb_p2m;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xen_pfn_t *xkb_m2p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_map_t xkb_pt_map[4];
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_map_t xkb_map;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *xkb_namelist;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t xkb_namesize;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} xkb_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const char xkb_shstrtab[] = "\0.symtab\0.strtab\0.shstrtab\0";
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct xkb_namelist {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Ehdr kh_elf_hdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev Phdr kh_text_phdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev Phdr kh_data_phdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev Shdr kh_shdr[XKB_SHDR_NUM];
843e19887f64dde75055cf8842fc4db2171eff45johnlev char shstrings[sizeof (xkb_shstrtab)];
843e19887f64dde75055cf8842fc4db2171eff45johnlev} xkb_namelist_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xkb_build_ksyms(xkb_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic offset_t xkb_mfn_to_offset(xkb_t *, mfn_t);
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 *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xkb_close(xkb_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Jump through the hoops we need to to correctly identify a core file
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * of either the old or new format.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_identify(const char *file, int *longmode)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xc_core_header_t header;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_file_t *gf = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_sect_t *sect = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_io_t *io = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *notes = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *pos;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int ret = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int fd;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((fd = open64(file, O_RDONLY)) == -1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pread64(fd, &header, sizeof (header), 0) != sizeof (header)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) close(fd);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) close(fd);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (header.xch_magic == XC_CORE_MAGIC) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *longmode = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Indeed.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = header.xch_index_offset - header.xch_ctxt_offset;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#ifdef _LP64
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sizeof (struct vcpu_guest_context) *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab header.xch_nr_vcpus == sz)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *longmode = 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#else
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sizeof (struct vcpu_guest_context) *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab header.xch_nr_vcpus != sz)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *longmode = 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif /* _LP64 */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((io = mdb_fdio_create_path(NULL, file, O_RDONLY, 0)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (-1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((gf = mdb_gelf_create(io, ET_NONE, GF_FILE)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab goto out;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((sect = mdb_gelf_sect_by_name(gf, ".note.Xen")) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab goto out;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((notes = mdb_gelf_sect_load(gf, sect)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab goto out;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct xc_elf_version *vers;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab Elf64_Nhdr *nhdr = (Elf64_Nhdr *)pos;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *desc;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *name;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab name = pos + sizeof (*nhdr);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab pos = desc + nhdr->n_descsz;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (nhdr->n_type != XEN_ELFNOTE_DUMPCORE_XEN_VERSION)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab continue;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
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 */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab vers = (struct xc_elf_version *)desc;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (strstr(vers->xev_capabilities, "x86_64")) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /*
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 */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (gf->gf_ehdr.e_machine == EM_386)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee *longmode = 0;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee else
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee *longmode = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else if (strstr(vers->xev_capabilities, "x86_32") ||
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab strstr(vers->xev_capabilities, "x86_32p")) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /*
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee * 32-bit hypervisor, can only be a 32-bit core.
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *longmode = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_warn("couldn't derive word size of dump; "
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "assuming 64-bit");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *longmode = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab ret = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabout:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (gf != NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_destroy(gf);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab else if (io != NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_io_destroy(io);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_fail(xkb_t *xkb, const char *msg, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_list args;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_start(args, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) fprintf(stderr, "%s: ", xkb->xkb_path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) vfprintf(stderr, msg, args);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) fprintf(stderr, "\n");
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_end(args);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xkb_close(xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab errno = ENOEXEC;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_build_m2p(xkb_t *xkb)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (i = 0; i <= xkb->xkb_max_pfn; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_p2m[i] != MFN_INVALID &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_p2m[i] > xkb->xkb_max_mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_max_mfn = xkb->xkb_p2m[i];
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_m2p = mdb_alloc((xkb->xkb_max_mfn + 1) * sizeof (xen_pfn_t),
843e19887f64dde75055cf8842fc4db2171eff45johnlev UM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i <= xkb->xkb_max_mfn; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_m2p[i] = PFN_INVALID;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (i = 0; i <= xkb->xkb_max_pfn; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_p2m[i] != MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_m2p[xkb->xkb_p2m[i]] = i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
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 */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_map_p2m(xkb_t *xkb)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev offset_t off;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t size;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_core_t *xc = &xkb->xkb_core;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t count = xkb->xkb_nr_pages;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t boff = xc->xc_hdr.xch_index_offset;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size = (sizeof (mfn_t) * count) + (PAGE_SIZE * 2);
843e19887f64dde75055cf8842fc4db2171eff45johnlev size = PAGE_MASK(size);
843e19887f64dde75055cf8842fc4db2171eff45johnlev off = PAGE_MASK(boff);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xc->xc_p2m_buf = (mfn_t *)mmap(NULL, size, PROT_READ,
843e19887f64dde75055cf8842fc4db2171eff45johnlev MAP_SHARED, xkb->xkb_fd, off);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xc->xc_p2m_buf == (xen_pfn_t *)MAP_FAILED) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xkb_fail(xkb, "cannot map p2m table");
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_p2m = (mfn_t *)((char *)xc->xc_p2m_buf +
843e19887f64dde75055cf8842fc4db2171eff45johnlev PAGE_OFFSET(boff));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*
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 */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic int
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_build_p2m(xkb_t *xkb)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_elf_t *xe = &xkb->xkb_elf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_sect_t *sect;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t size;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t i;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct elf_p2m {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t pfn;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t gmfn;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } *p2m;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_p2m");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sect == NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (void) xkb_fail(xkb, "cannot find section .xen_p2m");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (0);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((p2m = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (void) xkb_fail(xkb, "couldn't read .xen_p2m");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (0);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (i = 0; i < xkb->xkb_nr_pages; i++) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (p2m[i].pfn > xkb->xkb_max_pfn)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_max_pfn = p2m[i].pfn;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_p2m = mdb_alloc(size, UM_SLEEP);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size = sizeof (size_t) * (xkb->xkb_max_pfn + 1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xe->xe_off = mdb_alloc(size, UM_SLEEP);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (i = 0; i <= xkb->xkb_max_pfn; i++) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_p2m[i] = PFN_INVALID;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xe->xe_off[i] = (size_t)-1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (i = 0; i < xkb->xkb_nr_pages; i++) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_p2m[p2m[i].pfn] = p2m[i].gmfn;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xe->xe_off[p2m[i].pfn] = i;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
5d2eda970e48f8985448151c73e699614ce9f357John Levon/*
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 */
5d2eda970e48f8985448151c73e699614ce9f357John Levonstatic int
5d2eda970e48f8985448151c73e699614ce9f357John Levonxkb_build_fake_p2m(xkb_t *xkb)
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb_elf_t *xe = &xkb->xkb_elf;
5d2eda970e48f8985448151c73e699614ce9f357John Levon mdb_gelf_sect_t *sect;
5d2eda970e48f8985448151c73e699614ce9f357John Levon size_t size;
5d2eda970e48f8985448151c73e699614ce9f357John Levon size_t i;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon uint64_t *p2pfn;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pfn");
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (sect == NULL) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon (void) xkb_fail(xkb, "cannot find section .xen_pfn");
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (0);
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon if ((p2pfn = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon (void) xkb_fail(xkb, "couldn't read .xen_pfn");
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (0);
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon for (i = 0; i < xkb->xkb_nr_pages; i++) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (p2pfn[i] != PFN_INVALID && p2pfn[i] > xkb->xkb_max_pfn)
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_max_pfn = p2pfn[i];
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon size = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1);
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_p2m = mdb_alloc(size, UM_SLEEP);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
5d2eda970e48f8985448151c73e699614ce9f357John Levon size = sizeof (size_t) * (xkb->xkb_max_pfn + 1);
5d2eda970e48f8985448151c73e699614ce9f357John Levon xe->xe_off = mdb_alloc(size, UM_SLEEP);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon for (i = 0; i <= xkb->xkb_max_pfn; i++) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_p2m[i] = PFN_INVALID;
5d2eda970e48f8985448151c73e699614ce9f357John Levon xe->xe_off[i] = (size_t)-1;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon for (i = 0; i < xkb->xkb_nr_pages; i++) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (p2pfn[i] == PFN_INVALID)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee continue;
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_p2m[p2pfn[i]] = p2pfn[i];
5d2eda970e48f8985448151c73e699614ce9f357John Levon xe->xe_off[p2pfn[i]] = i;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (1);
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Return the MFN of the top-level page table for the given as.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mfn_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_as_to_mfn(xkb_t *xkb, struct as *as)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t asp = (uintptr_t)as;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t hatp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t htablep;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t pfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, asp + offsetof(struct as, a_hat), &hatp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, hatp + xkb->xkb_info.di_hat_htable_off,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &htablep))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, htablep + xkb->xkb_info.di_ht_pfn_off,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &pfn))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (pfn > xkb->xkb_max_pfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb->xkb_p2m[pfn]);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levonstatic mfn_t
5d2eda970e48f8985448151c73e699614ce9f357John Levonxkb_cr3_to_pfn(xkb_t *xkb)
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee uint64_t cr3 = xkb->xkb_vcpus[0]->ctrlreg[3];
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (xkb->xkb_is_hvm)
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (cr3 >> PAGE_SHIFT);
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (xen_cr3_to_pfn(cr3));
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
5d2eda970e48f8985448151c73e699614ce9f357John Levon
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ssize_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_helper(xkb_t *xkb, struct as *as, int phys, uint64_t addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev void *buf, size_t size)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t left = size;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int windowed = (xkb->xkb_pages == NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon mfn_t tlmfn = xkb_cr3_to_pfn(xkb);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (left) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint64_t pos = addr + (size - left);
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *outpos = (char *)buf + (size - left);
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t pageoff = PAGE_OFFSET(pos);
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t sz = MIN(left, PAGE_SIZE - pageoff);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_t mfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!phys) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn = xkb_va_to_mfn(xkb, pos, tlmfn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mfn == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xen_pfn_t pfn = pos >> PAGE_SHIFT;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (pfn > xkb->xkb_max_pfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn = xkb->xkb_p2m[pfn];
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mfn == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we're windowed then pread() is much faster.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (windowed) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev offset_t off = xkb_mfn_to_offset(xkb, mfn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (off == ~1ULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev off += pageoff;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = pread64(xkb->xkb_fd, outpos, sz, off);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret == -1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret != sz)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((size - left) + ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev left -= ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_map_mfn(xkb, mfn, &xkb->xkb_map) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(xkb->xkb_map.mm_map + pageoff, outpos, sz);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev left -= sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (size);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ssize_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_pread(xkb_t *xkb, uint64_t addr, void *buf, size_t size)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_read_helper(xkb, NULL, 1, addr, buf, size));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ssize_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_aread(xkb_t *xkb, uintptr_t addr, void *buf, size_t size, struct as *as)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_read_helper(xkb, as, 0, addr, buf, size));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic ssize_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read(xkb_t *xkb, uintptr_t addr, void *buf, size_t size)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_aread(xkb, addr, buf, size, NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_read_word(xkb_t *xkb, uintptr_t addr, uintptr_t *buf)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, addr, buf, sizeof (uintptr_t)) !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (uintptr_t))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_readstr(xkb_t *xkb, uintptr_t addr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *str = mdb_alloc(1024, UM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < 1024; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, addr + i, &str[i], 1) != 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(str, 1024);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (str[i] == '\0')
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == 1024) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(str, 1024);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (str);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic offset_t
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_pfn_to_off(xkb_t *xkb, xen_pfn_t pfn)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (pfn == PFN_INVALID || pfn > xkb->xkb_max_pfn)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (-1ULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_type == XKB_FORMAT_CORE)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (PAGE_SIZE * pfn);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (PAGE_SIZE * (xkb->xkb_elf.xe_off[pfn]));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic offset_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_mfn_to_offset(xkb_t *xkb, mfn_t mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xen_pfn_t pfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mfn > xkb->xkb_max_mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pfn = xkb->xkb_m2p[mfn];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pfn == PFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb->xkb_pages_off + xkb_pfn_to_off(xkb, pfn));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_map_mfn(xkb_t *xkb, mfn_t mfn, mfn_map_t *mm)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int windowed = (xkb->xkb_pages == NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev offset_t off;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mm->mm_mfn == mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mm->mm_map);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mm->mm_mfn = mfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (windowed) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mm->mm_map != (char *)MAP_FAILED) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) munmap(mm->mm_map, PAGE_SIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mm->mm_map = (void *)MAP_FAILED;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((off = xkb_mfn_to_offset(xkb, mfn)) == (-1ULL))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mm->mm_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_fd, off);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mm->mm_map == (char *)MAP_FAILED)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xen_pfn_t pfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mm->mm_map = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mfn > xkb->xkb_max_mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev pfn = xkb->xkb_m2p[mfn];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (pfn == PFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mm->mm_map = xkb->xkb_pages + xkb_pfn_to_off(xkb, pfn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mm->mm_map);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levonstatic uint64_t
5d2eda970e48f8985448151c73e699614ce9f357John Levonxkb_get_pte(mmu_info_t *mmu, char *ptep)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t pte = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (mmu->mi_ptesize == 8) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab pte = *((uint64_t *)ptep);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev pte = *((uint32_t *)ptep);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (pte);
5d2eda970e48f8985448151c73e699614ce9f357John Levon}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levonstatic mfn_t
5d2eda970e48f8985448151c73e699614ce9f357John Levonxkb_pte_to_base_mfn(uint64_t pte, size_t level)
5d2eda970e48f8985448151c73e699614ce9f357John Levon{
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (PTE_IS_LGPG(pte, level)) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon pte &= PT_PADDR_LGPG;
5d2eda970e48f8985448151c73e699614ce9f357John Levon } else {
5d2eda970e48f8985448151c73e699614ce9f357John Levon pte &= PT_PADDR;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (pte >> PAGE_SHIFT);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Resolve the given VA into an MFN, using the provided mfn as a top-level page
843e19887f64dde75055cf8842fc4db2171eff45johnlev * table.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mfn_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_va_to_mfn(xkb_t *xkb, uintptr_t va, mfn_t mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev mmu_info_t *mmu = &xkb->xkb_mmu;
5d2eda970e48f8985448151c73e699614ce9f357John Levon uint64_t pte;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t level;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (level = mmu->mi_max; ; --level) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t entry;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_map_mfn(xkb, mfn, &xkb->xkb_pt_map[level]) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev entry = (va >> mmu->mi_shift[level]) & (mmu->mi_ptes - 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon pte = xkb_get_pte(mmu, (char *)xkb->xkb_pt_map[level].mm_map +
5d2eda970e48f8985448151c73e699614ce9f357John Levon entry * mmu->mi_ptesize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon if ((mfn = xkb_pte_to_base_mfn(pte, level)) == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (MFN_INVALID);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (level == 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon /*
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 */
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (PTE_IS_LGPG(pte, level)) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon mfn += (va & ((1 << mmu->mi_shift[level]) - 1)) >>
5d2eda970e48f8985448151c73e699614ce9f357John Levon PAGE_SHIFT;
5d2eda970e48f8985448151c73e699614ce9f357John Levon break;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mfn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
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{
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, modulep, module, sizeof (struct module)) !=
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (struct module))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, (uintptr_t)module->symhdr +
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(Shdr, sh_addr), sym_addr))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, (uintptr_t)module->strhdr +
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(Shdr, sh_addr), str_addr))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb, (uintptr_t)module->symhdr +
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(Shdr, sh_size), sym_count))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *sym_count /= sizeof (Sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
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{
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < sym_count; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Sym sym;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *name;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int type = XKB_WALK_GLOBAL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, sym_addr + i * sizeof (sym), &sym,
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (sym)) != sizeof (sym))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (GELF_ST_BIND(sym.st_info) == STB_LOCAL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev type = XKB_WALK_LOCAL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev name = xkb_readstr(xkb, str_addr + sym.st_name);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev sym.st_shndx = SHN_ABS;
843e19887f64dde75055cf8842fc4db2171eff45johnlev sym.st_name = sizes[XKB_WALK_STR];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizes[type] += sizeof (sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sz = strlen(name) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizes[XKB_WALK_STR] += sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (buf != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (types & type) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&sym, *buf, sizeof (sym));
843e19887f64dde75055cf8842fc4db2171eff45johnlev *buf += sizeof (sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (types & XKB_WALK_STR) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(name, *buf, sz);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *buf += sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(name, 1024);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_walk_syms(xkb_t *xkb, uintptr_t modhead, char **buf,
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t *sizes, int types)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t modctl = modhead;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t modulep;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct module module;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t sym_count;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t sym_addr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t str_addr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t max_iter = 500;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bzero(sizes, sizeof (*sizes) * (XKB_WALK_STR + 1));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * empty first symbol
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizes[XKB_WALK_LOCAL] += sizeof (Sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizes[XKB_WALK_STR] += 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (buf != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (types & XKB_WALK_LOCAL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev Sym tmp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev bzero(&tmp, sizeof (tmp));
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&tmp, *buf, sizeof (tmp));
843e19887f64dde75055cf8842fc4db2171eff45johnlev *buf += sizeof (tmp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (types & XKB_WALK_STR) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev **buf = '\0';
843e19887f64dde75055cf8842fc4db2171eff45johnlev (*buf)++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (;;) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb,
843e19887f64dde75055cf8842fc4db2171eff45johnlev modctl + offsetof(struct modctl, mod_mp), &modulep))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (modulep == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto next;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_module(xkb, modulep, &module, &sym_addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &sym_count, &str_addr))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((module.flags & KOBJ_NOKSYMS))
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto next;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_modsyms(xkb, buf, sizes, types, sym_addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev str_addr, sym_count))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevnext:
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_read_word(xkb,
843e19887f64dde75055cf8842fc4db2171eff45johnlev modctl + offsetof(struct modctl, mod_next), &modctl))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (modctl == modhead)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Try and prevent us looping forever if we have a broken list.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (--max_iter == 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
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 */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_build_ksyms(xkb_t *xkb)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev debug_info_t *info = &xkb->xkb_info;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t sizes[XKB_WALK_STR + 1];
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb_namelist_t *hdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *buf;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct modctl modules;
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t module;
843e19887f64dde75055cf8842fc4db2171eff45johnlev Shdr *shp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, info->di_modules, &modules,
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (struct modctl)) != sizeof (struct modctl))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev module = (uintptr_t)modules.mod_mp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, NULL, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XKB_WALK_LOCAL | XKB_WALK_GLOBAL | XKB_WALK_STR))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_namesize = sizeof (xkb_namelist_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_namesize += sizes[XKB_WALK_LOCAL];
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_namesize += sizes[XKB_WALK_GLOBAL];
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_namesize += sizes[XKB_WALK_STR];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xkb->xkb_namelist = mdb_zalloc(xkb->xkb_namesize, UM_SLEEP))
843e19887f64dde75055cf8842fc4db2171eff45johnlev == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED - alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr = (xkb_namelist_t *)xkb->xkb_namelist;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb_read(xkb, module + offsetof(struct module, hdr),
843e19887f64dde75055cf8842fc4db2171eff45johnlev &hdr->kh_elf_hdr, sizeof (Ehdr)) != sizeof (Ehdr))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
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_elf_hdr.e_phnum = 2;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_elf_hdr.e_shnum = XKB_SHDR_NUM;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_elf_hdr.e_shstrndx = XKB_SHDR_SHSTRTAB;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_text_phdr.p_type = PT_LOAD;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_text_phdr.p_vaddr = (Addr)info->di_s_text;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_text_phdr.p_memsz = (Word)(info->di_e_text - info->di_s_text);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_text_phdr.p_flags = PF_R | PF_X;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_data_phdr.p_type = PT_LOAD;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_data_phdr.p_vaddr = (Addr)info->di_s_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_data_phdr.p_memsz = (Word)(info->di_e_data - info->di_s_data);
843e19887f64dde75055cf8842fc4db2171eff45johnlev hdr->kh_data_phdr.p_flags = PF_R | PF_W | PF_X;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp = &hdr->kh_shdr[XKB_SHDR_SYMTAB];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_name = 1; /* xkb_shstrtab[1] = ".symtab" */
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_type = SHT_SYMTAB;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_offset = sizeof (xkb_namelist_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_size = sizes[XKB_WALK_LOCAL] + sizes[XKB_WALK_GLOBAL];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_link = XKB_SHDR_STRTAB;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_info = sizes[XKB_WALK_LOCAL] / sizeof (Sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addralign = sizeof (Addr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_entsize = sizeof (Sym);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp = &hdr->kh_shdr[XKB_SHDR_STRTAB];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_name = 9; /* xkb_shstrtab[9] = ".strtab" */
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_type = SHT_STRTAB;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_offset = sizeof (xkb_namelist_t) +
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizes[XKB_WALK_LOCAL] + sizes[XKB_WALK_GLOBAL];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_size = sizes[XKB_WALK_STR];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addralign = 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp = &hdr->kh_shdr[XKB_SHDR_SHSTRTAB];
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_name = 17; /* xkb_shstrtab[17] = ".shstrtab" */
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_type = SHT_STRTAB;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_offset = offsetof(xkb_namelist_t, shstrings);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_size = sizeof (xkb_shstrtab);
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addralign = 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(xkb_shstrtab, hdr->shstrings, sizeof (xkb_shstrtab));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev buf = xkb->xkb_namelist + sizeof (xkb_namelist_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XKB_WALK_LOCAL))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XKB_WALK_GLOBAL))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes,
843e19887f64dde75055cf8842fc4db2171eff45johnlev XKB_WALK_STR))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic xkb_t *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_open_core(xkb_t *xkb)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_core_t *xc = &xkb->xkb_core;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t sz;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee int i;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee struct vcpu_guest_context *vcp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_type = XKB_FORMAT_CORE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((xkb->xkb_fd = open64(xkb->xkb_path, O_RDONLY)) == -1)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot open %s", xkb->xkb_path));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (pread64(xkb->xkb_fd, &xc->xc_hdr, sizeof (xc->xc_hdr), 0) !=
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sizeof (xc->xc_hdr))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid dump file"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xc->xc_hdr.xch_magic == XC_CORE_MAGIC_HVM)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot process HVM images"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xc->xc_hdr.xch_magic != XC_CORE_MAGIC) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid magic %d",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xc->xc_hdr.xch_magic));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * With FORMAT_CORE, all pages are in the dump (non-existing
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * ones are zeroed out).
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_nr_pages = xc->xc_hdr.xch_nr_pages;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages_off = xc->xc_hdr.xch_pages_offset;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_max_pfn = xc->xc_hdr.xch_nr_pages - 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_nr_vcpus = xc->xc_hdr.xch_nr_vcpus;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data_sz = sz;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data = mdb_alloc(sz, UM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (pread64(xkb->xkb_fd, xkb->xkb_vcpu_data, sz,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xc->xc_hdr.xch_ctxt_offset) != sz)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot read VCPU contexts"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpus = mdb_alloc(sz, UM_SLEEP);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee vcp = xkb->xkb_vcpu_data;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee for (i = 0; i < xkb->xkb_nr_vcpus; i++)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpus[i] = &vcp[i];
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
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 */
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
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_pages == (char *)MAP_FAILED)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
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 */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_is_pae = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!xkb_map_p2m(xkb))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic xkb_t *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_open_elf(xkb_t *xkb)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_elf_t *xe = &xkb->xkb_elf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_sect_t *sect;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *notes;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *pos;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_io_t *io;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee size_t sz;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee int i;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee void *dp;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((io = mdb_fdio_create_path(NULL, xkb->xkb_path,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab O_RDONLY, 0)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "failed to open"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xe->xe_gelf = mdb_gelf_create(io, ET_NONE, GF_FILE);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xe->xe_gelf == NULL) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_io_destroy(io);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_fd = mdb_fdio_fileno(io);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".note.Xen");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sect == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((notes = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Now we know this is indeed a hypervisor core dump, even if
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * it's corrupted.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_type = XKB_FORMAT_ELF;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab Elf64_Nhdr *nhdr = (Elf64_Nhdr *)pos;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab uint64_t vers;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *desc;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab char *name;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab name = pos + sizeof (*nhdr);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab pos = desc + nhdr->n_descsz;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab switch (nhdr->n_type) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab case XEN_ELFNOTE_DUMPCORE_NONE:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab case XEN_ELFNOTE_DUMPCORE_HEADER:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (nhdr->n_descsz != sizeof (struct xc_elf_header)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid ELF note "
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "XEN_ELFNOTE_DUMPCORE_HEADER\n"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bcopy(desc, &xe->xe_hdr,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sizeof (struct xc_elf_header));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab case XEN_ELFNOTE_DUMPCORE_XEN_VERSION:
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (nhdr->n_descsz < sizeof (struct xc_elf_version)) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid ELF note "
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "XEN_ELFNOTE_DUMPCORE_XEN_VERSION\n"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bcopy(desc, &xe->xe_version,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sizeof (struct xc_elf_version));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab case XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /* LINTED - alignment */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab vers = *((uint64_t *)desc);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((vers >> 32) != 0) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "unknown major "
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "version %d (expected 0)\n",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (int)(vers >> 32)));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((vers & 0xffffffff) != 1) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_warn("unexpected dump minor number "
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "version %d (expected 1)\n",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (int)(vers & 0xffffffff));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab default:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_warn("unknown ELF note %d(%s)\n",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab nhdr->n_type, name);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab break;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_is_hvm = xe->xe_hdr.xeh_magic == XC_CORE_MAGIC_HVM;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (xe->xe_hdr.xeh_magic != XC_CORE_MAGIC &&
5d2eda970e48f8985448151c73e699614ce9f357John Levon xe->xe_hdr.xeh_magic != XC_CORE_MAGIC_HVM) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid magic %d",
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xe->xe_hdr.xeh_magic));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_nr_pages = xe->xe_hdr.xeh_nr_pages;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_is_pae = (strstr(xe->xe_version.xev_capabilities,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab "x86_32p") != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_prstatus");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sect == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot find section .xen_prstatus"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (sect->gs_shdr.sh_entsize < sizeof (vcpu_guest_context_t))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid section .xen_prstatus"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_nr_vcpus = sect->gs_shdr.sh_size / sect->gs_shdr.sh_entsize;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data = mdb_gelf_sect_load(xe->xe_gelf, sect);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (xkb->xkb_vcpu_data == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot load section .xen_prstatus"));
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpu_data_sz = sect->gs_shdr.sh_size;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee /*
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 */
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpus = mdb_alloc(sz, UM_SLEEP);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee for (i = 0; i < xkb->xkb_nr_vcpus; i++) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee dp = ((char *)xkb->xkb_vcpu_data +
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee i * sect->gs_shdr.sh_entsize);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_vcpus[i] = dp;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pages");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sect == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot find section .xen_pages"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!PAGE_ALIGNED(sect->gs_shdr.sh_offset))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, ".xen_pages is not page aligned"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (sect->gs_shdr.sh_entsize != PAGE_SIZE)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid section .xen_pages"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages_off = sect->gs_shdr.sh_offset;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Try to map all the data pages. If we can't, fall back to the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * window/pread() approach, which is significantly slower.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pages = mmap(NULL, PAGE_SIZE * xkb->xkb_nr_pages,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab PROT_READ, MAP_SHARED, xkb->xkb_fd, xkb->xkb_pages_off);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_pages == (char *)MAP_FAILED)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_pages = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (xkb->xkb_is_hvm) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!xkb_build_fake_p2m(xkb))
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon } else {
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (!xkb_build_p2m(xkb))
5d2eda970e48f8985448151c73e699614ce9f357John Levon return (NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabstatic void
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_init_mmu(xkb_t *xkb)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
843e19887f64dde75055cf8842fc4db2171eff45johnlev#if defined(__amd64)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_max = 3;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_shift[0] = 12;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_shift[1] = 21;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_shift[2] = 30;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_shift[3] = 39;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_ptes = 512;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_mmu.mi_ptesize = 8;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#elif defined(__i386)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_is_pae) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_max = 2;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_shift[0] = 12;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_shift[1] = 21;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_shift[2] = 30;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_ptes = 512;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_ptesize = 8;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_max = 1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_shift[0] = 12;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_shift[1] = 22;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_ptes = 1024;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_mmu.mi_ptesize = 4;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*ARGSUSED*/
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_t *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabxkb_open(const char *namelist, const char *corefile, const char *swapfile,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int flag, const char *err)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab{
5d2eda970e48f8985448151c73e699614ce9f357John Levon uintptr_t debug_info = DEBUG_INFO;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct stat64 corestat;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_t *xkb = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab size_t i;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (stat64(corefile, &corestat) == -1)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "cannot stat %s", corefile));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (flag != O_RDONLY)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (xkb_fail(xkb, "invalid open flags"));
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb = mdb_zalloc(sizeof (*xkb), UM_SLEEP);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
5d2eda970e48f8985448151c73e699614ce9f357John Levon for (i = 0; i < 4; i++) {
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_pt_map[i].mm_mfn = MFN_INVALID;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_pt_map[i].mm_map = (char *)MAP_FAILED;
5d2eda970e48f8985448151c73e699614ce9f357John Levon }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_type = XKB_FORMAT_UNKNOWN;
5d2eda970e48f8985448151c73e699614ce9f357John Levon xkb->xkb_map.mm_mfn = MFN_INVALID;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_map.mm_map = (char *)MAP_FAILED;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_core.xc_p2m_buf = (char *)MAP_FAILED;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_fd = -1;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb->xkb_path = strdup(corefile);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if ((xkb = xkb_open_elf(xkb)) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_type == XKB_FORMAT_UNKNOWN) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (!xkb_open_core(xkb))
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_init_mmu(xkb);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_build_m2p(xkb))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (xkb->xkb_is_hvm)
5d2eda970e48f8985448151c73e699614ce9f357John Levon debug_info = DEBUG_INFO_HVM;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (xkb_read(xkb, debug_info, &xkb->xkb_info,
843e19887f64dde75055cf8842fc4db2171eff45johnlev sizeof (xkb->xkb_info)) != sizeof (xkb->xkb_info))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "cannot read debug_info"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_info.di_magic != DEBUG_INFO_MAGIC) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "invalid debug info magic %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_info.di_magic));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_info.di_version != DEBUG_INFO_VERSION) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "unknown debug info version %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev xkb->xkb_info.di_version));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!xkb_build_ksyms(xkb))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb_fail(xkb, "cannot construct namelist"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xkb);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_close(xkb_t *xkb)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee size_t i, sz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_m2p != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(xkb->xkb_m2p,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (xkb->xkb_max_mfn + 1) * sizeof (xen_pfn_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_pages != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) munmap((void *)xkb->xkb_pages,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab PAGE_SIZE * xkb->xkb_nr_pages);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < 4; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *addr = xkb->xkb_pt_map[i].mm_map;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (addr != (char *)MAP_FAILED)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) munmap((void *)addr, PAGE_SIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_map.mm_map != (char *)MAP_FAILED) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) munmap((void *)xkb->xkb_map.mm_map,
843e19887f64dde75055cf8842fc4db2171eff45johnlev PAGE_SIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xkb->xkb_namelist != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(xkb->xkb_namelist, xkb->xkb_namesize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_type == XKB_FORMAT_ELF) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_elf_t *xe = &xkb->xkb_elf;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xe->xe_gelf != NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_gelf_destroy(xe->xe_gelf);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_p2m != NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_free(xkb->xkb_p2m, sz);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = sizeof (size_t) * (xkb->xkb_max_pfn + 1);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xe->xe_off != NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab mdb_free(xe->xe_off, sz);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else if (xkb->xkb_type == XKB_FORMAT_CORE) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab xkb_core_t *xc = &xkb->xkb_core;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xkb->xkb_fd != -1)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (void) close(xkb->xkb_fd);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = (xkb->xkb_nr_pages * sizeof (mfn_t)) + (PAGE_SIZE * 2);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab sz = PAGE_MASK(sz);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (xc->xc_p2m_buf != (xen_pfn_t *)MAP_FAILED)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (void) munmap(xc->xc_p2m_buf, sz);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (xkb->xkb_vcpu_data != NULL)
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee mdb_free(xkb->xkb_vcpu_data, xkb->xkb_vcpu_data_sz);
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee }
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee if (xkb->xkb_vcpus != NULL) {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee sz = sizeof (struct vcpu_guest_context *) *
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee xkb->xkb_nr_vcpus;
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee mdb_free(xkb->xkb_vcpus, sz);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev free(xkb->xkb_path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_free(xkb, sizeof (*xkb));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mdb_io_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_sym_io(xkb_t *xkb, const char *symfile)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_io_t *io = mdb_memio_create(xkb->xkb_namelist, xkb->xkb_namesize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (io == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev mdb_warn("failed to create namelist from %s", xkb->xkb_path);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (io);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevuint64_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_vtop(xkb_t *xkb, struct as *as, uintptr_t addr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
5d2eda970e48f8985448151c73e699614ce9f357John Levon mfn_t tlmfn = xkb_cr3_to_pfn(xkb);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn_t mfn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mfn = xkb_va_to_mfn(xkb, addr, tlmfn);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mfn == MFN_INVALID || mfn > xkb->xkb_max_mfn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1ULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (((uint64_t)xkb->xkb_m2p[mfn] << PAGE_SHIFT)
843e19887f64dde75055cf8842fc4db2171eff45johnlev | PAGE_OFFSET(addr));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxkb_getmregs(xkb_t *xkb, uint_t cpu, struct privmregs *mregs)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct vcpu_guest_context *vcpu;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct cpu_user_regs *ur;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct regs *regs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (cpu >= xkb->xkb_nr_vcpus) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev errno = EINVAL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bzero(mregs, sizeof (*mregs));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee vcpu = xkb->xkb_vcpus[cpu];
843e19887f64dde75055cf8842fc4db2171eff45johnlev ur = &vcpu->user_regs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs = &mregs->pm_gregs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_ss = ur->ss;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_cs = ur->cs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_ds = ur->ds;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_es = ur->es;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_fs = ur->fs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_gs = ur->gs;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_trapno = ur->entry_vector;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_err = ur->error_code;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#ifdef __amd64
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_savfp = ur->rbp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_savpc = ur->rip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rdi = ur->rdi;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rsi = ur->rsi;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rdx = ur->rdx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rcx = ur->rcx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r8 = ur->r8;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r9 = ur->r9;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rax = ur->rax;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rbx = ur->rbx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rbp = ur->rbp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r10 = ur->r10;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r11 = ur->r11;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r12 = ur->r12;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r13 = ur->r13;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r14 = ur->r14;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_r15 = ur->r15;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rip = ur->rip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rfl = ur->rflags;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_rsp = ur->rsp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#else
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_savfp = ur->ebp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_savpc = ur->eip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_edi = ur->edi;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_esi = ur->esi;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_ebp = ur->ebp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_esp = ur->esp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_ebx = ur->ebx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_edx = ur->edx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_ecx = ur->ecx;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_eax = ur->eax;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_eip = ur->eip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_efl = ur->eflags;
843e19887f64dde75055cf8842fc4db2171eff45johnlev regs->r_uesp = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#endif
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&vcpu->ctrlreg, &mregs->pm_cr, 8 * sizeof (ulong_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(&vcpu->debugreg, &mregs->pm_dr, 8 * sizeof (ulong_t));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mregs->pm_flags = PM_GREGS | PM_CRREGS | PM_DRREGS;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mdb_kb_ops_t xpv_kb_ops = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_open = (void *(*)())xkb_open,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_close = (int (*)())xkb_close,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_sym_io = (mdb_io_t *(*)())xkb_sym_io,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_kread = (ssize_t (*)())xkb_read,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_kwrite = (ssize_t (*)())mdb_tgt_notsup,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_aread = (ssize_t (*)())xkb_aread,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_awrite = (ssize_t (*)())mdb_tgt_notsup,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_pread = (ssize_t (*)())xkb_pread,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_pwrite = (ssize_t (*)())mdb_tgt_notsup,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_vtop = (uint64_t (*)())xkb_vtop,
843e19887f64dde75055cf8842fc4db2171eff45johnlev .kb_getmregs = (int (*)())xkb_getmregs
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevmdb_kb_ops_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevmdb_kb_ops(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (&xpv_kb_ops);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const mdb_dcmd_t dcmds[] = { NULL, };
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const mdb_walker_t walkers[] = { NULL, };
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevconst mdb_modinfo_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlev_mdb_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (&modinfo);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlev_mdb_fini(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev}