1 /*
2 * kdd-xen.c -- xen-specific functions for the kdd debugging stub
3 *
4 * Tim Deegan <Tim.Deegan@citrix.com>
5 *
6 * Copyright (c) 2007-2010, Citrix Systems Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <stdio.h>
38 #include <errno.h>
39 #include <inttypes.h>
40 #include <sys/types.h>
41 #include <sys/mman.h>
42
43 #include <xenctrl.h>
44 #include <xen/xen.h>
45 #include <xen/hvm/save.h>
46
47 #include "kdd.h"
48
49 #define MAPSIZE 4093 /* Prime */
50
51 #define PAGE_SHIFT 12
52 #define PAGE_SIZE (1U << PAGE_SHIFT)
53
54 struct kdd_guest {
55 struct xentoollog_logger xc_log; /* Must be first for xc log callbacks */
56 xc_interface *xc_handle;
57 uint32_t domid;
58 char id[80];
59 FILE *log;
60 int verbosity;
61 void *hvm_buf;
62 uint32_t hvm_sz;
63 uint32_t pfns[MAPSIZE];
64 void * maps[MAPSIZE];
65 };
66
67
68 /* Flush any mappings we have of the guest memory: it's not polite
69 * top hold on to them while the guest is running */
flush_maps(kdd_guest * g)70 static void flush_maps(kdd_guest *g)
71 {
72 int i;
73 for (i = 0; i < MAPSIZE; i++) {
74 if (g->maps[i] != NULL)
75 munmap(g->maps[i], PAGE_SIZE);
76 g->maps[i] = NULL;
77 }
78 }
79
80
81 /* Halt the guest so we can debug it */
kdd_halt(kdd_guest * g)82 void kdd_halt(kdd_guest *g)
83 {
84 uint32_t sz;
85 void *buf;
86
87 xc_domain_pause(g->xc_handle, g->domid);
88
89 /* How much space do we need for the HVM state? */
90 sz = xc_domain_hvm_getcontext(g->xc_handle, g->domid, 0, 0);
91 if (sz == (uint32_t) -1) {
92 KDD_LOG(g, "Can't get HVM state size for domid %"PRIu32": %s\n",
93 g->domid, strerror(errno));
94 return;
95 }
96 buf = realloc(g->hvm_buf, sz);
97 if (!buf) {
98 KDD_LOG(g, "Couldn't allocate %"PRIu32" for HVM buffer\n", sz);
99 return;
100 }
101 g->hvm_buf = buf;
102 g->hvm_sz = sz;
103 memset(buf, 0, sz);
104
105 /* Get the HVM state */
106 sz = xc_domain_hvm_getcontext(g->xc_handle, g->domid, buf, sz);
107 if (sz == (uint32_t) -1) {
108 KDD_LOG(g, "Can't get HVM state for domid %"PRIu32": %s\n",
109 g->domid, strerror(errno));
110 }
111 }
112
113 /* Check whether the guest has stopped. Returns 'interesting' vcpu or -1 */
114 /* TODO: open DEBUG_VIRQ if it's free and wait for events rather than
115 * always polling the guest state */
kdd_poll_guest(kdd_guest * g)116 int kdd_poll_guest(kdd_guest *g)
117 {
118 /* TODO: finish plumbing through polling for breakpoints */
119 return 0;
120 }
121
122 /* Update the HVM state */
hvm_writeback(kdd_guest * g)123 static void hvm_writeback(kdd_guest *g)
124 {
125 if (g->hvm_buf && xc_domain_hvm_setcontext(g->xc_handle, g->domid,
126 g->hvm_buf, g->hvm_sz))
127 KDD_LOG(g, "Can't set HVM state for domid %"PRIu32": %s\n",
128 g->domid, strerror(errno));
129 }
130
131 /* Start the guest running again */
kdd_run(kdd_guest * g)132 void kdd_run(kdd_guest *g)
133 {
134 flush_maps(g);
135 hvm_writeback(g);
136 xc_domain_unpause(g->xc_handle, g->domid);
137 }
138
139 /* How many CPUs are there in this guest? */
kdd_count_cpus(kdd_guest * g)140 int kdd_count_cpus(kdd_guest *g)
141 {
142 struct hvm_save_descriptor *desc;
143 int maxcpu = 0;
144
145 if (!g->hvm_buf)
146 return 0;
147
148 /* Scan the CPU save records. */
149 for (desc = g->hvm_buf;
150 (void *) desc >= g->hvm_buf && (void *) desc < g->hvm_buf + g->hvm_sz;
151 desc = ((void *)desc) + (sizeof *desc) + desc->length) {
152 if (desc->typecode == HVM_SAVE_CODE(CPU)) {
153 if (maxcpu < desc->instance)
154 maxcpu = desc->instance;
155 }
156 }
157 return maxcpu + 1;
158 }
159
160 /* Helper fn: get CPU state from cached HVM state */
get_cpu(kdd_guest * g,int cpuid)161 static struct hvm_hw_cpu *get_cpu(kdd_guest *g, int cpuid)
162 {
163 struct hvm_save_descriptor *desc;
164 struct hvm_hw_cpu *cpu;
165
166 if (!g->hvm_buf)
167 return NULL;
168
169 /* Find the right CPU */
170 for (desc = g->hvm_buf;
171 (void *) desc >= g->hvm_buf && (void *) desc < g->hvm_buf + g->hvm_sz;
172 desc = ((void *)desc) + (sizeof *desc) + desc->length) {
173 if (desc->typecode == HVM_SAVE_CODE(CPU) && desc->instance == cpuid) {
174 cpu = ((void *)desc) + (sizeof *desc);
175 if ((void *) cpu + sizeof (*cpu) <= g->hvm_buf + g->hvm_sz)
176 return cpu;
177 }
178 }
179
180 KDD_LOG(g, "Dom %"PRIu32" has no CPU %i\n", g->domid, cpuid);
181 return NULL;
182 }
183
184 /* Helper fn: get APIC state from cached HVM state */
get_lapic(kdd_guest * g,int cpuid)185 static struct hvm_hw_lapic_regs *get_lapic(kdd_guest *g, int cpuid)
186 {
187 struct hvm_save_descriptor *desc;
188 struct hvm_hw_lapic_regs *regs;
189
190 if (!g->hvm_buf)
191 return NULL;
192
193 /* Find the right CPU's LAPIC */
194 for (desc = g->hvm_buf;
195 (void *) desc >= g->hvm_buf && (void *) desc < g->hvm_buf + g->hvm_sz;
196 desc = ((void *)desc) + (sizeof *desc) + desc->length) {
197 if (desc->typecode == HVM_SAVE_CODE(LAPIC_REGS) && desc->instance == cpuid) {
198 regs = ((void *)desc) + (sizeof *desc);
199 if ((void *) regs + sizeof (*regs) <= g->hvm_buf + g->hvm_sz)
200 return regs;
201 }
202 }
203
204 KDD_LOG(g, "Dom %"PRIu32" has no LAPIC %i\n", g->domid, cpuid);
205 return NULL;
206 }
207
208
209 /* Accessors for guest user registers */
kdd_get_regs_x86_32(struct hvm_hw_cpu * cpu,kdd_regs_x86_32 * r)210 static void kdd_get_regs_x86_32(struct hvm_hw_cpu *cpu, kdd_regs_x86_32 *r)
211 {
212 r->gs = cpu->gs_sel;
213 r->fs = cpu->fs_sel;
214 r->es = cpu->es_sel;
215 r->ds = cpu->ds_sel;
216 r->edi = cpu->rdi;
217 r->esi = cpu->rsi;
218 r->ebx = cpu->rbx;
219 r->edx = cpu->rdx;
220 r->ecx = cpu->rcx;
221 r->eax = cpu->rax;
222 r->ebp = cpu->rbp;
223 r->eip = cpu->rip;
224 r->cs = cpu->cs_sel;
225 r->eflags = cpu->rflags;
226 r->esp = cpu->rsp;
227 r->ss = cpu->ss_sel;
228 memcpy(r->fp, cpu->fpu_regs, 112); // 108 save area + 4 of ???
229 }
230
kdd_set_regs_x86_32(struct hvm_hw_cpu * cpu,kdd_regs_x86_32 * r)231 static void kdd_set_regs_x86_32(struct hvm_hw_cpu *cpu, kdd_regs_x86_32 *r)
232 {
233 cpu->gs_sel = r->gs;
234 cpu->fs_sel = r->fs;
235 cpu->es_sel = r->es;
236 cpu->ds_sel = r->ds;
237 cpu->rdi = r->edi;
238 cpu->rsi = r->esi;
239 cpu->rbx = r->ebx;
240 cpu->rdx = r->edx;
241 cpu->rcx = r->ecx;
242 cpu->rax = r->eax;
243 cpu->rbp = r->ebp;
244 cpu->rip = r->eip;
245 cpu->cs_sel = r->cs;
246 cpu->rflags = r->eflags;
247 cpu->rsp = r->esp;
248 cpu->ss_sel = r->ss;
249 memcpy(cpu->fpu_regs, r->fp, 112); // 108 save area + 4 of ???
250 }
251
kdd_get_regs_x86_64(struct hvm_hw_cpu * cpu,kdd_regs_x86_64 * r)252 static void kdd_get_regs_x86_64(struct hvm_hw_cpu *cpu, kdd_regs_x86_64 *r)
253 {
254 // XXX debug pattern
255 uint16_t i;
256 for (i = 0 ; i < (sizeof *r / 2) ; i++)
257 ((uint16_t *)r)[i] = i;
258
259 r->cs = cpu->cs_sel;
260 r->ds = cpu->ds_sel;
261 r->es = cpu->es_sel;
262 r->fs = cpu->fs_sel;
263 r->gs = cpu->gs_sel;
264 r->ss = cpu->ss_sel;
265 r->rflags = cpu->rflags;
266 r->dr0 = cpu->dr0;
267 r->dr1 = cpu->dr1;
268 r->dr2 = cpu->dr2;
269 r->dr3 = cpu->dr3;
270 r->dr6 = cpu->dr6;
271 r->dr7 = cpu->dr7;
272 r->rax = cpu->rax;
273 r->rcx = cpu->rcx;
274 r->rdx = cpu->rdx;
275 r->rbx = cpu->rbx;
276 r->rsp = cpu->rsp;
277 r->rbp = cpu->rbp;
278 r->rsi = cpu->rsi;
279 r->rdi = cpu->rdi;
280 r->r8 = cpu->r8;
281 r->r9 = cpu->r9;
282 r->r10 = cpu->r10;
283 r->r11 = cpu->r11;
284 r->r12 = cpu->r12;
285 r->r13 = cpu->r13;
286 r->r14 = cpu->r14;
287 r->r15 = cpu->r15;
288 r->rip = cpu->rip;
289 memcpy(r->fp, cpu->fpu_regs, 112); // Definitely not right
290 }
291
kdd_set_regs_x86_64(struct hvm_hw_cpu * cpu,kdd_regs_x86_64 * r)292 static void kdd_set_regs_x86_64(struct hvm_hw_cpu *cpu, kdd_regs_x86_64 *r)
293 {
294 cpu->cs_sel = r->cs;
295 cpu->ds_sel = r->ds;
296 cpu->es_sel = r->es;
297 cpu->fs_sel = r->fs;
298 cpu->gs_sel = r->gs;
299 cpu->ss_sel = r->ss;
300 cpu->rflags = r->rflags;
301 cpu->dr0 = r->dr0;
302 cpu->dr1 = r->dr1;
303 cpu->dr2 = r->dr2;
304 cpu->dr3 = r->dr3;
305 cpu->dr6 = r->dr6;
306 cpu->dr7 = r->dr7;
307 cpu->rax = r->rax;
308 cpu->rcx = r->rcx;
309 cpu->rdx = r->rdx;
310 cpu->rbx = r->rbx;
311 cpu->rsp = r->rsp;
312 cpu->rbp = r->rbp;
313 cpu->rsi = r->rsi;
314 cpu->rdi = r->rdi;
315 cpu->r8 = r->r8;
316 cpu->r9 = r->r9;
317 cpu->r10 = r->r10;
318 cpu->r11 = r->r11;
319 cpu->r12 = r->r12;
320 cpu->r13 = r->r13;
321 cpu->r14 = r->r14;
322 cpu->r15 = r->r15;
323 cpu->rip = r->rip;
324 memcpy(r->fp, cpu->fpu_regs, 112); // Definitely not right
325 }
326
327
kdd_get_regs(kdd_guest * g,int cpuid,kdd_regs * r,int w64)328 int kdd_get_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64)
329 {
330 struct hvm_hw_cpu *cpu;
331
332 cpu = get_cpu(g, cpuid);
333 if (!cpu)
334 return -1;
335
336 memset(r, 0, sizeof(*r));
337
338 if (w64)
339 kdd_get_regs_x86_64(cpu, &r->r64);
340 else
341 kdd_get_regs_x86_32(cpu, &r->r32);
342
343 return 0;
344 }
345
kdd_set_regs(kdd_guest * g,int cpuid,kdd_regs * r,int w64)346 int kdd_set_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64)
347 {
348 struct hvm_hw_cpu *cpu;
349
350 cpu = get_cpu(g, cpuid);
351 if (!cpu)
352 return -1;
353
354 if (w64)
355 kdd_set_regs_x86_64(cpu, &r->r64);
356 else
357 kdd_set_regs_x86_32(cpu, &r->r32);
358
359 hvm_writeback(g);
360 return 0;
361 }
362
363
364 /* Accessors for guest control registers */
kdd_get_ctrl_x86_32(struct hvm_hw_cpu * cpu,kdd_ctrl_x86_32 * c)365 static void kdd_get_ctrl_x86_32(struct hvm_hw_cpu *cpu, kdd_ctrl_x86_32 *c)
366 {
367 c->cr0 = cpu->cr0;
368 c->cr2 = cpu->cr2;
369 c->cr3 = cpu->cr3;
370 c->cr4 = cpu->cr4;
371 c->dr0 = cpu->dr0;
372 c->dr1 = cpu->dr1;
373 c->dr2 = cpu->dr2;
374 c->dr3 = cpu->dr3;
375 c->dr6 = cpu->dr6;
376 c->dr7 = cpu->dr7;
377 c->gdt_base = cpu->gdtr_base;
378 c->gdt_limit = cpu->gdtr_limit;
379 c->idt_base = cpu->idtr_base;
380 c->idt_limit = cpu->idtr_limit;
381 c->tss_sel = cpu->tr_sel;
382 c->ldt_sel = cpu->ldtr_sel;
383 }
384
kdd_get_ctrl_x86_64(struct hvm_hw_cpu * cpu,struct hvm_hw_lapic_regs * lapic,kdd_ctrl_x86_64 * c)385 static void kdd_get_ctrl_x86_64(struct hvm_hw_cpu *cpu,
386 struct hvm_hw_lapic_regs *lapic,
387 kdd_ctrl_x86_64 *c)
388 {
389 c->cr0 = cpu->cr0;
390 c->cr2 = cpu->cr2;
391 c->cr3 = cpu->cr3;
392 c->cr4 = cpu->cr4;
393 c->dr0 = cpu->dr0;
394 c->dr1 = cpu->dr1;
395 c->dr2 = cpu->dr2;
396 c->dr3 = cpu->dr3;
397 c->dr6 = cpu->dr6;
398 c->dr7 = cpu->dr7;
399 c->gdt_base = cpu->gdtr_base;
400 c->gdt_limit = cpu->gdtr_limit;
401 c->idt_base = cpu->idtr_base;
402 c->idt_limit = cpu->idtr_limit;
403 c->tss_sel = cpu->tr_sel;
404 c->ldt_sel = cpu->ldtr_sel;
405 c->cr8 = lapic->data[0x80] >> 4; /* Top half of the low byte of the TPR */
406 }
407
408
kdd_get_ctrl(kdd_guest * g,int cpuid,kdd_ctrl * ctrl,int w64)409 int kdd_get_ctrl(kdd_guest *g, int cpuid, kdd_ctrl *ctrl, int w64)
410 {
411 struct hvm_hw_cpu *cpu;
412 struct hvm_hw_lapic_regs *lapic;
413
414 cpu = get_cpu(g, cpuid);
415 if (!cpu)
416 return -1;
417
418 if (w64) {
419 lapic = get_lapic(g, cpuid);
420 if (!lapic)
421 return -1;
422 kdd_get_ctrl_x86_64(cpu, lapic, &ctrl->c64);
423 } else {
424 kdd_get_ctrl_x86_32(cpu, &ctrl->c32);
425 }
426
427 return 0;
428 }
429
kdd_wrmsr(kdd_guest * g,int cpuid,uint32_t msr,uint64_t value)430 int kdd_wrmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t value)
431 {
432 struct hvm_hw_cpu *cpu;
433
434 cpu = get_cpu(g, cpuid);
435 if (!cpu)
436 return -1;
437
438 switch (msr) {
439 case 0x00000174: cpu->sysenter_cs = value; break;
440 case 0x00000175: cpu->sysenter_esp = value; break;
441 case 0x00000176: cpu->sysenter_eip = value; break;
442 case 0xc0000080: cpu->msr_efer = value; break;
443 case 0xc0000081: cpu->msr_star = value; break;
444 case 0xc0000082: cpu->msr_lstar = value; break;
445 case 0xc0000083: cpu->msr_cstar = value; break;
446 case 0xc0000084: cpu->msr_syscall_mask = value; break;
447 case 0xc0000100: cpu->fs_base = value; break;
448 case 0xc0000101: cpu->gs_base = value; break;
449 case 0xc0000102: cpu->shadow_gs = value; break;
450 default:
451 return -1;
452 }
453
454 hvm_writeback(g);
455 return 0;
456 }
457
kdd_rdmsr(kdd_guest * g,int cpuid,uint32_t msr,uint64_t * value)458 int kdd_rdmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t *value)
459 {
460 struct hvm_hw_cpu *cpu;
461
462 cpu = get_cpu(g, cpuid);
463 if (!cpu)
464 return -1;
465
466 switch (msr) {
467 case 0x00000174: *value = cpu->sysenter_cs; break;
468 case 0x00000175: *value = cpu->sysenter_esp; break;
469 case 0x00000176: *value = cpu->sysenter_eip; break;
470 case 0xc0000080: *value = cpu->msr_efer; break;
471 case 0xc0000081: *value = cpu->msr_star; break;
472 case 0xc0000082: *value = cpu->msr_lstar; break;
473 case 0xc0000083: *value = cpu->msr_cstar; break;
474 case 0xc0000084: *value = cpu->msr_syscall_mask; break;
475 case 0xc0000100: *value = cpu->fs_base; break;
476 case 0xc0000101: *value = cpu->gs_base; break;
477 case 0xc0000102: *value = cpu->shadow_gs; break;
478 default:
479 return -1;
480 }
481
482 return 0;
483 }
484
485
486 /* Accessor for guest physical memory */
kdd_access_physical_page(kdd_guest * g,uint64_t addr,uint32_t len,uint8_t * buf,int write)487 static uint32_t kdd_access_physical_page(kdd_guest *g, uint64_t addr,
488 uint32_t len, uint8_t *buf, int write)
489 {
490 uint32_t map_pfn, map_offset;
491 uint8_t *map;
492
493 map_pfn = (addr >> PAGE_SHIFT);
494 map_offset = addr & (PAGE_SIZE - 1);
495
496 /* Evict any mapping of the wrong frame from our slot */
497 if (g->pfns[map_pfn % MAPSIZE] != map_pfn
498 && g->maps[map_pfn % MAPSIZE] != NULL) {
499 munmap(g->maps[map_pfn % MAPSIZE], PAGE_SIZE);
500 g->maps[map_pfn % MAPSIZE] = NULL;
501 }
502 g->pfns[map_pfn % MAPSIZE] = map_pfn;
503
504 /* Now map the frame if it's not already there */
505 if (g->maps[map_pfn % MAPSIZE] != NULL)
506 map = g->maps[map_pfn % MAPSIZE];
507 else {
508 map = xc_map_foreign_range(g->xc_handle,
509 g->domid,
510 PAGE_SIZE,
511 PROT_READ|PROT_WRITE,
512 map_pfn);
513
514 KDD_DEBUG(g, "map: %u, 0x%16.16"PRIx32": %p +0x%"PRIx32"\n",
515 write ? PROT_READ|PROT_WRITE : PROT_READ,
516 map_pfn, map, map_offset);
517
518 if (!map)
519 return 0;
520 g->maps[map_pfn % MAPSIZE] = map;
521 }
522
523 if (write)
524 memcpy(map + map_offset, buf, len);
525 else
526 memcpy(buf, map + map_offset, len);
527
528 return len;
529 }
530
kdd_access_physical(kdd_guest * g,uint64_t addr,uint32_t len,uint8_t * buf,int write)531 uint32_t kdd_access_physical(kdd_guest *g, uint64_t addr,
532 uint32_t len, uint8_t *buf, int write)
533 {
534 uint32_t chunk, rv, done = 0;
535 while (len > 0) {
536 chunk = PAGE_SIZE - (addr & (PAGE_SIZE - 1));
537 if (chunk > len)
538 chunk = len;
539 rv = kdd_access_physical_page(g, addr, chunk, buf, write);
540 done += rv;
541 if (rv != chunk)
542 return done;
543 addr += chunk;
544 buf += chunk;
545 len -= chunk;
546 }
547 return done;
548 }
549
550
551 /* Plumb libxc log messages into our own logging */
kdd_xc_log(struct xentoollog_logger * logger,xentoollog_level level,int errnoval,const char * context,const char * format,va_list al)552 static void kdd_xc_log(struct xentoollog_logger *logger,
553 xentoollog_level level,
554 int errnoval /* or -1 */,
555 const char *context /* eg "xc", "xl", may be 0 */,
556 const char *format /* without level, context, \n */,
557 va_list al)
558 {
559 kdd_guest *g = (kdd_guest *) logger;
560 /* Suppress most libxc levels unless we're logging at debug level */
561 if (g->verbosity < 1 || (level < XTL_WARN && g->verbosity < 3))
562 return;
563 fprintf(g->log, "libxc[%s:%i:%i]: ", context ? : "?", level, errnoval);
564 vfprintf(g->log, format, al);
565 fprintf(g->log, "\n");
566 (void) fflush(g->log);
567 }
568
569
570 /* Set up guest-specific state */
kdd_guest_init(char * arg,FILE * log,int verbosity)571 kdd_guest *kdd_guest_init(char *arg, FILE *log, int verbosity)
572 {
573 kdd_guest *g = NULL;
574 xc_interface *xch = NULL;
575 uint32_t domid;
576 xc_dominfo_t info;
577
578 g = calloc(1, sizeof (kdd_guest));
579 if (!g)
580 goto err;
581 g->log = log;
582 g->verbosity = verbosity;
583 g->xc_log.vmessage = kdd_xc_log;
584
585 xch = xc_interface_open(&g->xc_log, NULL, 0);
586 if (!xch)
587 goto err;
588 g->xc_handle = xch;
589
590 domid = strtoul(arg, NULL, 0);
591 if (domid == 0)
592 goto err;
593 g->domid = domid;
594
595 /* Check that the domain exists and is HVM */
596 if (xc_domain_getinfo(xch, domid, 1, &info) != 1 || !info.hvm)
597 goto err;
598
599 snprintf(g->id, (sizeof g->id) - 1,
600 "a xen guest with domain id %i", g->domid);
601
602 return g;
603
604 err:
605 free(g);
606 if (xch)
607 xc_interface_close(xch);
608 return NULL;
609 }
610
611 /* Say what kind of guest this is */
kdd_guest_identify(kdd_guest * g)612 char *kdd_guest_identify(kdd_guest *g)
613 {
614 return g->id;
615 }
616
617 /* Tear down guest-specific state */
kdd_guest_teardown(kdd_guest * g)618 void kdd_guest_teardown(kdd_guest *g)
619 {
620 flush_maps(g);
621 xc_interface_close(g->xc_handle);
622 free(g->hvm_buf);
623 free(g);
624 }
625