[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xenctx: compat-mode/HVM support



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1231153733 0
# Node ID 9cc632cc6d400685679671b6bbc58dfe4c5e287e
# Parent  34f52eafd4e32b297a24f58cef60770e00c5bb15
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@xxxxxxxxxx>
---
 tools/xentrace/xenctx.c |  328 +++++++++++++++++++++++++++++-------------------
 1 files changed, 204 insertions(+), 124 deletions(-)

diff -r 34f52eafd4e3 -r 9cc632cc6d40 tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Mon Jan 05 11:08:25 2009 +0000
+++ b/tools/xentrace/xenctx.c   Mon Jan 05 11:08:53 2009 +0000
@@ -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 stack_trace = 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;
-
-static int is_kernel_text(size_t addr)
-{
-#if defined (__i386__)
+guest_word_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext, 
kernel_hypercallpage;
+
+static int is_kernel_text(guest_word_t addr)
+{
+#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 
     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
     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]);
-}
-#endif
-
-#ifdef __i386__
-static void print_ctx(vcpu_guest_context_t *ctx1)
-{
-    struct cpu_user_regs *regs = &ctx1->user_regs;
+        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]);
+        }
+}
+
+static void print_ctx_32(vcpu_guest_context_x86_32_t *ctx)
+{
+    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
     printf(" gs:     %04x\n", regs->gs);
 
     if (disp_all) {
-        print_special(ctx1->ctrlreg, "cr", 0x1d);
-        print_special(ctx1->debugreg, "dr", 0xcf);
-    }
-}
-#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);
+        print_special(ctx->ctrlreg, "cr", 0x1d, 4);
+        print_special(ctx->debugreg, "dr", 0xcf, 4);
+    }
+}
+
+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("rax: %016lx\t", regs->rax);
-    printf("rcx: %016lx\t", regs->rcx);
-    printf("rdx: %016lx\n", regs->rdx);
-
-    printf("rbx: %016lx\t", regs->rbx);
-    printf("rsi: %016lx\t", regs->rsi);
-    printf("rdi: %016lx\n", regs->rdi);
-
-    printf("rbp: %016lx\t", regs->rbp);
-    printf(" r8: %016lx\t", regs->r8);
-    printf(" r9: %016lx\n", regs->r9);
-
-    printf("r10: %016lx\t", regs->r10);
-    printf("r11: %016lx\t", regs->r11);
-    printf("r12: %016lx\n", regs->r12);
-
-    printf("r13: %016lx\t", regs->r13);
-    printf("r14: %016lx\t", regs->r14);
-    printf("r15: %016lx\n", regs->r15);
+    printf("rsp: %016"PRIx64"\n", regs->rsp);
+
+    printf("rax: %016"PRIx64"\t", regs->rax);
+    printf("rcx: %016"PRIx64"\t", regs->rcx);
+    printf("rdx: %016"PRIx64"\n", regs->rdx);
+
+    printf("rbx: %016"PRIx64"\t", regs->rbx);
+    printf("rsi: %016"PRIx64"\t", regs->rsi);
+    printf("rdi: %016"PRIx64"\n", regs->rdi);
+
+    printf("rbp: %016"PRIx64"\t", regs->rbp);
+    printf(" r8: %016"PRIx64"\t", regs->r8);
+    printf(" r9: %016"PRIx64"\n", regs->r9);
+
+    printf("r10: %016"PRIx64"\t", regs->r10);
+    printf("r11: %016"PRIx64"\t", regs->r11);
+    printf("r12: %016"PRIx64"\n", regs->r12);
+
+    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
            tr->itir >> ITIR_KEY_SHIFT & ITIR_KEY_MASK);
 }
 
-void print_ctx(vcpu_guest_context_t *ctx)
-{
-    struct vcpu_guest_context_regs *regs = &ctx->regs;
+void print_ctx(vcpu_guest_context_any_t *ctx)
+{
+    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
     return (void *)(mapped + offset);
 }
 
-static void print_stack(vcpu_guest_context_t *ctx, int vcpu)
-{
-    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;
+static guest_word_t read_stack_word(guest_word_t *src, int width)
+{
+    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_conte
         printf("Stack Trace:\n");
     else
         printf("Call Trace:\n");
-    printf("%c [<" FMT_SIZE_T ">] ",
-        stack_trace ? '*' : ' ', INSTR_POINTER(regs));
-
-    print_symbol(INSTR_POINTER(regs));
+    printf("%c [<", stack_trace ? '*' : ' ');
+    print_stack_word(instr_pointer(ctx), width);
+    printf(">] ");
+
+    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 @@ int main(int argc, char **argv)
 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[] = {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.