mdb_kb.c revision 843e19887f64dde75055cf8842fc4db2171eff45
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* KVM backend for hypervisor domain dumps. We don't use libkvm for such
* dumps, since they do not have a namelist file or the typical dump structures
* we expect to aid bootstrapping. Instead, we bootstrap based upon a
* debug_info structure at a known VA, using the guest's own page tables to
* resolve to physical addresses, and construct the namelist in a manner
* similar to ksyms_snapshot().
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <gelf.h>
#include <errno.h>
#include <sys/debug_info.h>
#include <sys/kobj_impl.h>
#include <sys/sysmacros.h>
#include <sys/privmregs.h>
#include <mdb/mdb_target_impl.h>
#if defined(__i386)
#define DEF_DEBUG_INFO_VA 0xfb3ff000
#define PAE_DEBUG_INFO_VA 0xf4bff000
#define DEF_DEBUG_INFO_VA 0xfffffffffb7ff000
#endif
#define XKB_SHDR_NULL 0
#define XKB_SHDR_SYMTAB 1
#define XKB_SHDR_STRTAB 2
#define XKB_SHDR_SHSTRTAB 3
#define XKB_SHDR_NUM 4
#define XKB_WALK_LOCAL 0x1
#define XKB_WALK_GLOBAL 0x2
#define XKB_WALK_STR 0x4
#define PAGE_SIZE 0x1000
#define PAGE_SHIFT 12
#define PT_PADDR 0x000ffffffffff000ull
#define PT_VALID 0x1
/*
* Once the headers are available easily from within ON, we can use those, but
* until then these definitions are duplicates.
*/
#define XC_CORE_MAGIC 0xF00FEBED
#define XC_CORE_MAGIC_HVM 0xF00FEBEE
typedef struct xc_core_header {
unsigned int xch_magic;
unsigned int xch_nr_vcpus;
unsigned int xch_nr_pages;
unsigned int xch_ctxt_offset;
unsigned int xch_index_offset;
unsigned int xch_pages_offset;
typedef struct mfn_map {
char *mm_map;
} mfn_map_t;
typedef struct mmu_info {
} mmu_info_t;
typedef struct xkb {
char *xkb_path;
int xkb_fd;
char *xkb_namelist;
struct vcpu_guest_context *xkb_ctxts;
char *xkb_pages;
void *xkb_p2m_buf;
} xkb_t;
static const char xkb_shstrtab[] = "\0.symtab\0.strtab\0.shstrtab\0";
typedef struct xkb_namelist {
char shstrings[sizeof (xkb_shstrtab)];
static int xkb_build_ksyms(xkb_t *);
int
{
int fd;
return (-1);
return (0);
}
return (0);
*longmode = 0;
/*
* Indeed.
*/
#ifdef _LP64
*longmode = 1;
#else
*longmode = 1;
#endif /* _LP64 */
return (1);
}
static void *
{
return (NULL);
}
static int
{
size_t i;
}
UM_SLEEP);
for (i = 0; i <= xkb->xkb_max_mfn; i++)
}
return (1);
}
/*
* Just to make things jolly fun, they've not page-aligned the p2m table.
*/
static int
{
/* LINTED - alignment */
return (0);
}
/* LINTED - alignment */
PAGE_OFFSET(boff));
return (1);
}
/*
* Return the MFN of the top-level page table for the given as.
*/
static mfn_t
{
return (MFN_INVALID);
&htablep))
return (MFN_INVALID);
&pfn))
return (MFN_INVALID);
return (MFN_INVALID);
}
static ssize_t
{
return (-1);
while (left) {
if (!phys) {
if (mfn == MFN_INVALID)
return (-1);
} else {
return (-1);
if (mfn == MFN_INVALID)
return (-1);
}
/*
* If we're windowed then pread() is much faster.
*/
if (windowed) {
int ret;
if (off == ~1ULL)
return (-1);
if (ret == -1)
return (-1);
} else {
return (-1);
}
}
return (size);
}
static ssize_t
{
}
static ssize_t
{
}
static ssize_t
{
}
static int
{
sizeof (uintptr_t))
return (0);
return (1);
}
static char *
{
size_t i;
for (i = 0; i < 1024; i++) {
return (NULL);
}
if (str[i] == '\0')
break;
}
if (i == 1024) {
return (NULL);
}
return (str);
}
static offset_t
{
return (-1ULL);
if (pfn == PFN_INVALID)
return (-1ULL);
}
static char *
{
if (windowed) {
}
return (NULL);
return (NULL);
} else {
return (NULL);
if (pfn == PFN_INVALID)
return (NULL);
}
}
static mfn_t
{
/* LINTED - alignment */
/* LINTED - alignment */
}
return (MFN_INVALID);
/* XXX: doesn't do large pages */
return (pte >> PAGE_SHIFT);
}
/*
* Resolve the given VA into an MFN, using the provided mfn as a top-level page
* table.
*/
static mfn_t
{
char *tmp;
return (MFN_INVALID);
return (MFN_INVALID);
if (level == 0)
break;
}
return (mfn);
}
static int
{
sizeof (struct module))
return (0);
return (0);
return (0);
return (0);
return (1);
}
static int
{
size_t i;
for (i = 0; i < sym_count; i++) {
char *name;
int type = XKB_WALK_GLOBAL;
return (0);
}
if (types & XKB_WALK_STR) {
}
}
}
return (1);
}
static int
{
/*
* empty first symbol
*/
if (types & XKB_WALK_LOCAL) {
}
if (types & XKB_WALK_STR) {
**buf = '\0';
(*buf)++;
}
}
for (;;) {
if (!xkb_read_word(xkb,
return (0);
goto next;
return (0);
goto next;
return (0);
next:
if (!xkb_read_word(xkb,
return (0);
break;
/*
* Try and prevent us looping forever if we have a broken list.
*/
if (--max_iter == 0)
break;
}
return (1);
}
/*
* Userspace equivalent of ksyms_snapshot(). Since we don't have a namelist
* file for hypervisor images, we fabricate one here using code similar
*/
static int
{
char *buf;
return (0);
return (0);
== NULL)
return (0);
/* LINTED - alignment */
return (0);
return (0);
return (0);
return (0);
return (1);
}
/*ARGSUSED*/
xkb_t *
{
size_t i;
for (i = 0; i < 4; i++)
}
/*
* Try to map all the data pages. If we can't, fall back to the
*/
#if defined(__amd64)
/*
* We'd like to adapt for correctness' sake, but we have no way of
* detecting a PAE guest, since cr4 writes are disallowed.
*/
#endif
if (!xkb_map_p2m(xkb))
return (NULL);
if (!xkb_build_m2p(xkb))
return (NULL);
}
}
if (!xkb_build_ksyms(xkb))
return (xkb);
}
int
{
size_t i;
return (0);
}
} else {
for (i = 0; i < 4; i++) {
if (addr != (char *)MAP_FAILED)
}
}
}
}
return (0);
}
/*ARGSUSED*/
static mdb_io_t *
{
return (io);
}
{
return (-1ULL);
return (-1ULL);
| PAGE_OFFSET(addr));
}
static int
{
struct vcpu_guest_context *vcpu;
struct cpu_user_regs *ur;
return (-1);
}
#ifdef __amd64
#else
#endif
return (0);
}
static mdb_kb_ops_t xpv_kb_ops = {
.kb_getmregs = (int (*)())xkb_getmregs
};
mdb_kb_ops(void)
{
return (&xpv_kb_ops);
}
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}
void
_mdb_fini(void)
{
}