[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Save/restore: clean up marshalling code
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1170239230 0 # Node ID ffcd586dbaae1c1f81132f0d7c697d8699b292bd # Parent 7d3bb465e938575dfa54f362b87337d3ee012f4b [HVM] Save/restore: clean up marshalling code - All entries are now defined as structs and saved/restored in self-contained operations. - Save/restore operations are type-safe, to tie each entry's typecode to a particular struct and its length. - Save/restore handlers are registered once per host instead of per domain. - Detect buffer overrun before it happens and abort. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/domctl.c | 3 xen/arch/x86/hvm/hvm.c | 71 +++--- xen/arch/x86/hvm/i8254.c | 25 +- xen/arch/x86/hvm/intercept.c | 407 +++++++++++++------------------------- xen/arch/x86/hvm/svm/svm.c | 33 --- xen/arch/x86/hvm/vioapic.c | 70 +++--- xen/arch/x86/hvm/vlapic.c | 108 +++++++--- xen/arch/x86/hvm/vmx/vmx.c | 44 +--- xen/arch/x86/hvm/vpic.c | 51 +++- xen/include/asm-x86/hvm/domain.h | 15 - xen/include/asm-x86/hvm/hvm.h | 4 xen/include/asm-x86/hvm/support.h | 230 ++++++++++----------- xen/include/public/hvm/save.h | 83 ++++++- 13 files changed, 553 insertions(+), 591 deletions(-) diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/domctl.c Wed Jan 31 10:27:10 2007 +0000 @@ -302,6 +302,8 @@ long arch_do_domctl( ret = -EFAULT; if ( copy_from_guest(c, domctl->u.hvmcontext.ctxt, 1) != 0 ) goto sethvmcontext_out; + c->size = sizeof (c->data); + c->cur = 0; ret = -EINVAL; if ( !is_hvm_domain(d) ) @@ -330,6 +332,7 @@ long arch_do_domctl( if ( (c = xmalloc(struct hvm_domain_context)) == NULL ) goto gethvmcontext_out; memset(c, 0, sizeof(*c)); + c->size = sizeof (c->data); ret = -ENODATA; if ( !is_hvm_domain(d) ) diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/hvm.c Wed Jan 31 10:27:10 2007 +0000 @@ -168,19 +168,11 @@ int hvm_domain_initialise(struct domain void hvm_domain_destroy(struct domain *d) { - HVMStateEntry *se, *dse; pit_deinit(d); rtc_deinit(d); pmtimer_deinit(d); hpet_deinit(d); - se = d->arch.hvm_domain.first_se; - while (se) { - dse = se; - se = se->next; - xfree(dse); - } - if ( d->arch.hvm_domain.shared_page_va ) unmap_domain_page_global( (void *)d->arch.hvm_domain.shared_page_va); @@ -189,23 +181,43 @@ void hvm_domain_destroy(struct domain *d unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va); } -void hvm_save_cpu_ctxt(hvm_domain_context_t *h, void *opaque) -{ - struct vcpu *v = opaque; - - /* We don't need to save state for a vcpu that is down; the restore - * code will leave it down if there is nothing saved. */ - if ( test_bit(_VCPUF_down, &v->vcpu_flags) ) - return; - - hvm_funcs.save_cpu_ctxt(h, opaque); -} - -int hvm_load_cpu_ctxt(hvm_domain_context_t *h, void *opaque, int version) -{ - struct vcpu *v = opaque; - - if ( hvm_funcs.load_cpu_ctxt(h, opaque, version) < 0 ) +static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) +{ + struct vcpu *v; + struct hvm_hw_cpu ctxt; + + for_each_vcpu(d, v) + { + /* We don't need to save state for a vcpu that is down; the restore + * code will leave it down if there is nothing saved. */ + if ( test_bit(_VCPUF_down, &v->vcpu_flags) ) + continue; + + hvm_funcs.save_cpu_ctxt(v, &ctxt); + if ( hvm_save_entry(CPU, v->vcpu_id, h, &ctxt) != 0 ) + return 1; + } + return 0; +} + +static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) +{ + int vcpuid; + struct vcpu *v; + struct hvm_hw_cpu ctxt; + + /* Which vcpu is this? */ + vcpuid = hvm_load_instance(h); + if ( vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL ) + { + gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid); + return -EINVAL; + } + + if ( hvm_load_entry(CPU, h, &ctxt) != 0 ) + return -EINVAL; + + if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 ) return -EINVAL; /* Auxiliary processors should be woken immediately. */ @@ -215,13 +227,11 @@ int hvm_load_cpu_ctxt(hvm_domain_context return 0; } +HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt); + int hvm_vcpu_initialise(struct vcpu *v) { int rc; - - hvm_register_savevm(v->domain, "xen_hvm_cpu", v->vcpu_id, 1, - hvm_save_cpu_ctxt, hvm_load_cpu_ctxt, - (void *)v); if ( (rc = vlapic_init(v)) != 0 ) return rc; @@ -248,9 +258,6 @@ int hvm_vcpu_initialise(struct vcpu *v) pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); hpet_init(v); - /* init hvm sharepage */ - shpage_init(v->domain, get_sp(v->domain)); - /* Init guest TSC to start from zero. */ hvm_set_guest_time(v, 0); diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/i8254.c Wed Jan 31 10:27:10 2007 +0000 @@ -411,28 +411,24 @@ static void pit_info(PITState *pit) } #endif -static void pit_save(hvm_domain_context_t *h, void *opaque) -{ - struct domain *d = opaque; +static int pit_save(struct domain *d, hvm_domain_context_t *h) +{ PITState *pit = &d->arch.hvm_domain.pl_time.vpit; pit_info(pit); /* Save the PIT hardware state */ - hvm_put_struct(h, &pit->hw); -} - -static int pit_load(hvm_domain_context_t *h, void *opaque, int version_id) -{ - struct domain *d = opaque; + return hvm_save_entry(PIT, 0, h, &pit->hw); +} + +static int pit_load(struct domain *d, hvm_domain_context_t *h) +{ PITState *pit = &d->arch.hvm_domain.pl_time.vpit; int i; - if (version_id != 1) - return -EINVAL; - /* Restore the PIT hardware state */ - hvm_get_struct(h, &pit->hw); + if ( hvm_load_entry(PIT, h, &pit->hw) ) + return 1; /* Recreate platform timers from hardware state. There will be some * time jitter here, but the wall-clock will have jumped massively, so @@ -446,6 +442,8 @@ static int pit_load(hvm_domain_context_t pit_info(pit); return 0; } + +HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load); static void pit_reset(void *opaque) { @@ -474,7 +472,6 @@ void pit_init(struct vcpu *v, unsigned l pt++; pt->vcpu = v; pt++; pt->vcpu = v; - hvm_register_savevm(v->domain, "xen_hvm_i8254", PIT_BASE, 1, pit_save, pit_load, v->domain); register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); /* register the speaker port */ register_portio_handler(v->domain, 0x61, 1, handle_speaker_io); diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/intercept.c Wed Jan 31 10:27:10 2007 +0000 @@ -157,176 +157,129 @@ static inline void hvm_mmio_access(struc } } - -int hvm_register_savevm(struct domain *d, - const char *idstr, - int instance_id, - int version_id, - SaveStateHandler *save_state, - LoadStateHandler *load_state, - void *opaque) -{ - HVMStateEntry *se, **pse; - - if ( (se = xmalloc(struct HVMStateEntry)) == NULL ){ - printk("allocat hvmstate entry fail.\n"); - return -1; - } - - safe_strcpy(se->idstr, idstr); - - se->instance_id = instance_id; - se->version_id = version_id; - se->save_state = save_state; - se->load_state = load_state; - se->opaque = opaque; - se->next = NULL; - - /* add at the end of list */ - pse = &d->arch.hvm_domain.first_se; - while (*pse != NULL) - pse = &(*pse)->next; - *pse = se; - return 0; -} +/* List of handlers for various HVM save and restore types */ +static struct { + hvm_save_handler save; + hvm_load_handler load; +} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL},}; + +/* Init-time function to add entries to that list */ +void hvm_register_savevm(uint16_t typecode, + hvm_save_handler save_state, + hvm_load_handler load_state) +{ + ASSERT(typecode <= HVM_SAVE_CODE_MAX); + ASSERT(hvm_sr_handlers[typecode].save == NULL); + ASSERT(hvm_sr_handlers[typecode].load == NULL); + hvm_sr_handlers[typecode].save = save_state; + hvm_sr_handlers[typecode].load = load_state; +} + int hvm_save(struct domain *d, hvm_domain_context_t *h) { - uint32_t len, len_pos, cur_pos; uint32_t eax, ebx, ecx, edx; - HVMStateEntry *se; - char *chgset; + char *c; struct hvm_save_header hdr; + struct hvm_save_end end; + hvm_save_handler handler; + uint16_t i; hdr.magic = HVM_FILE_MAGIC; hdr.version = HVM_FILE_VERSION; + + /* Save some CPUID bits */ cpuid(1, &eax, &ebx, &ecx, &edx); hdr.cpuid = eax; - hvm_put_struct(h, &hdr); - - /* save xen changeset */ - chgset = strrchr(XEN_CHANGESET, ' '); - if ( chgset ) - chgset++; + + /* Save xen changeset */ + c = strrchr(XEN_CHANGESET, ':'); + if ( c ) + hdr.changeset = simple_strtoll(c, NULL, 16); + else + hdr.changeset = -1ULL; /* Unknown */ + + if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) + { + gdprintk(XENLOG_ERR, "HVM save: failed to write header\n"); + return -1; + } + + /* Save all available kinds of state */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + { + handler = hvm_sr_handlers[i].save; + if ( handler != NULL ) + { + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM save: failed to save type %"PRIu16"\n", i); + return -1; + } + } + } + + /* Save an end-of-file marker */ + if ( hvm_save_entry(END, 0, h, &end) != 0 ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n"); + return -1; + } + + /* Save macros should not have let us overrun */ + ASSERT(h->cur <= h->size); + return 0; +} + +int hvm_load(struct domain *d, hvm_domain_context_t *h) +{ + uint32_t eax, ebx, ecx, edx; + char *c; + uint64_t cset; + struct hvm_save_header hdr; + struct hvm_save_descriptor *desc; + hvm_load_handler handler; + struct vcpu *v; + + /* Read the save header, which must be first */ + if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) + return -1; + + if (hdr.magic != HVM_FILE_MAGIC) { + gdprintk(XENLOG_ERR, + "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic); + return -1; + } + + if (hdr.version != HVM_FILE_VERSION) { + gdprintk(XENLOG_ERR, + "HVM restore: unsupported version %u\n", hdr.version); + return -1; + } + + cpuid(1, &eax, &ebx, &ecx, &edx); + /*TODO: need to define how big a difference is acceptable */ + if (hdr.cpuid != eax) + gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") " + "does not match host (%#"PRIx32").\n", hdr.cpuid, eax); + + + c = strrchr(XEN_CHANGESET, ':'); + if ( hdr.changeset == -1ULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset was not saved.\n"); + else if ( c == NULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset is not available.\n"); else - chgset = XEN_CHANGESET; - - len = strlen(chgset); - hvm_put_8u(h, len); - hvm_put_buffer(h, chgset, len); - - for(se = d->arch.hvm_domain.first_se; se != NULL; se = se->next) { - /* ID string */ - len = strnlen(se->idstr, sizeof(se->idstr)); - hvm_put_8u(h, len); - hvm_put_buffer(h, se->idstr, len); - - hvm_put_32u(h, se->instance_id); - hvm_put_32u(h, se->version_id); - - /* record size */ - len_pos = hvm_ctxt_tell(h); - hvm_put_32u(h, 0); - - se->save_state(h, se->opaque); - - cur_pos = hvm_ctxt_tell(h); - len = cur_pos - len_pos - 4; - hvm_ctxt_seek(h, len_pos); - hvm_put_32u(h, len); - hvm_ctxt_seek(h, cur_pos); - - } - - h->size = hvm_ctxt_tell(h); - hvm_ctxt_seek(h, 0); - - if (h->size >= HVM_CTXT_SIZE) { - printk("hvm_domain_context overflow when hvm_save! need %"PRId32" bytes for use.\n", h->size); - return -1; - } - - return 0; - -} - -static HVMStateEntry *find_se(struct domain *d, const char *idstr, int instance_id) -{ - HVMStateEntry *se; - - for(se = d->arch.hvm_domain.first_se; se != NULL; se = se->next) { - if (!strncmp(se->idstr, idstr, sizeof(se->idstr)) && - instance_id == se->instance_id){ - return se; - } - } - return NULL; -} - -int hvm_load(struct domain *d, hvm_domain_context_t *h) -{ - uint32_t len, rec_len, rec_pos, instance_id, version_id; - uint32_t eax, ebx, ecx, edx; - HVMStateEntry *se; - char idstr[HVM_SE_IDSTR_LEN]; - xen_changeset_info_t chgset; - char *cur_chgset; - int ret; - struct hvm_save_header hdr; - struct vcpu *v; - - if (h->size >= HVM_CTXT_SIZE) { - printk("hvm_load fail! seems hvm_domain_context overflow when hvm_save! need %"PRId32" bytes.\n", h->size); - return -1; - } - - hvm_ctxt_seek(h, 0); - - hvm_get_struct(h, &hdr); - - if (hdr.magic != HVM_FILE_MAGIC) { - printk("HVM restore magic dismatch!\n"); - return -1; - } - - if (hdr.version != HVM_FILE_VERSION) { - printk("HVM restore version dismatch!\n"); - return -1; - } - - /* check cpuid */ - cpuid(1, &eax, &ebx, &ecx, &edx); - /*TODO: need difine how big difference is acceptable */ - if (hdr.cpuid != eax) - printk("warnings: try to restore hvm guest(0x%"PRIx32") " - "on a different type processor(0x%"PRIx32").\n", - hdr.cpuid, - eax); - - - /* check xen change set */ - cur_chgset = strrchr(XEN_CHANGESET, ' '); - if ( cur_chgset ) - cur_chgset++; - else - cur_chgset = XEN_CHANGESET; - - len = hvm_get_8u(h); - if (len > 20) { /*typical length is 18 -- "revision number:changeset id" */ - printk("wrong change set length %d when hvm restore!\n", len); - return -1; - } - - hvm_get_buffer(h, chgset, len); - chgset[len] = '\0'; - if (strncmp(cur_chgset, chgset, len + 1)) - printk("warnings: try to restore hvm guest(%s) on a different changeset %s.\n", - chgset, cur_chgset); - - - if ( !strcmp(cur_chgset, "unavailable") ) - printk("warnings: try to restore hvm guest when changeset is unavailable.\n"); - + { + cset = simple_strtoll(c, NULL, 16); + if ( hdr.changeset != cset ) + gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64 + ") does not match host (%#"PRIx64").\n", hdr.changeset, cset); + } /* Down all the vcpus: we only re-enable the ones that had state saved. */ for_each_vcpu(d, v) @@ -334,109 +287,43 @@ int hvm_load(struct domain *d, hvm_domai vcpu_sleep_nosync(v); while(1) { - if (hvm_ctxt_end(h)) { - break; - } - - /* ID string */ - len = hvm_get_8u(h); - if (len > HVM_SE_IDSTR_LEN) { - printk("wrong HVM save entry idstr len %d!", len); + + if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, + "HVM restore: save did not end with a null entry\n"); return -1; } - - hvm_get_buffer(h, idstr, len); - idstr[len] = '\0'; - - instance_id = hvm_get_32u(h); - version_id = hvm_get_32u(h); - - printk("HVM S/R Loading \"%s\" instance %#x\n", idstr, instance_id); - - rec_len = hvm_get_32u(h); - rec_pos = hvm_ctxt_tell(h); - - se = find_se(d, idstr, instance_id); - if (se == NULL) { - printk("warnings: hvm load can't find device %s's instance %d!\n", - idstr, instance_id); - } else { - ret = se->load_state(h, se->opaque, version_id); - if (ret < 0) - printk("warnings: loading state fail for device %s instance %d!\n", - idstr, instance_id); - } - - - /* make sure to jump end of record */ - if ( hvm_ctxt_tell(h) - rec_pos != rec_len) { - printk("wrong hvm record size, maybe some dismatch between save&restore handler!\n"); - } - hvm_ctxt_seek(h, rec_pos + rec_len); - } - - return 0; -} - - -#ifdef HVM_DEBUG_SUSPEND -static void shpage_info(shared_iopage_t *sh) -{ - - vcpu_iodata_t *p = &sh->vcpu_iodata[0]; - ioreq_t *req = &p->vp_ioreq; - printk("*****sharepage_info******!\n"); - printk("vp_eport=%d\n", p->vp_eport); - printk("io packet: " - "state:%x, pvalid: %x, dir:%x, port: %"PRIx64", " - "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", - req->state, req->data_is_ptr, req->dir, req->addr, - req->data, req->count, req->size); -} -#else -static void shpage_info(shared_iopage_t *sh) -{ -} -#endif - -static void shpage_save(hvm_domain_context_t *h, void *opaque) -{ - /* XXX:no action required for shpage save/restore, since it's in guest memory - * keep it for debug purpose only */ - -#if 0 - struct shared_iopage *s = opaque; - /* XXX:smp */ - struct ioreq *req = &s->vcpu_iodata[0].vp_ioreq; - - shpage_info(s); - - hvm_put_buffer(h, (char*)req, sizeof(struct ioreq)); -#endif -} - -static int shpage_load(hvm_domain_context_t *h, void *opaque, int version_id) -{ - struct shared_iopage *s = opaque; -#if 0 - /* XXX:smp */ - struct ioreq *req = &s->vcpu_iodata[0].vp_ioreq; - - if (version_id != 1) - return -EINVAL; - - hvm_get_buffer(h, (char*)req, sizeof(struct ioreq)); - - -#endif - shpage_info(s); - return 0; -} - -void shpage_init(struct domain *d, shared_iopage_t *sp) -{ - hvm_register_savevm(d, "xen_hvm_shpage", 0x10, 1, shpage_save, shpage_load, sp); -} + + /* Read the typecode of the next entry and check for the end-marker */ + desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); + if ( desc->typecode == 0 ) + return 0; + + /* Find the handler for this entry */ + if ( desc->typecode > HVM_SAVE_CODE_MAX + || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) + { + gdprintk(XENLOG_ERR, + "HVM restore: unknown entry typecode %u\n", + desc->typecode); + return -1; + } + + /* Load the entry */ + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM restore: failed to load entry %u/%u\n", + desc->typecode, desc->instance); + return -1; + } + } + + /* Not reached */ +} + int hvm_buffered_io_intercept(ioreq_t *p) { diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Jan 31 10:27:10 2007 +0000 @@ -603,29 +603,16 @@ void svm_load_cpu_state(struct vcpu *v, // dump_msr_state(guest_state); } -void svm_save_vmcb_ctxt(hvm_domain_context_t *h, void *opaque) -{ - struct vcpu *v = opaque; - struct hvm_hw_cpu ctxt; - - svm_save_cpu_state(v, &ctxt); - - svm_vmcs_save(v, &ctxt); - - hvm_put_struct(h, &ctxt); -} - -int svm_load_vmcb_ctxt(hvm_domain_context_t *h, void *opaque, int version) -{ - struct vcpu *v = opaque; - struct hvm_hw_cpu ctxt; - - if (version != 1) - return -EINVAL; - - hvm_get_struct(h, &ctxt); - svm_load_cpu_state(v, &ctxt); - if (svm_vmcb_restore(v, &ctxt)) { +void svm_save_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) +{ + svm_save_cpu_state(v, ctxt); + svm_vmcs_save(v, ctxt); +} + +int svm_load_vmcb_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) +{ + svm_load_cpu_state(v, ctxt); + if (svm_vmcb_restore(v, ctxt)) { printk("svm_vmcb restore failed!\n"); domain_crash(v->domain); return -EINVAL; diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/vioapic.c Wed Jan 31 10:27:10 2007 +0000 @@ -523,49 +523,57 @@ static void hvmirq_info(struct hvm_hw_ir } #endif -static void ioapic_save(hvm_domain_context_t *h, void *opaque) -{ - struct domain *d = opaque; + +static int ioapic_save(struct domain *d, hvm_domain_context_t *h) +{ struct hvm_hw_vioapic *s = domain_vioapic(d); + ioapic_info(s); + + /* save io-apic state*/ + return ( hvm_save_entry(IOAPIC, 0, h, s) ); +} + +static int ioapic_save_irqs(struct domain *d, hvm_domain_context_t *h) +{ struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; + hvmirq_info(hvm_irq); + + /* save IRQ state*/ + return ( hvm_save_entry(IRQ, 0, h, hvm_irq) ); +} + + +static int ioapic_load(struct domain *d, hvm_domain_context_t *h) +{ + struct hvm_hw_vioapic *s = domain_vioapic(d); + + /* restore ioapic state */ + if ( hvm_load_entry(IOAPIC, h, s) != 0 ) + return -EINVAL; ioapic_info(s); + return 0; +} + +static int ioapic_load_irqs(struct domain *d, hvm_domain_context_t *h) +{ + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; + + /* restore irq state */ + if ( hvm_load_entry(IRQ, h, hvm_irq) != 0 ) + return -EINVAL; + hvmirq_info(hvm_irq); - - /* save io-apic state*/ - hvm_put_struct(h, s); - - /* save hvm irq state */ - hvm_put_struct(h, hvm_irq); -} - -static int ioapic_load(hvm_domain_context_t *h, void *opaque, int version_id) -{ - struct domain *d = opaque; - struct hvm_hw_vioapic *s = domain_vioapic(d); - struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; - - if (version_id != 1) - return -EINVAL; - - /* restore ioapic state */ - hvm_get_struct(h, s); - - /* restore irq state */ - hvm_get_struct(h, hvm_irq); - - ioapic_info(s); - hvmirq_info(hvm_irq); - return 0; } + +HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load); +HVM_REGISTER_SAVE_RESTORE(IRQ, ioapic_save_irqs, ioapic_load_irqs); void vioapic_init(struct domain *d) { struct hvm_hw_vioapic *vioapic = domain_vioapic(d); int i; - - hvm_register_savevm(d, "xen_hvm_ioapic", 0, 1, ioapic_save, ioapic_load, d); memset(vioapic, 0, sizeof(*vioapic)); for ( i = 0; i < VIOAPIC_NUM_PINS; i++ ) diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/vlapic.c Wed Jan 31 10:27:10 2007 +0000 @@ -810,50 +810,105 @@ static void lapic_info(struct vlapic *s) } #endif -static void lapic_save(hvm_domain_context_t *h, void *opaque) -{ - struct vlapic *s = opaque; - - lapic_info(s); - - hvm_put_struct(h, &s->hw); - hvm_put_struct(h, s->regs); -} - -static int lapic_load(hvm_domain_context_t *h, void *opaque, int version_id) -{ - struct vlapic *s = opaque; - struct vcpu *v = vlapic_vcpu(s); +/* rearm the actimer if needed, after a HVM restore */ +static void lapic_rearm(struct vlapic *s) +{ unsigned long tmict; - if (version_id != 1) - return -EINVAL; - - hvm_get_struct(h, &s->hw); - hvm_get_struct(h, s->regs); - - /* rearm the actiemr if needed */ tmict = vlapic_get_reg(s, APIC_TMICT); if (tmict > 0) { uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->hw.timer_divisor; uint32_t lvtt = vlapic_get_reg(s, APIC_LVTT); s->pt.irq = lvtt & APIC_VECTOR_MASK; - create_periodic_time(v, &s->pt, period, s->pt.irq, + create_periodic_time(vlapic_vcpu(s), &s->pt, period, s->pt.irq, vlapic_lvtt_period(s), NULL, s); printk("lapic_load to rearm the actimer:" "bus cycle is %uns, " "saved tmict count %lu, period %"PRIu64"ns, irq=%"PRIu8"\n", APIC_BUS_CYCLE_NS, tmict, period, s->pt.irq); - - } - + } lapic_info(s); - +} + +static int lapic_save_hidden(struct domain *d, hvm_domain_context_t *h) +{ + struct vcpu *v; + struct vlapic *s; + + for_each_vcpu(d, v) + { + s = vcpu_vlapic(v); + lapic_info(s); + + if ( hvm_save_entry(LAPIC, v->vcpu_id, h, &s->hw) != 0 ) + return 1; + } return 0; } + +static int lapic_save_regs(struct domain *d, hvm_domain_context_t *h) +{ + struct vcpu *v; + struct vlapic *s; + + for_each_vcpu(d, v) + { + s = vcpu_vlapic(v); + if ( hvm_save_entry(LAPIC_REGS, v->vcpu_id, h, s->regs) != 0 ) + return 1; + } + return 0; +} + +static int lapic_load_hidden(struct domain *d, hvm_domain_context_t *h) +{ + uint16_t vcpuid; + struct vcpu *v; + struct vlapic *s; + + /* Which vlapic to load? */ + vcpuid = hvm_load_instance(h); + if ( vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL ) + { + gdprintk(XENLOG_ERR, "HVM restore: domain has no vlapic %u\n", vcpuid); + return -EINVAL; + } + s = vcpu_vlapic(v); + + if ( hvm_load_entry(LAPIC, h, &s->hw) != 0 ) + return -EINVAL; + + lapic_info(s); + return 0; +} + +static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h) +{ + uint16_t vcpuid; + struct vcpu *v; + struct vlapic *s; + + /* Which vlapic to load? */ + vcpuid = hvm_load_instance(h); + if ( vcpuid > MAX_VIRT_CPUS || (v = d->vcpu[vcpuid]) == NULL ) + { + gdprintk(XENLOG_ERR, "HVM restore: domain has no vlapic %u\n", vcpuid); + return -EINVAL; + } + s = vcpu_vlapic(v); + + if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) + return -EINVAL; + + lapic_rearm(s); + return 0; +} + +HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden); +HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs); int vlapic_init(struct vcpu *v) { @@ -873,7 +928,6 @@ int vlapic_init(struct vcpu *v) vlapic->regs = map_domain_page_global(page_to_mfn(vlapic->regs_page)); memset(vlapic->regs, 0, PAGE_SIZE); - hvm_register_savevm(v->domain, "xen_hvm_lapic", v->vcpu_id, 1, lapic_save, lapic_load, vlapic); vlapic_reset(vlapic); vlapic->hw.apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jan 31 10:27:10 2007 +0000 @@ -364,19 +364,9 @@ static inline void __restore_debug_regis /* DR7 is loaded from the VMCS. */ } -static int __get_instruction_length(void); int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) -{ - unsigned long inst_len; - - inst_len = __get_instruction_length(); +{ c->eip = __vmread(GUEST_RIP); - -#ifdef HVM_DEBUG_SUSPEND - printk("vmx_vmcs_save: inst_len=0x%lx, eip=0x%"PRIx64".\n", - inst_len, c->eip); -#endif - c->esp = __vmread(GUEST_RSP); c->eflags = __vmread(GUEST_RFLAGS); @@ -632,30 +622,18 @@ void vmx_load_cpu_state(struct vcpu *v, } -void vmx_save_vmcs_ctxt(hvm_domain_context_t *h, void *opaque) -{ - struct vcpu *v = opaque; - struct hvm_hw_cpu ctxt; - - vmx_save_cpu_state(v, &ctxt); +void vmx_save_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) +{ + vmx_save_cpu_state(v, ctxt); vmx_vmcs_enter(v); - vmx_vmcs_save(v, &ctxt); + vmx_vmcs_save(v, ctxt); vmx_vmcs_exit(v); - - hvm_put_struct(h, &ctxt); -} - -int vmx_load_vmcs_ctxt(hvm_domain_context_t *h, void *opaque, int version) -{ - struct vcpu *v = opaque; - struct hvm_hw_cpu ctxt; - - if (version != 1) - return -EINVAL; - - hvm_get_struct(h, &ctxt); - vmx_load_cpu_state(v, &ctxt); - if (vmx_vmcs_restore(v, &ctxt)) { +} + +int vmx_load_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) +{ + vmx_load_cpu_state(v, ctxt); + if (vmx_vmcs_restore(v, ctxt)) { printk("vmx_vmcs restore failed!\n"); domain_crash(v->domain); return -EINVAL; diff -r 7d3bb465e938 -r ffcd586dbaae xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/arch/x86/hvm/vpic.c Wed Jan 31 10:27:10 2007 +0000 @@ -404,26 +404,43 @@ static void vpic_info(struct hvm_hw_vpic } #endif -static void vpic_save(hvm_domain_context_t *h, void *opaque) -{ - struct hvm_hw_vpic *s = opaque; +static int vpic_save(struct domain *d, hvm_domain_context_t *h) +{ + struct hvm_hw_vpic *s; + int i; + + /* Save the state of both PICs */ + for ( i = 0; i < 2 ; i++ ) + { + s = &d->arch.hvm_domain.vpic[i]; + vpic_info(s); + if ( hvm_save_entry(PIC, i, h, s) ) + return 1; + } + + return 0; +} + +static int vpic_load(struct domain *d, hvm_domain_context_t *h) +{ + struct hvm_hw_vpic *s; + uint16_t inst; + /* Which PIC is this? */ + inst = hvm_load_instance(h); + if ( inst > 1 ) + return -EINVAL; + s = &d->arch.hvm_domain.vpic[inst]; + + /* Load the state */ + if ( hvm_load_entry(PIC, h, s) != 0 ) + return -EINVAL; + vpic_info(s); - hvm_put_struct(h, s); -} - -static int vpic_load(hvm_domain_context_t *h, void *opaque, int version_id) -{ - struct hvm_hw_vpic *s = opaque; - - if (version_id != 1) - return -EINVAL; - - hvm_get_struct(h, s); - vpic_info(s); - return 0; } + +HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load); void vpic_init(struct domain *d) { @@ -434,14 +451,12 @@ void vpic_init(struct domain *d) memset(vpic, 0, sizeof(*vpic)); vpic->is_master = 1; vpic->elcr = 1 << 2; - hvm_register_savevm(d, "xen_hvm_i8259", 0x20, 1, vpic_save, vpic_load, vpic); register_portio_handler(d, 0x20, 2, vpic_intercept_pic_io); register_portio_handler(d, 0x4d0, 1, vpic_intercept_elcr_io); /* Slave PIC. */ vpic++; memset(vpic, 0, sizeof(*vpic)); - hvm_register_savevm(d, "xen_hvm_i8259", 0xa0, 1, vpic_save, vpic_load, vpic); register_portio_handler(d, 0xa0, 2, vpic_intercept_pic_io); register_portio_handler(d, 0x4d1, 1, vpic_intercept_elcr_io); } diff -r 7d3bb465e938 -r ffcd586dbaae xen/include/asm-x86/hvm/domain.h --- a/xen/include/asm-x86/hvm/domain.h Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/include/asm-x86/hvm/domain.h Wed Jan 31 10:27:10 2007 +0000 @@ -28,20 +28,6 @@ #include <public/hvm/params.h> #include <public/hvm/save.h> -typedef void SaveStateHandler(hvm_domain_context_t *h, void *opaque); -typedef int LoadStateHandler(hvm_domain_context_t *h, void *opaque, int version_id); - -#define HVM_SE_IDSTR_LEN 32 -typedef struct HVMStateEntry { - char idstr[HVM_SE_IDSTR_LEN]; - int instance_id; - int version_id; - SaveStateHandler *save_state; - LoadStateHandler *load_state; - void *opaque; - struct HVMStateEntry *next; -} HVMStateEntry; - struct hvm_domain { unsigned long shared_page_va; unsigned long buffered_io_va; @@ -65,7 +51,6 @@ struct hvm_domain { uint64_t params[HVM_NR_PARAMS]; struct hvm_domain_context *hvm_ctxt; - HVMStateEntry *first_se; }; #endif /* __ASM_X86_HVM_DOMAIN_H__ */ diff -r 7d3bb465e938 -r ffcd586dbaae xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/include/asm-x86/hvm/hvm.h Wed Jan 31 10:27:10 2007 +0000 @@ -83,8 +83,8 @@ struct hvm_function_table { struct vcpu *v, struct cpu_user_regs *r); /* save and load hvm guest cpu context for save/restore */ - void (*save_cpu_ctxt)(hvm_domain_context_t *h, void *opaque); - int (*load_cpu_ctxt)(hvm_domain_context_t *h, void *opaque, int version); + void (*save_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt); + int (*load_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt); /* * Examine specifics of the guest state: diff -r 7d3bb465e938 -r ffcd586dbaae xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/include/asm-x86/hvm/support.h Wed Jan 31 10:27:10 2007 +0000 @@ -119,133 +119,121 @@ extern unsigned int opt_hvm_debug_level; #define TRACE_VMEXIT(index, value) \ current->arch.hvm_vcpu.hvm_trace_values[index] = (value) -/* save/restore support */ - -//#define HVM_DEBUG_SUSPEND - -extern int hvm_register_savevm(struct domain *d, - const char *idstr, - int instance_id, - int version_id, - SaveStateHandler *save_state, - LoadStateHandler *load_state, - void *opaque); - -static inline void hvm_ctxt_seek(hvm_domain_context_t *h, unsigned int pos) -{ - h->cur = pos; -} - -static inline uint32_t hvm_ctxt_tell(hvm_domain_context_t *h) -{ - return h->cur; -} - -static inline int hvm_ctxt_end(hvm_domain_context_t *h) -{ - return (h->cur >= h->size || h->cur >= HVM_CTXT_SIZE); -} - -static inline void hvm_put_byte(hvm_domain_context_t *h, unsigned int i) -{ - if (h->cur >= HVM_CTXT_SIZE) { - h->cur++; - return; +/* + * Save/restore support + */ + +/* Marshalling an entry: check space and fill in the header */ +static inline int _hvm_init_entry(struct hvm_domain_context *h, + uint16_t tc, uint16_t inst, uint32_t len) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + if ( h->size - h->cur < len + sizeof (*d) ) + { + gdprintk(XENLOG_WARNING, + "HVM save: no room for %"PRIu32" + %u bytes " + "for typecode %"PRIu16"\n", + len, (unsigned) sizeof (*d), tc); + return -1; } - h->data[h->cur++] = (char)i; -} - -static inline void hvm_put_8u(hvm_domain_context_t *h, uint8_t b) -{ - hvm_put_byte(h, b); -} - -static inline void hvm_put_16u(hvm_domain_context_t *h, uint16_t b) -{ - hvm_put_8u(h, b >> 8); - hvm_put_8u(h, b); -} - -static inline void hvm_put_32u(hvm_domain_context_t *h, uint32_t b) -{ - hvm_put_16u(h, b >> 16); - hvm_put_16u(h, b); -} - -static inline void hvm_put_64u(hvm_domain_context_t *h, uint64_t b) -{ - hvm_put_32u(h, b >> 32); - hvm_put_32u(h, b); -} - -static inline void hvm_put_buffer(hvm_domain_context_t *h, const char *buf, int len) -{ - memcpy(&h->data[h->cur], buf, len); - h->cur += len; -} - -static inline char hvm_get_byte(hvm_domain_context_t *h) -{ - if (h->cur >= HVM_CTXT_SIZE) { - printk("hvm_get_byte overflow.\n"); + d->typecode = tc; + d->instance = inst; + d->length = len; + h->cur += sizeof (*d); + return 0; +} + +/* Marshalling: copy the contents in a type-safe way */ +#define _hvm_write_entry(_x, _h, _src) do { \ + *(HVM_SAVE_TYPE(_x) *)(&(_h)->data[(_h)->cur]) = *(_src); \ + (_h)->cur += HVM_SAVE_LENGTH(_x); \ +} while (0) + +/* Marshalling: init and copy; evaluates to zero on success */ +#define hvm_save_entry(_x, _inst, _h, _src) ({ \ + int r; \ + r = _hvm_init_entry((_h), HVM_SAVE_CODE(_x), \ + (_inst), HVM_SAVE_LENGTH(_x)); \ + if ( r == 0 ) \ + _hvm_write_entry(_x, (_h), (_src)); \ + r; }) + +/* Unmarshalling: test an entry's size and typecode and record the instance */ +static inline int _hvm_check_entry(struct hvm_domain_context *h, + uint16_t type, uint32_t len) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + if ( len + sizeof (*d) > h->size - h->cur) + { + gdprintk(XENLOG_WARNING, + "HVM restore: not enough data left to read %u bytes " + "for type %u\n", len, type); + return -1; + } + if ( type != d->typecode || len != d->length ) + { + gdprintk(XENLOG_WARNING, + "HVM restore mismatch: expected type %u length %u, " + "saw type %u length %u\n", type, len, d->typecode, d->length); return -1; } - - if (h->cur >= h->size) { - printk("hvm_get_byte exceed data area.\n"); - return -1; - } - - return h->data[h->cur++]; -} - -static inline uint8_t hvm_get_8u(hvm_domain_context_t *h) -{ - return hvm_get_byte(h); -} - -static inline uint16_t hvm_get_16u(hvm_domain_context_t *h) -{ - uint16_t v; - v = hvm_get_8u(h) << 8; - v |= hvm_get_8u(h); - - return v; -} - -static inline uint32_t hvm_get_32u(hvm_domain_context_t *h) -{ - uint32_t v; - v = hvm_get_16u(h) << 16; - v |= hvm_get_16u(h); - - return v; -} - -static inline uint64_t hvm_get_64u(hvm_domain_context_t *h) -{ - uint64_t v; - v = (uint64_t)hvm_get_32u(h) << 32; - v |= hvm_get_32u(h); - - return v; -} - -static inline void hvm_get_buffer(hvm_domain_context_t *h, char *buf, int len) -{ - memcpy(buf, &h->data[h->cur], len); - h->cur += len; -} - -#define hvm_put_struct(_h, _p) \ - hvm_put_buffer((_h), (char *)(_p), sizeof(*(_p))) -#define hvm_get_struct(_h, _p) \ - hvm_get_buffer((_h), (char *)(_p), sizeof(*(_p))) - + h->cur += sizeof (*d); + return 0; +} + +/* Unmarshalling: copy the contents in a type-safe way */ +#define _hvm_read_entry(_x, _h, _dst) do { \ + *(_dst) = *(HVM_SAVE_TYPE(_x) *) (&(_h)->data[(_h)->cur]); \ + (_h)->cur += HVM_SAVE_LENGTH(_x); \ +} while (0) + +/* Unmarshalling: check, then copy. Evaluates to zero on success. */ +#define hvm_load_entry(_x, _h, _dst) ({ \ + int r; \ + r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x), HVM_SAVE_LENGTH(_x)); \ + if ( r == 0 ) \ + _hvm_read_entry(_x, (_h), (_dst)); \ + r; }) + +/* Unmarshalling: what is the instance ID of the next entry? */ +static inline uint16_t hvm_load_instance(struct hvm_domain_context *h) +{ + struct hvm_save_descriptor *d + = (struct hvm_save_descriptor *)&h->data[h->cur]; + return d->instance; +} + +/* Handler types for different types of save-file entry. + * The save handler may save multiple instances of a type into the buffer; + * the load handler will be called once for each instance found when + * restoring. Both return non-zero on error. */ +typedef int (*hvm_save_handler) (struct domain *d, + hvm_domain_context_t *h); +typedef int (*hvm_load_handler) (struct domain *d, + hvm_domain_context_t *h); + +/* Init-time function to declare a pair of handlers for a type */ +void hvm_register_savevm(uint16_t typecode, + hvm_save_handler save_state, + hvm_load_handler load_state); + +/* Syntactic sugar around that function */ +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ +static int __hvm_register_##_x##_save_and_restore(void) \ +{ \ + hvm_register_savevm(HVM_SAVE_CODE(_x), &_save, &_load); \ + return 0; \ +} \ +__initcall(__hvm_register_##_x##_save_and_restore); + + +/* Entry points for saving and restoring HVM domain state */ int hvm_save(struct domain *d, hvm_domain_context_t *h); int hvm_load(struct domain *d, hvm_domain_context_t *h); -void shpage_init(struct domain *d, shared_iopage_t *sp); +/* End of save/restore */ extern char hvm_io_bitmap[]; extern int hvm_enabled; diff -r 7d3bb465e938 -r ffcd586dbaae xen/include/public/hvm/save.h --- a/xen/include/public/hvm/save.h Wed Jan 31 10:11:26 2007 +0000 +++ b/xen/include/public/hvm/save.h Wed Jan 31 10:27:10 2007 +0000 @@ -40,24 +40,52 @@ */ /* - * Save/restore header - */ - -#define HVM_SAVE_TYPE_HEADER 0 + * Each entry is preceded by a descriptor giving its type and length + */ +struct hvm_save_descriptor { + uint16_t typecode; /* Used to demux the various types below */ + uint16_t instance; /* Further demux within a type */ + uint32_t length; /* In bytes, *not* including this descriptor */ +}; + + +/* + * Each entry has a datatype associated with it: for example, the CPU state + * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU), + * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU). + * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system + * ugliness. + */ + +#define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \ + struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; } + +#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t) +#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x))) +#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c)) + + +/* + * Save/restore header: general info about the save file. + */ #define HVM_FILE_MAGIC 0x54381286 #define HVM_FILE_VERSION 0x00000001 struct hvm_save_header { - uint32_t magic; - uint32_t version; - uint32_t cpuid; -}; + uint32_t magic; /* Must be HVM_FILE_MAGIC */ + uint32_t version; /* File format version */ + uint64_t changeset; /* Version of Xen that saved this file */ + uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */ +}; + +DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); + /* * Processor */ -#define HVM_SAVE_TYPE_CPU 1 + struct hvm_hw_cpu { uint64_t eip; uint64_t esp; @@ -124,11 +152,13 @@ struct hvm_hw_cpu { uint64_t tsc; }; +DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu); + /* * PIT */ -#define HVM_SAVE_TYPE_PIT 2 + struct hvm_hw_pit { struct hvm_hw_pit_channel { int64_t count_load_time; @@ -148,11 +178,13 @@ struct hvm_hw_pit { uint32_t speaker_data_on; }; +DECLARE_HVM_SAVE_TYPE(PIT, 3, struct hvm_hw_pit); + /* * PIC */ -#define HVM_SAVE_TYPE_PIC 3 + struct hvm_hw_vpic { /* IR line bitmasks. */ uint8_t irr; @@ -201,11 +233,12 @@ struct hvm_hw_vpic { uint8_t int_output; }; +DECLARE_HVM_SAVE_TYPE(PIC, 4, struct hvm_hw_vpic); + /* * IO-APIC */ -#define HVM_SAVE_TYPE_IOAPIC 4 #ifdef __ia64__ #define VIOAPIC_IS_IOSAPIC 1 @@ -242,11 +275,13 @@ struct hvm_hw_vioapic { } redirtbl[VIOAPIC_NUM_PINS]; }; +DECLARE_HVM_SAVE_TYPE(IOAPIC, 5, struct hvm_hw_vioapic); + /* * IRQ */ -#define HVM_SAVE_TYPE_IRQ 5 + struct hvm_hw_irq { /* * Virtual interrupt wires for a single PCI bus. @@ -309,22 +344,40 @@ struct hvm_hw_irq { u8 round_robin_prev_vcpu; }; +DECLARE_HVM_SAVE_TYPE(IRQ, 6, struct hvm_hw_irq); /* * LAPIC */ -#define HVM_SAVE_TYPE_LAPIC 6 + struct hvm_hw_lapic { uint64_t apic_base_msr; uint32_t disabled; /* VLAPIC_xx_DISABLED */ uint32_t timer_divisor; }; -#define HVM_SAVE_TYPE_LAPIC_REGS 7 +DECLARE_HVM_SAVE_TYPE(LAPIC, 7, struct hvm_hw_lapic); struct hvm_hw_lapic_regs { /* A 4k page of register state */ uint8_t data[0x400]; }; +DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 8, struct hvm_hw_lapic_regs); + + +/* + * Largest type-code in use + */ +#define HVM_SAVE_CODE_MAX 8 + + +/* + * The series of save records is teminated by a zero-type, zero-length + * descriptor. + */ + +struct hvm_save_end {}; +DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end); + #endif /* __XEN_PUBLIC_HVM_SAVE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |