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

[Xen-devel] [PATCH 1/4] tools/test: Add check-hvmctx



From: Don Slutz <dslutz@xxxxxxxxxxx>

This is a unit test for xc_domain_hvm_getcontext_partial vs
xc_domain_hvm_getcontext.

Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
---
 tools/tests/check-hvmctx/.gitignore     |   1 +
 tools/tests/check-hvmctx/Makefile       |  34 ++
 tools/tests/check-hvmctx/README         |  21 +
 tools/tests/check-hvmctx/check-hvmctx.c | 661 ++++++++++++++++++++++++++++++++
 4 files changed, 717 insertions(+)
 create mode 100644 tools/tests/check-hvmctx/.gitignore
 create mode 100644 tools/tests/check-hvmctx/Makefile
 create mode 100644 tools/tests/check-hvmctx/README
 create mode 100644 tools/tests/check-hvmctx/check-hvmctx.c

diff --git a/tools/tests/check-hvmctx/.gitignore 
b/tools/tests/check-hvmctx/.gitignore
new file mode 100644
index 0000000..e2dabd8
--- /dev/null
+++ b/tools/tests/check-hvmctx/.gitignore
@@ -0,0 +1 @@
+check-hvmctx
diff --git a/tools/tests/check-hvmctx/Makefile 
b/tools/tests/check-hvmctx/Makefile
new file mode 100644
index 0000000..dce7508
--- /dev/null
+++ b/tools/tests/check-hvmctx/Makefile
@@ -0,0 +1,34 @@
+XEN_ROOT=$(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS += -Werror
+
+CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += $(CFLAGS_xeninclude)
+CFLAGS += $(CFLAGS_libxenstore)
+
+HDRS     = $(wildcard *.h)
+
+TARGETS-$(CONFIG_X86) += check-hvmctx
+TARGETS := $(TARGETS-y)
+
+# Include configure output (config.h) to headers search path
+CFLAGS += -I$(XEN_ROOT)/tools
+
+# Allow special builds
+CFLAGS += $(CHECK_HVMCTX)
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build: $(TARGETS) Makefile
+
+.PHONY: clean
+clean:
+       $(RM) *.o $(TARGETS) *~ $(DEPS)
+
+check-hvmctx: check-hvmctx.o Makefile
+       $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+
+-include $(DEPS)
diff --git a/tools/tests/check-hvmctx/README b/tools/tests/check-hvmctx/README
new file mode 100644
index 0000000..0d70df4
--- /dev/null
+++ b/tools/tests/check-hvmctx/README
@@ -0,0 +1,21 @@
+Check that xc_domain_hvm_getcontext_partial gets the same data as
+xc_domain_hvm_getcontext.
+
+To see the bug about offline VCPU(s) you can use the offline_module
+(offline.ko) in a domU.
+
+To see the bug about PIC:
+
+make clean;make CHECK_HVMCTX="-DDOPIC"
+
+To never report a time based issue (I see it about 1 out of 50):
+
+make clean;make CHECK_HVMCTX="-DFULLCLEAN"
+
+To see time based issues:
+
+make clean;make CHECK_HVMCTX="-DNOTCLEAN"
+
+Normal:
+
+make clean;make
diff --git a/tools/tests/check-hvmctx/check-hvmctx.c 
b/tools/tests/check-hvmctx/check-hvmctx.c
new file mode 100644
index 0000000..db331f9
--- /dev/null
+++ b/tools/tests/check-hvmctx/check-hvmctx.c
@@ -0,0 +1,661 @@
+/*
+ * check-hvmctx.c
+ *
+ * check that xc_domain_hvm_getcontext_partial gets the same data as 
xc_domain_hvm_getcontext.
+ *
+ * Based on xen-hvmctx.c
+ *
+ * Tim Deegan <Tim.Deegan@xxxxxxxxxx>
+ * Copyright (c) 2008 Citrix Systems, Inc.
+ * Copyright (C) 2013 by Verizon.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#define BITS_PER_LONG __WORDSIZE
+#define BITS_TO_LONGS(bits)                     \
+    (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits)               \
+    unsigned long name[BITS_TO_LONGS(bits)]
+
+#include <xenctrl.h>
+#include <xen/xen.h>
+#include <xen/domctl.h>
+#include <xen/hvm/save.h>
+
+static uint8_t *buf = NULL;
+static uint32_t len;
+static uint32_t off;
+static int debug = 0;
+
+#define READ(_x) do {                                                   \
+        if ( len - off < sizeof (_x) )                                  \
+        {                                                               \
+            fprintf(stderr,                                             \
+                    "Error: need another %u bytes, only %u available",  \
+                    (unsigned int)sizeof(_x), len - off);               \
+            exit(1);                                                    \
+        }                                                               \
+        memcpy(&(_x), buf + off, sizeof (_x));                          \
+        off += sizeof (_x);                                             \
+    } while (0)
+
+static void vms_dump(const void *d, int size)
+{
+    int len, i, j, c;
+    const unsigned char *buf = d;
+
+    for(i = 0; i < size; i += 16) {
+        len = size - i;
+        if (len > 16)
+            len = 16;
+        for(j = len; j < 16; j++) {
+            if ((j != 15) && ((j & 3) == 3))
+                printf(" ");
+            printf("  ");
+        }
+        for(j = len - 1; j >= 0; j--) {
+            if ((j != 15) && ((j & 3) == 3))
+                printf(" ");
+            printf("%02x", buf[i+j]);
+        }
+        printf("   %08x: ", i);
+        for(j = 0; j < len; j++) {
+            c = buf[i+j];
+            if (c < ' ' || c > '~')
+                c = '.';
+            printf("%c", c);
+        }
+        printf("\n");
+    }
+}
+
+static void dump_header(void)
+{
+    HVM_SAVE_TYPE(HEADER) h;
+    READ(h);
+    printf("     Header: magic %#lx, version %lu\n",
+           (unsigned long) h.magic, (unsigned long) h.version);
+    if (debug & 0x02) {
+        printf("             Xen changeset %llx\n",
+               (unsigned long long) h.changeset);
+        printf("             CPUID[0][%%eax] 0x%.8lx\n", (unsigned long) 
h.cpuid);
+        printf("             gtsc_khz %lu\n", (unsigned long) h.gtsc_khz);
+    }
+}
+
+struct fpu_mm {
+    uint64_t lo;
+    uint16_t hi;
+    uint16_t pad[3];
+} __attribute__((packed));
+
+struct fpu_xmm {
+    uint64_t lo;
+    uint64_t hi;
+};
+
+struct fpu_regs {
+    uint16_t fcw;
+    uint16_t fsw;
+    uint8_t ftw;
+    uint8_t res0;
+    uint16_t fop;
+    uint64_t fpuip;
+    uint64_t fpudp;
+    uint32_t mxcsr;
+    uint32_t mxcsr_mask;
+    struct fpu_mm mm[8];
+    struct fpu_xmm xmm[16];
+    uint64_t res1[12];
+} __attribute__((packed));
+
+static void dump_fpu(void *p)
+{
+    struct fpu_regs *r = p;
+    int i;
+
+    printf("    FPU:    fcw 0x%4.4x fsw 0x%4.4x\n",
+           (unsigned)r->fcw, (unsigned)r->fsw);
+    if (debug & 0x02) {
+        printf("            ftw 0x%2.2x (0x%2.2x) fop 0x%4.4x\n"
+               "          fpuip 0x%16.16"PRIx64" fpudp 0x%16.16"PRIx64"\n"
+               "          mxcsr 0x%8.8lx mask 0x%8.8lx\n",
+               (unsigned)r->ftw, (unsigned)r->res0, (unsigned)r->fop,
+               r->fpuip, r->fpudp,
+               (unsigned long)r->mxcsr, (unsigned long)r->mxcsr_mask);
+
+        for ( i = 0 ; i < 8 ; i++ )
+            printf("            mm%i 0x%4.4x%16.16"PRIx64" 
(0x%4.4x%4.4x%4.4x)\n",
+                   i, r->mm[i].hi, r->mm[i].lo,
+                   r->mm[i].pad[2], r->mm[i].pad[1], r->mm[i].pad[0]);
+
+        for ( i = 0 ; i < 16 ; i++ )
+            printf("          xmm%2.2i 0x%16.16"PRIx64"%16.16"PRIx64"\n",
+                   i, r->xmm[i].hi, r->xmm[i].lo);
+
+        for ( i = 0 ; i < 6 ; i++ )
+            printf("               (0x%16.16"PRIx64"%16.16"PRIx64")\n",
+                   r->res1[2*i+1], r->res1[2*i]);
+    }
+}
+
+static void dump_cpu(void)
+{
+    HVM_SAVE_TYPE(CPU) c;
+    READ(c);
+    printf("    CPU:    rax 0x%16.16llx     rbx 0x%16.16llx\n",
+           (unsigned long long) c.rax, (unsigned long long) c.rbx);
+    if (debug & 0x02) {
+        printf("            rcx 0x%16.16llx     rdx 0x%16.16llx\n"
+               "            rbp 0x%16.16llx     rsi 0x%16.16llx\n"
+               "            rdi 0x%16.16llx     rsp 0x%16.16llx\n"
+               "             r8 0x%16.16llx      r9 0x%16.16llx\n"
+               "            r10 0x%16.16llx     r11 0x%16.16llx\n"
+               "            r12 0x%16.16llx     r13 0x%16.16llx\n"
+               "            r14 0x%16.16llx     r15 0x%16.16llx\n"
+               "            rip 0x%16.16llx  rflags 0x%16.16llx\n"
+               "            cr0 0x%16.16llx     cr2 0x%16.16llx\n"
+               "            cr3 0x%16.16llx     cr4 0x%16.16llx\n"
+               "            dr0 0x%16.16llx     dr1 0x%16.16llx\n"
+               "            dr2 0x%16.16llx     dr3 0x%16.16llx\n"
+               "            dr6 0x%16.16llx     dr7 0x%16.16llx\n"
+               "             cs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             ds 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             es 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             fs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             gs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             ss 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "             tr 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "           ldtr 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
+               "           idtr            (0x%16.16llx + 0x%8.8x)\n"
+               "           gdtr            (0x%16.16llx + 0x%8.8x)\n"
+               "    sysenter cs 0x%8.8llx  eip 0x%16.16llx  esp 0x%16.16llx\n"
+               "      shadow gs 0x%16.16llx\n"
+               "      MSR flags 0x%16.16llx  lstar 0x%16.16llx\n"
+               "           star 0x%16.16llx  cstar 0x%16.16llx\n"
+               "         sfmask 0x%16.16llx   efer 0x%16.16llx\n"
+               "            tsc 0x%16.16llx\n"
+               "          event 0x%8.8lx error 0x%8.8lx\n",
+               (unsigned long long) c.rcx, (unsigned long long) c.rdx,
+               (unsigned long long) c.rbp, (unsigned long long) c.rsi,
+               (unsigned long long) c.rdi, (unsigned long long) c.rsp,
+               (unsigned long long) c.r8, (unsigned long long) c.r9,
+               (unsigned long long) c.r10, (unsigned long long) c.r11,
+               (unsigned long long) c.r12, (unsigned long long) c.r13,
+               (unsigned long long) c.r14, (unsigned long long) c.r15,
+               (unsigned long long) c.rip, (unsigned long long) c.rflags,
+               (unsigned long long) c.cr0, (unsigned long long) c.cr2,
+               (unsigned long long) c.cr3, (unsigned long long) c.cr4,
+               (unsigned long long) c.dr0, (unsigned long long) c.dr1,
+               (unsigned long long) c.dr2, (unsigned long long) c.dr3,
+               (unsigned long long) c.dr6, (unsigned long long) c.dr7,
+               c.cs_sel, (unsigned long long) c.cs_base, c.cs_limit, 
c.cs_arbytes,
+               c.ds_sel, (unsigned long long) c.ds_base, c.ds_limit, 
c.ds_arbytes,
+               c.es_sel, (unsigned long long) c.es_base, c.es_limit, 
c.es_arbytes,
+               c.fs_sel, (unsigned long long) c.fs_base, c.fs_limit, 
c.fs_arbytes,
+               c.gs_sel, (unsigned long long) c.gs_base, c.gs_limit, 
c.gs_arbytes,
+               c.ss_sel, (unsigned long long) c.ss_base, c.ss_limit, 
c.ss_arbytes,
+               c.tr_sel, (unsigned long long) c.tr_base, c.tr_limit, 
c.tr_arbytes,
+               c.ldtr_sel, (unsigned long long) c.ldtr_base,
+               c.ldtr_limit, c.ldtr_arbytes,
+               (unsigned long long) c.idtr_base, c.idtr_limit,
+               (unsigned long long) c.gdtr_base, c.gdtr_limit,
+               (unsigned long long) c.sysenter_cs,
+               (unsigned long long) c.sysenter_eip,
+               (unsigned long long) c.sysenter_esp,
+               (unsigned long long) c.shadow_gs,
+               (unsigned long long) c.msr_flags,
+               (unsigned long long) c.msr_lstar,
+               (unsigned long long) c.msr_star,
+               (unsigned long long) c.msr_cstar,
+               (unsigned long long) c.msr_syscall_mask,
+               (unsigned long long) c.msr_efer,
+               (unsigned long long) c.tsc,
+               (unsigned long) c.pending_event, (unsigned long) c.error_code);
+        dump_fpu(&c.fpu_regs);
+    }
+}
+
+
+static void dump_pic(void)
+{
+    HVM_SAVE_TYPE(PIC) p;
+    READ(p);
+    printf("    PIC: IRQ base %#x, irr %#x, imr %#x, isr %#x\n",
+           p.irq_base, p.irr, p.imr, p.isr);
+    if (debug & 0x02) {
+
+        printf("         init_state %u, priority_add %u, readsel_isr %u, poll 
%u\n",
+               p.init_state, p.priority_add, p.readsel_isr, p.poll);
+        printf("         auto_eoi %u, rotate_on_auto_eoi %u\n",
+               p.auto_eoi, p.rotate_on_auto_eoi);
+        printf("         special_fully_nested_mode %u, special_mask_mode %u\n",
+               p.special_fully_nested_mode, p.special_mask_mode);
+        printf("         is_master %u, elcr %#x, int_output %#x\n",
+               p.is_master, p.elcr, p.int_output);
+    }
+}
+
+
+static void dump_ioapic(void)
+{
+    int i;
+    HVM_SAVE_TYPE(IOAPIC) p;
+    READ(p);
+    printf("    IOAPIC: base_address %#llx, ioregsel %#x id %#x\n",
+           (unsigned long long) p.base_address, p.ioregsel, p.id);
+    if (debug & 0x02) {
+        for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
+        {
+            printf("            pin %.2i: 0x%.16llx\n", i,
+                   (unsigned long long) p.redirtbl[i].bits);
+        }
+    }
+}
+
+static void dump_lapic(void)
+{
+    HVM_SAVE_TYPE(LAPIC) p;
+    READ(p);
+    printf("    LAPIC: base_msr %#llx, disabled %#x, timer_divisor %#x\n",
+           (unsigned long long) p.apic_base_msr, p.disabled, p.timer_divisor);
+}
+
+static void dump_lapic_regs(void)
+{
+    unsigned int i;
+    HVM_SAVE_TYPE(LAPIC_REGS) r;
+    READ(r);
+    printf("    LAPIC registers:\n");
+    if (debug & 0x02) {
+        for ( i = 0 ; i < 0x400 ; i += 32 )
+        {
+            printf("          0x%4.4x: 0x%16.16llx   0x%4.4x: 0x%16.16llx\n",
+                   i, *(unsigned long long *)&r.data[i],
+                   i + 16, *(unsigned long long *)&r.data[i + 16]);
+        }
+    }
+}
+
+static void dump_pci_irq(void)
+{
+    HVM_SAVE_TYPE(PCI_IRQ) i;
+    READ(i);
+    printf("    PCI IRQs: 0x%16.16llx%16.16llx\n",
+           (unsigned long long) i.pad[0], (unsigned long long) i.pad[1]);
+}
+
+static void dump_isa_irq(void)
+{
+    HVM_SAVE_TYPE(ISA_IRQ) i;
+    READ(i);
+    printf("    ISA IRQs: 0x%4.4llx\n",
+           (unsigned long long) i.pad[0]);
+}
+
+static void dump_pci_link(void)
+{
+    HVM_SAVE_TYPE(PCI_LINK) l;
+    READ(l);
+    printf("    PCI LINK: %u %u %u %u\n",
+           l.route[0], l.route[1], l.route[2], l.route[3]);
+}
+
+static void dump_pit(void)
+{
+    int i;
+    HVM_SAVE_TYPE(PIT) p;
+    READ(p);
+    printf("    PIT: speaker %s\n", p.speaker_data_on ? "on" : "off");
+    if (debug & 0x02) {
+        for ( i = 0 ; i < 2 ; i++ )
+        {
+            printf("         ch %1i: count %#x, latched_count %#x, 
count_latched %u\n",
+                   i, p.channels[i].count, p.channels[i].latched_count,
+                   p.channels[i].count_latched);
+            printf("               status %#x, status_latched %#x\n",
+                   p.channels[i].status, p.channels[i].status_latched);
+            printf("               rd_state %#x, wr_state %#x, wr_latch %#x, 
rw_mode %#x\n",
+                   p.channels[i].read_state, p.channels[i].write_state,
+                   p.channels[i].write_latch, p.channels[i].rw_mode);
+            printf("               mode %#x, bcd %#x, gate %#x\n",
+                   p.channels[i].mode, p.channels[i].bcd, p.channels[i].gate);
+        }
+    }
+}
+
+static void dump_rtc(void)
+{
+    HVM_SAVE_TYPE(RTC) r;
+    READ(r);
+    printf("    RTC: regs 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 
0x%2.2x 0x%2.2x\n",
+           r.cmos_data[0], r.cmos_data[1], r.cmos_data[2], r.cmos_data[3],
+           r.cmos_data[4], r.cmos_data[5], r.cmos_data[6], r.cmos_data[7]);
+    if (debug & 0x02) {
+        printf("              0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x, 
index 0x%2.2x\n",
+               r.cmos_data[8], r.cmos_data[9], r.cmos_data[10], 
r.cmos_data[11],
+               r.cmos_data[12], r.cmos_data[13], r.cmos_index);
+    }
+
+}
+
+static void dump_hpet(void)
+{
+    int i;
+    HVM_SAVE_TYPE(HPET) h;
+    READ(h);
+    printf("    HPET: capability %#llx config %#llx\n",
+           (unsigned long long) h.capability,
+           (unsigned long long) h.config);
+    if (debug & 0x02) {
+        printf("          isr %#llx counter %#llx\n",
+               (unsigned long long) h.isr,
+               (unsigned long long) h.mc64);
+        for ( i = 0; i < HPET_TIMER_NUM; i++ )
+        {
+            printf("          timer%i config %#llx cmp %#llx\n", i,
+                   (unsigned long long) h.timers[i].config,
+                   (unsigned long long) h.timers[i].cmp);
+            printf("          timer%i period %#llx fsb %#llx\n", i,
+                   (unsigned long long) h.period[i],
+                   (unsigned long long) h.timers[i].fsb);
+        }
+    }
+}
+
+static void dump_pmtimer(void)
+{
+    HVM_SAVE_TYPE(PMTIMER) p;
+    READ(p);
+    printf("    ACPI PM: TMR_VAL 0x%x, PM1a_STS 0x%x, PM1a_EN 0x%x\n",
+           p.tmr_val, (unsigned) p.pm1a_sts, (unsigned) p.pm1a_en);
+}
+
+static void dump_mtrr(void)
+{
+    HVM_SAVE_TYPE(MTRR) p;
+    int i;
+    READ(p);
+    printf("    MTRR: PAT 0x%llx, cap 0x%llx, default 0x%llx\n",
+           (unsigned long long) p.msr_pat_cr,
+           (unsigned long long) p.msr_mtrr_cap,
+           (unsigned long long) p.msr_mtrr_def_type);
+    if (debug & 0x02) {
+        for ( i = 0 ; i < MTRR_VCNT ; i++ )
+            printf("          var %i 0x%16.16llx 0x%16.16llx\n", i,
+                   (unsigned long long) p.msr_mtrr_var[2 * i],
+                   (unsigned long long) p.msr_mtrr_var[2 * i + 1]);
+        for ( i = 0 ; i < NUM_FIXED_MSR ; i++ )
+            printf("          fixed %.2i 0x%16.16llx\n", i,
+                   (unsigned long long) p.msr_mtrr_fixed[i]);
+    }
+}
+
+static void dump_viridian_domain(void)
+{
+    HVM_SAVE_TYPE(VIRIDIAN_DOMAIN) p;
+    READ(p);
+    printf("    VIRIDIAN_DOMAIN: hypercall gpa 0x%llx, guest_os_id 0x%llx\n",
+           (unsigned long long) p.hypercall_gpa,
+           (unsigned long long) p.guest_os_id);
+}
+
+static void dump_viridian_vcpu(void)
+{
+    HVM_SAVE_TYPE(VIRIDIAN_VCPU) p;
+    READ(p);
+    printf("    VIRIDIAN_VCPU: apic_assist 0x%llx\n",
+           (unsigned long long) p.apic_assist);
+}
+
+static void dump_vmce_vcpu(void)
+{
+    HVM_SAVE_TYPE(VMCE_VCPU) p;
+    READ(p);
+    printf("    VMCE_VCPU: caps %" PRIx64 "\n", p.caps);
+    if (debug & 0x02) {
+        printf("    VMCE_VCPU: bank0 mci_ctl2 %" PRIx64 "\n", 
p.mci_ctl2_bank0);
+        printf("    VMCE_VCPU: bank1 mci_ctl2 %" PRIx64 "\n", 
p.mci_ctl2_bank1);
+    }
+}
+
+static void dump_tsc_adjust(void)
+{
+    HVM_SAVE_TYPE(TSC_ADJUST) p;
+    READ(p);
+    printf("    TSC_ADJUST: tsc_adjust %" PRIx64 "\n", p.tsc_adjust);
+}
+
+static void dump_xsave(int xsave_size)
+{
+    uint8_t p[xsave_size];
+    READ(p);
+    printf(" CPU XSAVE:\n");
+    if (debug & 0x02) {
+        vms_dump(&p, sizeof(p));
+    }
+}
+
+int main(int argc, char **argv)
+{
+    int entry, domid, ret;
+    xc_interface *xch;
+    uint8_t *tbuf = NULL;
+    int retval = 0;
+
+    struct hvm_save_descriptor desc;
+
+    if ( argc < 2 || argc > 3 || !argv[1] || (domid = atoi(argv[1])) < 0 )
+    {
+        fprintf(stderr, "usage: %s <domid>\n", argv[0]);
+        exit(1);
+    }
+    if (argc == 3)
+        debug = atoi(argv[2]);
+
+    xch = xc_interface_open(0,0,0);
+    if ( !xch )
+    {
+        fprintf(stderr, "Error: can't open libxc handle\n");
+        exit(1);
+    }
+
+    ret = xc_domain_pause(xch, domid);
+    if (ret < 0) {
+        perror("xc_domain_pause");
+        exit(-1);
+    }
+
+    /*
+     * Calling with zero buffer length should return the buffer length
+     * required.
+     */
+    len = xc_domain_hvm_getcontext(xch, domid, 0, 0);
+    if ( len == (uint32_t) -1 )
+    {
+        fprintf(stderr, "Error: can't get record length for dom %i\n", domid);
+        exit(1);
+    }
+    buf = malloc(len);
+    if ( buf == NULL )
+    {
+        fprintf(stderr, "Error: can't allocate %u bytes\n", len);
+        exit(1);
+    }
+    tbuf = malloc(len);
+    if ( tbuf == NULL )
+    {
+        fprintf(stderr, "Error: can't allocate %u bytes\n", len);
+        exit(1);
+    }
+    len = xc_domain_hvm_getcontext(xch, domid, buf, len);
+    if ( len == (uint32_t) -1 )
+    {
+        fprintf(stderr, "Error: can't get HVM record for dom %i\n", domid);
+        exit(1);
+    }
+    off = 0;
+
+    /* Say hello */
+    printf("Check HVM save record vs partial for domain %i\n", domid);
+    if (debug & 0x20) {
+#ifndef DOPIC
+        printf("PIC:        Cannot get just 2nd instance and can change -- 
time based.\n");
+#endif
+#ifndef NOTCLEAN
+        printf("HPET:       Changes -- time based.\n");
+        printf("PMTIMER:    Changes -- time based.\n");
+#endif
+#if defined(FULLCLEAN) || !defined(NOTCLEAN)
+        printf("IOAPIC:     Can change -- time based.\n");
+        printf("LAPIC_REGS: Can change -- time based.\n");
+        printf("PCI_IRQ:    Can change -- time based.\n");
+        printf("ISA_IRQ:    Can change -- time based.\n");
+#endif
+    }
+
+    entry = 0;
+    do {
+        READ(desc);
+        if (debug & 0x01)
+            printf("Entry %i: type %u instance %u, length %u\n",
+                   entry, (unsigned) desc.typecode,
+                   (unsigned) desc.instance, (unsigned) desc.length);
+        switch (desc.typecode)
+        {
+        case HVM_SAVE_CODE(HEADER):     /* Not supported by 
xc_domain_hvm_getcontext_partial */
+        case HVM_SAVE_CODE(END):        /* Not supported by 
xc_domain_hvm_getcontext_partial */
+#ifndef DOPIC
+        case HVM_SAVE_CODE(PIC):        /* Cannot get just 2nd instance and 
can change -- time based */
+#endif
+#ifndef NOTCLEAN
+        case HVM_SAVE_CODE(HPET):       /* Changes -- time based */
+        case HVM_SAVE_CODE(PMTIMER):    /* Changes -- time based */
+#endif
+#if defined(FULLCLEAN) || !defined(NOTCLEAN)
+        case HVM_SAVE_CODE(IOAPIC):     /* Can change -- time based */
+        case HVM_SAVE_CODE(LAPIC_REGS): /* Can change -- time based */
+        case HVM_SAVE_CODE(PCI_IRQ):    /* Can change -- time based */
+        case HVM_SAVE_CODE(ISA_IRQ):    /* Can change -- time based */
+#endif
+            off += (desc.length);
+            break;
+        default:
+            if (xc_domain_hvm_getcontext_partial(
+                    xch, domid, desc.typecode, desc.instance,
+                    tbuf, desc.length) != 0) {
+                fprintf(stderr, "Error: xc_domain_hvm_getcontext_partial: 
entry %i: type %u instance %u, length %u: ",
+                        entry, (unsigned) desc.typecode,
+                        (unsigned) desc.instance, (unsigned) desc.length);
+                perror("");
+                retval = 42;
+                memset(tbuf, 0xee, desc.length);
+            }
+            ret = desc.length;
+#ifndef NOTCLEAN
+            if (desc.typecode == HVM_SAVE_CODE(CPU))
+                ret -= 16; /* Skip TSC; it changes while paused... */
+#endif
+            if (memcmp(tbuf, buf + off, ret) != 0) {
+                printf("Error: entry %i: type %u instance %u, length %u 
mismatch!\n",
+                       entry, (unsigned) desc.typecode,
+                       (unsigned) desc.instance, (unsigned) desc.length);
+                retval = 1;
+                if (debug & 0x04) {
+                    int i;
+                    uint8_t *gbuf = buf + off;
+
+                    for (i = 0; i < ret; i++) {
+                        if (gbuf[i] != tbuf[i])
+                            printf("[%03x] good=%02x bad=%02x\n",
+                                   i, gbuf[i], tbuf[i]);
+                    }
+                }
+                if (debug & 0x10) {
+                    printf("good:\n");
+                    vms_dump(buf + off, desc.length);
+                    printf("bad:\n");
+                    vms_dump(tbuf, desc.length);
+                }
+                switch (desc.typecode)
+                {
+                case HVM_SAVE_CODE(HEADER): dump_header(); break;
+                case HVM_SAVE_CODE(CPU): dump_cpu(); break;
+                case HVM_SAVE_CODE(PIC): dump_pic(); break;
+                case HVM_SAVE_CODE(IOAPIC): dump_ioapic(); break;
+                case HVM_SAVE_CODE(LAPIC): dump_lapic(); break;
+                case HVM_SAVE_CODE(LAPIC_REGS): dump_lapic_regs(); break;
+                case HVM_SAVE_CODE(PCI_IRQ): dump_pci_irq(); break;
+                case HVM_SAVE_CODE(ISA_IRQ): dump_isa_irq(); break;
+                case HVM_SAVE_CODE(PCI_LINK): dump_pci_link(); break;
+                case HVM_SAVE_CODE(PIT): dump_pit(); break;
+                case HVM_SAVE_CODE(RTC): dump_rtc(); break;
+                case HVM_SAVE_CODE(HPET): dump_hpet(); break;
+                case HVM_SAVE_CODE(PMTIMER): dump_pmtimer(); break;
+                case HVM_SAVE_CODE(MTRR): dump_mtrr(); break;
+                case HVM_SAVE_CODE(VIRIDIAN_DOMAIN): dump_viridian_domain(); 
break;
+                case HVM_SAVE_CODE(VIRIDIAN_VCPU): dump_viridian_vcpu(); break;
+                case HVM_SAVE_CODE(VMCE_VCPU): dump_vmce_vcpu(); break;
+                case HVM_SAVE_CODE(TSC_ADJUST): dump_tsc_adjust(); break;
+                case CPU_XSAVE_CODE: dump_xsave(desc.length); break;
+                case HVM_SAVE_CODE(END): break;
+                default:
+                    printf(" ** Don't understand type %u: skipping\n",
+                           (unsigned) desc.typecode);
+                    off += (desc.length);
+                }
+            } else {
+                off += (desc.length);
+            }
+            break;
+        }
+        entry++;
+    } while ( desc.typecode != HVM_SAVE_CODE(END) && off < len );
+
+    ret = xc_domain_unpause(xch, domid);
+    if (ret < 0) {
+        perror("xc_domain_unpause");
+        exit(1);
+    }
+
+    return retval;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.8.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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