xenctx: compat-mode/HVM support

Add support to xenctx for guests that have a different word size
to the tools (x86 only, but shouldn't break ia64).  Again, only 32-bit
HVM guests are supported until EFER.LMA is easier to get at.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
This commit is contained in:
Keir Fraser committed 2009-01-05 11:08:53 +00:00
1 parent 446b916ca1
commit 1d6e30c679
1 file changed
+186 -106
+186 -106
View File
@@ -24,6 +24,8 @@
#include <getopt.h>
#include "xenctrl.h"
#include <xen/foreign/x86_32.h>
#include <xen/foreign/x86_64.h>
int xc_handle = 0;
int domid = 0;
@@ -31,28 +33,18 @@ int frame_ptrs = 0;
int stack_trace = 0;
int disp_all = 0;
#if defined (__i386__)
#if defined (__OpenBSD__)
#define FMT_SIZE_T "%08lx"
#define INSTR_POINTER(regs) (unsigned long)(regs->eip)
#else
#define FMT_SIZE_T "%08x"
#define INSTR_POINTER(regs) (regs->eip)
#endif
#define STACK_POINTER(regs) (regs->esp)
#define FRAME_POINTER(regs) (regs->ebp)
#define STACK_ROWS 4
#define STACK_COLS 8
#elif defined (__x86_64__)
#define FMT_SIZE_T "%016lx"
#define STACK_POINTER(regs) (regs->rsp)
#define FRAME_POINTER(regs) (regs->rbp)
#define INSTR_POINTER(regs) (regs->rip)
#define STACK_ROWS 4
#define STACK_COLS 4
#if defined (__i386__) || defined (__x86_64__)
typedef unsigned long long guest_word_t;
#define FMT_32B_WORD "%08llx"
#define FMT_64B_WORD "%016llx"
/* Word-length of the guest's own data structures */
int guest_word_size = sizeof (unsigned long);
/* Word-length of the context record we get from xen */
int ctxt_word_size = sizeof (unsigned long);
#elif defined (__ia64__)
/* On ia64, we can't translate virtual address to physical address. */
#define NO_TRANSLATION
typedef size_t guest_word_t;
/* Which registers should be displayed. */
int disp_cr_regs;
@@ -63,22 +55,19 @@ int disp_tlb;
#endif
struct symbol {
size_t address;
guest_word_t address;
char type;
char *name;
struct symbol *next;
} *symbol_table = NULL;
size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, kernel_hypercallpage;
static int is_kernel_text(size_t addr)
static int is_kernel_text(guest_word_t addr)
{
#if defined (__i386__)
#if defined (__i386__) || defined (__x86_64__)
if (symbol_table == NULL)
return (addr > 0xc000000);
#elif defined (__x86_64__)
if (symbol_table == NULL)
return (addr > 0xffffffff80000000UL);
return (addr > ((guest_word_size == 4) ? 0xc000000 : 0xffffffff80000000ULL));
#elif defined (__ia64__)
if (symbol_table == NULL)
return (addr > 0xa000000000000000UL);
@@ -134,7 +123,7 @@ static void insert_symbol(struct symbol *symbol)
prev = symbol;
}
static struct symbol *lookup_symbol(size_t address)
static struct symbol *lookup_symbol(guest_word_t address)
{
struct symbol *s = symbol_table;
@@ -147,7 +136,7 @@ static struct symbol *lookup_symbol(size_t address)
return NULL;
}
static void print_symbol(size_t addr)
static void print_symbol(guest_word_t addr)
{
struct symbol *s;
@@ -255,21 +244,23 @@ static void print_flags(uint64_t flags)
printf("\n");
}
static void print_special(unsigned long *regs, const char *name, unsigned int mask)
static void print_special(void *regs, const char *name, unsigned int mask, int width)
{
unsigned int i;
printf("\n");
for (i = 0; mask; mask >>= 1, ++i)
if (mask & 1)
printf("%s%u: " FMT_SIZE_T "\n", name, i, (size_t)regs[i]);
if (mask & 1) {
if (width == 4)
printf("%s%u: %08"PRIx32"\n", name, i, ((uint32_t *) regs)[i]);
else
printf("%s%u: %08"PRIx64"\n", name, i, ((uint64_t *) regs)[i]);
}
}
#endif
#ifdef __i386__
static void print_ctx(vcpu_guest_context_t *ctx1)
static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
{
struct cpu_user_regs *regs = &ctx1->user_regs;
struct cpu_user_regs_x86_32 *regs = &ctx->user_regs;
printf("cs:eip: %04x:%08x ", regs->cs, regs->eip);
print_symbol(regs->eip);
@@ -291,54 +282,87 @@ static void print_ctx(vcpu_guest_context_t *ctx1)
printf(" gs: %04x\n", regs->gs);
if (disp_all) {
print_special(ctx1->ctrlreg, "cr", 0x1d);
print_special(ctx1->debugreg, "dr", 0xcf);
print_special(ctx->ctrlreg, "cr", 0x1d, 4);
print_special(ctx->debugreg, "dr", 0xcf, 4);
}
}
#elif defined(__x86_64__)
static void print_ctx(vcpu_guest_context_t *ctx1)
{
struct cpu_user_regs *regs = &ctx1->user_regs;
printf("rip: %016lx ", regs->rip);
static void print_ctx_64(vcpu_guest_context_x86_64_t *ctx)
{
struct cpu_user_regs_x86_64 *regs = &ctx->user_regs;
printf("rip: %016"PRIx64" ", regs->rip);
print_symbol(regs->rip);
print_flags(regs->rflags);
printf("rsp: %016lx\n", regs->rsp);
printf("rsp: %016"PRIx64"\n", regs->rsp);
printf("rax: %016lx\t", regs->rax);
printf("rcx: %016lx\t", regs->rcx);
printf("rdx: %016lx\n", regs->rdx);
printf("rax: %016"PRIx64"\t", regs->rax);
printf("rcx: %016"PRIx64"\t", regs->rcx);
printf("rdx: %016"PRIx64"\n", regs->rdx);
printf("rbx: %016lx\t", regs->rbx);
printf("rsi: %016lx\t", regs->rsi);
printf("rdi: %016lx\n", regs->rdi);
printf("rbx: %016"PRIx64"\t", regs->rbx);
printf("rsi: %016"PRIx64"\t", regs->rsi);
printf("rdi: %016"PRIx64"\n", regs->rdi);
printf("rbp: %016lx\t", regs->rbp);
printf(" r8: %016lx\t", regs->r8);
printf(" r9: %016lx\n", regs->r9);
printf("rbp: %016"PRIx64"\t", regs->rbp);
printf(" r8: %016"PRIx64"\t", regs->r8);
printf(" r9: %016"PRIx64"\n", regs->r9);
printf("r10: %016lx\t", regs->r10);
printf("r11: %016lx\t", regs->r11);
printf("r12: %016lx\n", regs->r12);
printf("r10: %016"PRIx64"\t", regs->r10);
printf("r11: %016"PRIx64"\t", regs->r11);
printf("r12: %016"PRIx64"\n", regs->r12);
printf("r13: %016lx\t", regs->r13);
printf("r14: %016lx\t", regs->r14);
printf("r15: %016lx\n", regs->r15);
printf("r13: %016"PRIx64"\t", regs->r13);
printf("r14: %016"PRIx64"\t", regs->r14);
printf("r15: %016"PRIx64"\n", regs->r15);
printf(" cs: %04x\t", regs->cs);
printf(" ss: %04x\t", regs->ss);
printf(" ds: %04x\t", regs->ds);
printf(" es: %04x\n", regs->es);
printf(" fs: %04x @ %016lx\n", regs->fs, ctx1->fs_base);
printf(" gs: %04x @ %016lx/%016lx\n", regs->gs,
ctx1->gs_base_kernel, ctx1->gs_base_user);
printf(" fs: %04x @ %016"PRIx64"\n", regs->fs, ctx->fs_base);
printf(" gs: %04x @ %016"PRIx64"/%016"PRIx64"\n", regs->gs,
ctx->gs_base_kernel, ctx->gs_base_user);
if (disp_all) {
print_special(ctx1->ctrlreg, "cr", 0x1d);
print_special(ctx1->debugreg, "dr", 0xcf);
print_special(ctx->ctrlreg, "cr", 0x1d, 8);
print_special(ctx->debugreg, "dr", 0xcf, 8);
}
}
static void print_ctx(vcpu_guest_context_any_t *ctx)
{
if (ctxt_word_size == 4)
print_ctx_32(&ctx->x32);
else
print_ctx_64(&ctx->x64);
}
static guest_word_t instr_pointer(vcpu_guest_context_any_t *ctx)
{
if (ctxt_word_size == 4)
return ctx->x32.user_regs.eip;
else
return ctx->x64.user_regs.rip;
}
static guest_word_t stack_pointer(vcpu_guest_context_any_t *ctx)
{
if (ctxt_word_size == 4)
return ctx->x32.user_regs.esp;
else
return ctx->x64.user_regs.rsp;
}
static guest_word_t frame_pointer(vcpu_guest_context_any_t *ctx)
{
if (ctxt_word_size == 4)
return ctx->x32.user_regs.ebp;
else
return ctx->x64.user_regs.rbp;
}
#elif defined(__ia64__)
#define PTE_ED_SHIFT 52
@@ -401,9 +425,9 @@ static void print_tr(int i, const struct ia64_tr_entry *tr)
tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
}
void print_ctx(vcpu_guest_context_t *ctx)
void print_ctx(vcpu_guest_context_any_t *ctx)
{
struct vcpu_guest_context_regs *regs = &ctx->regs;
struct vcpu_guest_context_regs *regs = &ctx.c->regs;
struct vcpu_tr_regs *tr = &ctx->regs.tr;
int i;
unsigned int rbs_size, cfm_sof;
@@ -584,7 +608,7 @@ void print_ctx(vcpu_guest_context_t *ctx)
#endif
#ifndef NO_TRANSLATION
static void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
static void *map_page(vcpu_guest_context_any_t *ctx, int vcpu, guest_word_t virt)
{
static unsigned long previous_mfn = 0;
static void *mapped = NULL;
@@ -611,33 +635,53 @@ static void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
return (void *)(mapped + offset);
}
static void print_stack(vcpu_guest_context_t *ctx, int vcpu)
static guest_word_t read_stack_word(guest_word_t *src, int width)
{
struct cpu_user_regs *regs = &ctx->user_regs;
size_t stack = STACK_POINTER(regs);
size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
size_t frame;
size_t instr;
size_t *p;
guest_word_t word = 0;
/* Little-endian only */
memcpy(&word, src, width);
return word;
}
static void print_stack_word(guest_word_t word, int width)
{
if (width == 4)
printf(FMT_32B_WORD, word);
else
printf(FMT_64B_WORD, word);
}
static void print_stack(vcpu_guest_context_any_t *ctx, int vcpu, int width)
{
guest_word_t stack = stack_pointer(ctx);
guest_word_t stack_limit;
guest_word_t frame;
guest_word_t instr;
guest_word_t word;
guest_word_t *p;
int i;
stack_limit = ((stack_pointer(ctx) + XC_PAGE_SIZE)
& ~((guest_word_t) XC_PAGE_SIZE - 1));
printf("\n");
printf("Stack:\n");
for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) {
for (i=1; i<5 && stack < stack_limit; i++) {
while(stack < stack_limit && stack < stack_pointer(ctx) + i*32) {
p = map_page(ctx, vcpu, stack);
printf(" " FMT_SIZE_T, *p);
stack += sizeof(stack);
word = read_stack_word(p, width);
printf(" ");
print_stack_word(word, width);
stack += width;
}
printf("\n");
}
printf("\n");
printf("Code:\n");
instr = INSTR_POINTER(regs) - 21;
instr = instr_pointer(ctx) - 21;
for(i=0; i<32; i++) {
unsigned char *c = map_page(ctx, vcpu, instr+i);
if (instr+i == INSTR_POINTER(regs))
if (instr+i == instr_pointer(ctx))
printf("<%02x> ", *c);
else
printf("%02x ", *c);
@@ -650,52 +694,65 @@ static void print_stack(vcpu_guest_context_t *ctx, int vcpu)
printf("Stack Trace:\n");
else
printf("Call Trace:\n");
printf("%c [<" FMT_SIZE_T ">] ",
stack_trace ? '*' : ' ', INSTR_POINTER(regs));
printf("%c [<", stack_trace ? '*' : ' ');
print_stack_word(instr_pointer(ctx), width);
printf(">] ");
print_symbol(INSTR_POINTER(regs));
print_symbol(instr_pointer(ctx));
printf(" <--\n");
if (frame_ptrs) {
stack = STACK_POINTER(regs);
frame = FRAME_POINTER(regs);
stack = stack_pointer(ctx);
frame = frame_pointer(ctx);
while(frame && stack < stack_limit) {
if (stack_trace) {
while (stack < frame) {
p = map_page(ctx, vcpu, stack);
printf("| " FMT_SIZE_T " ", *p);
printf("\n");
stack += sizeof(*p);
printf("| ");
print_stack_word(read_stack_word(p, width), width);
printf(" \n");
stack += width;
}
} else {
stack = frame;
}
p = map_page(ctx, vcpu, stack);
frame = *p;
if (stack_trace)
printf("|-- " FMT_SIZE_T "\n", *p);
stack += sizeof(*p);
frame = read_stack_word(p, width);
if (stack_trace) {
printf("|-- ");
print_stack_word(read_stack_word(p, width), width);
printf("\n");
}
stack += width;
if (frame) {
p = map_page(ctx, vcpu, stack);
printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
print_symbol(*p);
word = read_stack_word(p, width);
printf("%c [<", stack_trace ? '|' : ' ');
print_stack_word(word, width);
printf(">] ");
print_symbol(word);
printf("\n");
stack += sizeof(*p);
stack += width;
}
}
} else {
stack = STACK_POINTER(regs);
stack = stack_pointer(ctx);
while(stack < stack_limit) {
p = map_page(ctx, vcpu, stack);
if (is_kernel_text(*p)) {
printf(" [<" FMT_SIZE_T ">] ", *p);
print_symbol(*p);
word = read_stack_word(p, width);
if (is_kernel_text(word)) {
printf(" [<");
print_stack_word(word, width);
printf(">] ");
print_symbol(word);
printf("\n");
} else if (stack_trace) {
printf(" " FMT_SIZE_T "\n", *p);
printf(" ");
print_stack_word(word, width);
printf("\n");
}
stack += sizeof(*p);
stack += width;
}
}
}
@@ -729,10 +786,33 @@ static void dump_ctx(int vcpu)
exit(-1);
}
print_ctx(&ctx.c);
#if defined(__i386__) || defined(__x86_64__)
{
struct xen_domctl domctl;
memset(&domctl, 0, sizeof domctl);
domctl.domain = domid;
domctl.cmd = XEN_DOMCTL_get_address_size;
if (xc_domctl(xc_handle, &domctl) == 0)
ctxt_word_size = guest_word_size = domctl.u.address_size.size / 8;
if (dominfo.hvm) {
xen_capabilities_info_t xen_caps = "";
if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) {
perror("xc_version");
exit(-1);
}
/* HVM guest context records are always host-sized */
ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4;
/* XXX For now we can't tell whether a HVM guest is in long
* XXX mode; eventually fix this here and in xc_pagetab.c */
guest_word_size = 4;
}
}
#endif
print_ctx(&ctx);
#ifndef NO_TRANSLATION
if (is_kernel_text(INSTR_POINTER((&ctx.c.user_regs))))
print_stack(&ctx.c, vcpu);
if (is_kernel_text(instr_pointer(&ctx)))
print_stack(&ctx, vcpu, guest_word_size);
#endif
if (!dominfo.paused) {
@@ -774,9 +854,9 @@ static void usage(void)
int main(int argc, char **argv)
{
int ch;
static const char *sopts = "fs:h"
static const char *sopts = "fs:ha"
#ifdef __ia64__
"ar:"
"r:"
#endif
;
static const struct option lopts[] = {
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.