4
* Print out the contents of a HVM save record in a human-readable way.
6
* Tim Deegan <Tim.Deegan@citrix.com>
7
* Copyright (c) 2008 Citrix Systems, Inc.
9
* Permission is hereby granted, free of charge, to any person obtaining a copy
10
* of this software and associated documentation files (the "Software"), to
11
* deal in the Software without restriction, including without limitation the
12
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13
* sell copies of the Software, and to permit persons to whom the Software is
14
* furnished to do so, subject to the following conditions:
16
* The above copyright notice and this permission notice shall be included in
17
* all copies or substantial portions of the Software.
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
* DEALINGS IN THE SOFTWARE.
37
#include <sys/types.h>
39
#include <arpa/inet.h>
41
#define BITS_PER_LONG __WORDSIZE
42
#define BITS_TO_LONGS(bits) \
43
(((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
44
#define DECLARE_BITMAP(name,bits) \
45
unsigned long name[BITS_TO_LONGS(bits)]
49
#include <xen/domctl.h>
50
#include <xen/hvm/save.h>
52
static uint8_t *buf = NULL;
56
#define READ(_x) do { \
57
if ( len - off < sizeof (_x) ) \
59
fprintf(stderr, "Error: need another %u bytes, only %u available", \
60
(unsigned int)sizeof(_x), len - off); \
63
memcpy(&(_x), buf + off, sizeof (_x)); \
67
static void dump_header(void)
69
HVM_SAVE_TYPE(HEADER) h;
71
printf(" Header: magic %#lx, version %lu\n",
72
(unsigned long) h.magic, (unsigned long) h.version);
73
printf(" Xen changeset %llx\n",
74
(unsigned long long) h.changeset);
75
printf(" CPUID[0][%%eax] 0x%.8lx\n", (unsigned long) h.cpuid);
76
printf(" gtsc_khz %lu\n", (unsigned long) h.gtsc_khz);
83
} __attribute__((packed));
101
struct fpu_xmm xmm[15];
103
} __attribute__((packed));
105
static void dump_fpu(void *p)
107
struct fpu_regs *r = p;
110
printf(" FPU: fcw 0x%4.4x fsw 0x%4.4x\n"
111
" ftw 0x%2.2x (0x%2.2x) fop 0x%4.4x\n"
112
" fpuip 0x%16.16"PRIx64" fpudp 0x%16.16"PRIx64"\n"
113
" mxcsr 0x%8.8lx mask 0x%8.8lx\n",
114
(unsigned)r->fcw, (unsigned)r->fsw,
115
(unsigned)r->ftw, (unsigned)r->res0, (unsigned)r->fop,
117
(unsigned long)r->mxcsr, (unsigned long)r->mxcsr_mask);
119
for ( i = 0 ; i < 8 ; i++ )
120
printf(" mm%i 0x%4.4x%16.16"PRIx64" (0x%4.4x%4.4x%4.4x)\n",
121
i, r->mm[i].hi, r->mm[i].lo,
122
r->mm[i].pad[2], r->mm[i].pad[1], r->mm[i].pad[0]);
124
for ( i = 0 ; i < 16 ; i++ )
125
printf(" xmm%2.2i 0x%16.16"PRIx64"%16.16"PRIx64"\n",
126
i, r->xmm[i].hi, r->xmm[i].lo);
128
for ( i = 0 ; i < 6 ; i++ )
129
printf(" (0x%16.16"PRIx64"%16.16"PRIx64")\n",
130
r->res1[2*i+1], r->res1[2*i]);
133
static void dump_cpu(void)
135
HVM_SAVE_TYPE(CPU) c;
137
printf(" CPU: rax 0x%16.16llx rbx 0x%16.16llx\n"
138
" rcx 0x%16.16llx rdx 0x%16.16llx\n"
139
" rbp 0x%16.16llx rsi 0x%16.16llx\n"
140
" rdi 0x%16.16llx rsp 0x%16.16llx\n"
141
" r8 0x%16.16llx r9 0x%16.16llx\n"
142
" r10 0x%16.16llx r11 0x%16.16llx\n"
143
" r12 0x%16.16llx r13 0x%16.16llx\n"
144
" r14 0x%16.16llx r15 0x%16.16llx\n"
145
" rip 0x%16.16llx rflags 0x%16.16llx\n"
146
" cr0 0x%16.16llx cr2 0x%16.16llx\n"
147
" cr3 0x%16.16llx cr4 0x%16.16llx\n"
148
" dr0 0x%16.16llx dr1 0x%16.16llx\n"
149
" dr2 0x%16.16llx dr3 0x%16.16llx\n"
150
" dr6 0x%16.16llx dr7 0x%16.16llx\n"
151
" cs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
152
" ds 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
153
" es 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
154
" fs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
155
" gs 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
156
" ss 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
157
" tr 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
158
" ldtr 0x%8.8x (0x%16.16llx + 0x%8.8x / 0x%5.5x)\n"
159
" itdr (0x%16.16llx + 0x%8.8x)\n"
160
" gdtr (0x%16.16llx + 0x%8.8x)\n"
161
" sysenter cs 0x%8.8llx eip 0x%16.16llx esp 0x%16.16llx\n"
162
" shadow gs 0x%16.16llx\n"
163
" MSR flags 0x%16.16llx lstar 0x%16.16llx\n"
164
" star 0x%16.16llx cstar 0x%16.16llx\n"
165
" sfmask 0x%16.16llx efer 0x%16.16llx\n"
167
" event 0x%8.8lx error 0x%8.8lx\n",
168
(unsigned long long) c.rax, (unsigned long long) c.rbx,
169
(unsigned long long) c.rcx, (unsigned long long) c.rdx,
170
(unsigned long long) c.rbp, (unsigned long long) c.rsi,
171
(unsigned long long) c.rdi, (unsigned long long) c.rsp,
172
(unsigned long long) c.r8, (unsigned long long) c.r9,
173
(unsigned long long) c.r10, (unsigned long long) c.r11,
174
(unsigned long long) c.r12, (unsigned long long) c.r13,
175
(unsigned long long) c.r14, (unsigned long long) c.r15,
176
(unsigned long long) c.rip, (unsigned long long) c.rflags,
177
(unsigned long long) c.cr0, (unsigned long long) c.cr2,
178
(unsigned long long) c.cr3, (unsigned long long) c.cr4,
179
(unsigned long long) c.dr0, (unsigned long long) c.dr1,
180
(unsigned long long) c.dr2, (unsigned long long) c.dr3,
181
(unsigned long long) c.dr6, (unsigned long long) c.dr7,
182
c.cs_sel, (unsigned long long) c.cs_base, c.cs_limit, c.cs_arbytes,
183
c.ds_sel, (unsigned long long) c.ds_base, c.ds_limit, c.ds_arbytes,
184
c.es_sel, (unsigned long long) c.es_base, c.es_limit, c.es_arbytes,
185
c.fs_sel, (unsigned long long) c.fs_base, c.fs_limit, c.fs_arbytes,
186
c.gs_sel, (unsigned long long) c.gs_base, c.gs_limit, c.gs_arbytes,
187
c.ss_sel, (unsigned long long) c.ss_base, c.ss_limit, c.ss_arbytes,
188
c.tr_sel, (unsigned long long) c.tr_base, c.tr_limit, c.tr_arbytes,
189
c.ldtr_sel, (unsigned long long) c.ldtr_base,
190
c.ldtr_limit, c.ldtr_arbytes,
191
(unsigned long long) c.idtr_base, c.idtr_limit,
192
(unsigned long long) c.gdtr_base, c.gdtr_limit,
193
(unsigned long long) c.sysenter_cs,
194
(unsigned long long) c.sysenter_eip,
195
(unsigned long long) c.sysenter_esp,
196
(unsigned long long) c.shadow_gs,
197
(unsigned long long) c.msr_flags,
198
(unsigned long long) c.msr_lstar,
199
(unsigned long long) c.msr_star,
200
(unsigned long long) c.msr_cstar,
201
(unsigned long long) c.msr_syscall_mask,
202
(unsigned long long) c.msr_efer,
203
(unsigned long long) c.tsc,
204
(unsigned long) c.pending_event, (unsigned long) c.error_code);
205
dump_fpu(&c.fpu_regs);
209
static void dump_pic(void)
211
HVM_SAVE_TYPE(PIC) p;
213
printf(" PIC: IRQ base %#x, irr %#x, imr %#x, isr %#x\n",
214
p.irq_base, p.irr, p.imr, p.isr);
216
printf(" init_state %u, priority_add %u, readsel_isr %u, poll %u\n",
217
p.init_state, p.priority_add, p.readsel_isr, p.poll);
218
printf(" auto_eoi %u, rotate_on_auto_eoi %u\n",
219
p.auto_eoi, p.rotate_on_auto_eoi);
220
printf(" special_fully_nested_mode %u, special_mask_mode %u\n",
221
p.special_fully_nested_mode, p.special_mask_mode);
222
printf(" is_master %u, elcr %#x, int_output %#x\n",
223
p.is_master, p.elcr, p.int_output);
227
static void dump_ioapic(void)
230
HVM_SAVE_TYPE(IOAPIC) p;
232
printf(" IOAPIC: base_address %#llx, ioregsel %#x id %#x\n",
233
(unsigned long long) p.base_address, p.ioregsel, p.id);
234
for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
236
printf(" pin %.2i: 0x%.16llx\n", i,
237
(unsigned long long) p.redirtbl[i].bits);
241
static void dump_lapic(void)
243
HVM_SAVE_TYPE(LAPIC) p;
245
printf(" LAPIC: base_msr %#llx, disabled %#x, timer_divisor %#x\n",
246
(unsigned long long) p.apic_base_msr, p.disabled, p.timer_divisor);
249
static void dump_lapic_regs(void)
252
HVM_SAVE_TYPE(LAPIC_REGS) r;
254
printf(" LAPIC registers:\n");
255
for ( i = 0 ; i < 0x400 ; i += 32 )
257
printf(" 0x%4.4x: 0x%16.16llx 0x%4.4x: 0x%16.16llx\n",
258
i, *(unsigned long long *)&r.data[i],
259
i + 16, *(unsigned long long *)&r.data[i + 16]);
263
static void dump_pci_irq(void)
265
HVM_SAVE_TYPE(PCI_IRQ) i;
267
printf(" PCI IRQs: 0x%16.16llx%16.16llx\n",
268
(unsigned long long) i.pad[0], (unsigned long long) i.pad[1]);
271
static void dump_isa_irq(void)
273
HVM_SAVE_TYPE(ISA_IRQ) i;
275
printf(" ISA IRQs: 0x%4.4llx\n",
276
(unsigned long long) i.pad[0]);
279
static void dump_pci_link(void)
281
HVM_SAVE_TYPE(PCI_LINK) l;
283
printf(" PCI LINK: %u %u %u %u\n",
284
l.route[0], l.route[1], l.route[2], l.route[3]);
287
static void dump_pit(void)
290
HVM_SAVE_TYPE(PIT) p;
292
printf(" PIT: speaker %s\n", p.speaker_data_on ? "on" : "off");
293
for ( i = 0 ; i < 2 ; i++ )
295
printf(" ch %1i: count %#x, latched_count %#x, count_latched %u\n",
296
i, p.channels[i].count, p.channels[i].latched_count,
297
p.channels[i].count_latched);
298
printf(" status %#x, status_latched %#x\n",
299
p.channels[i].status, p.channels[i].status_latched);
300
printf(" rd_state %#x, wr_state %#x, wr_latch %#x, rw_mode %#x\n",
301
p.channels[i].read_state, p.channels[i].write_state,
302
p.channels[i].write_latch, p.channels[i].rw_mode);
303
printf(" mode %#x, bcd %#x, gate %#x\n",
304
p.channels[i].mode, p.channels[i].bcd, p.channels[i].gate);
308
static void dump_rtc(void)
310
HVM_SAVE_TYPE(RTC) r;
312
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",
313
r.cmos_data[0], r.cmos_data[1], r.cmos_data[2], r.cmos_data[3],
314
r.cmos_data[4], r.cmos_data[5], r.cmos_data[6], r.cmos_data[7]);
315
printf(" 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x, index 0x%2.2x\n",
316
r.cmos_data[8], r.cmos_data[9], r.cmos_data[10], r.cmos_data[11],
317
r.cmos_data[12], r.cmos_data[13], r.cmos_index);
321
static void dump_hpet(void)
324
HVM_SAVE_TYPE(HPET) h;
326
printf(" HPET: capability %#llx config %#llx\n",
327
(unsigned long long) h.capability,
328
(unsigned long long) h.config);
329
printf(" isr %#llx counter %#llx\n",
330
(unsigned long long) h.isr,
331
(unsigned long long) h.mc64);
332
for ( i = 0; i < HPET_TIMER_NUM; i++ )
334
printf(" timer%i config %#llx cmp %#llx\n", i,
335
(unsigned long long) h.timers[i].config,
336
(unsigned long long) h.timers[i].cmp);
337
printf(" timer%i period %#llx fsb %#llx\n", i,
338
(unsigned long long) h.period[i],
339
(unsigned long long) h.timers[i].fsb);
343
static void dump_pmtimer(void)
345
HVM_SAVE_TYPE(PMTIMER) p;
347
printf(" ACPI PM: TMR_VAL 0x%x, PM1a_STS 0x%x, PM1a_EN 0x%x\n",
348
p.tmr_val, (unsigned) p.pm1a_sts, (unsigned) p.pm1a_en);
351
static void dump_mtrr(void)
353
HVM_SAVE_TYPE(MTRR) p;
356
printf(" MTRR: PAT 0x%llx, cap 0x%llx, default 0x%llx\n",
357
(unsigned long long) p.msr_pat_cr,
358
(unsigned long long) p.msr_mtrr_cap,
359
(unsigned long long) p.msr_mtrr_def_type);
360
for ( i = 0 ; i < MTRR_VCNT ; i++ )
361
printf(" var %i 0x%16.16llx 0x%16.16llx\n", i,
362
(unsigned long long) p.msr_mtrr_var[2 * i],
363
(unsigned long long) p.msr_mtrr_var[2 * i + 1]);
364
for ( i = 0 ; i < NUM_FIXED_MSR ; i++ )
365
printf(" fixed %.2i 0x%16.16llx\n", i,
366
(unsigned long long) p.msr_mtrr_fixed[i]);
369
static void dump_viridian(void)
371
HVM_SAVE_TYPE(VIRIDIAN) p;
373
printf(" VIRIDIAN: hypercall gpa 0x%llx, guest ID 0x%llx\n",
374
(unsigned long long) p.hypercall_gpa,
375
(unsigned long long) p.guest_os_id);
378
int main(int argc, char **argv)
380
int entry, domid, xch;
382
struct hvm_save_descriptor desc;
384
if ( argc != 2 || !argv[1] || (domid = atoi(argv[1])) < 0 )
386
fprintf(stderr, "usage: %s <domid>\n", argv[0]);
390
xch = xc_interface_open();
393
fprintf(stderr, "Error: can't open libxc handle\n");
396
len = xc_domain_hvm_getcontext(xch, domid, 0, 0);
397
if ( len == (uint32_t) -1 )
399
fprintf(stderr, "Error: can't get record length for dom %i\n", domid);
405
fprintf(stderr, "Error: can't allocate %u bytes\n", len);
408
len = xc_domain_hvm_getcontext(xch, domid, buf, len);
409
if ( len == (uint32_t) -1 )
411
fprintf(stderr, "Error: can't get HVM record for dom %i\n", domid);
417
printf("HVM save record for domain %i\n", domid);
422
printf("Entry %i: type %u instance %u, length %u\n",
423
entry++, (unsigned) desc.typecode,
424
(unsigned) desc.instance, (unsigned) desc.length);
425
switch (desc.typecode)
427
case HVM_SAVE_CODE(HEADER): dump_header(); break;
428
case HVM_SAVE_CODE(CPU): dump_cpu(); break;
429
case HVM_SAVE_CODE(PIC): dump_pic(); break;
430
case HVM_SAVE_CODE(IOAPIC): dump_ioapic(); break;
431
case HVM_SAVE_CODE(LAPIC): dump_lapic(); break;
432
case HVM_SAVE_CODE(LAPIC_REGS): dump_lapic_regs(); break;
433
case HVM_SAVE_CODE(PCI_IRQ): dump_pci_irq(); break;
434
case HVM_SAVE_CODE(ISA_IRQ): dump_isa_irq(); break;
435
case HVM_SAVE_CODE(PCI_LINK): dump_pci_link(); break;
436
case HVM_SAVE_CODE(PIT): dump_pit(); break;
437
case HVM_SAVE_CODE(RTC): dump_rtc(); break;
438
case HVM_SAVE_CODE(HPET): dump_hpet(); break;
439
case HVM_SAVE_CODE(PMTIMER): dump_pmtimer(); break;
440
case HVM_SAVE_CODE(MTRR): dump_mtrr(); break;
441
case HVM_SAVE_CODE(VIRIDIAN): dump_viridian(); break;
442
case HVM_SAVE_CODE(END): break;
444
printf(" ** Don't understand type %u: skipping\n",
445
(unsigned) desc.typecode);
446
off += (desc.length);
448
} while ( desc.typecode != HVM_SAVE_CODE(END) && off < len );