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