/* Reload the hardware state from a saved domain */ static int rtc_load(struct domain *d, hvm_domain_context_t *h) { RTCState *s = domain_vrtc(d); if ( !has_vrtc(d) ) return -ENODEV; spin_lock(&s->lock); /* Restore the registers */ if ( hvm_load_entry(RTC, h, &s->hw) != 0 ) { spin_unlock(&s->lock); return -EINVAL; } /* Reset the wall-clock time. In normal running, this runs with host * time, so let's keep doing that. */ s->current_tm = gmtime(get_localtime(d)); rtc_copy_date(s); /* Reset the periodic interrupt timer based on the registers */ rtc_timer_update(s); check_update_timer(s); alarm_timer_update(s); spin_unlock(&s->lock); return 0; }
static int viridian_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { struct hvm_viridian_context ctxt; if ( hvm_load_entry(VIRIDIAN, h, &ctxt) != 0 ) return -EINVAL; d->arch.hvm_domain.viridian.hypercall_gpa.raw = ctxt.hypercall_gpa; d->arch.hvm_domain.viridian.guest_os_id.raw = ctxt.guest_os_id; return 0; }
static int viridian_load_vcpu_ctxt(struct domain *d, hvm_domain_context_t *h) { int vcpuid; struct vcpu *v; struct hvm_viridian_vcpu_context ctxt; vcpuid = hvm_load_instance(h); if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL ) { dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no vcpu%u\n", d->domain_id, vcpuid); return -EINVAL; } if ( hvm_load_entry(VIRIDIAN_VCPU, h, &ctxt) != 0 ) return -EINVAL; v->arch.hvm_vcpu.viridian.apic_assist.raw = ctxt.apic_assist; return 0; }
int hvm_load(struct domain *d, hvm_domain_context_t *h) { 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 ( arch_hvm_load(d, &hdr) ) return -1; 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 { 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) if ( test_and_set_bit(_VPF_down, &v->pause_flags) ) vcpu_sleep_nosync(v); for ( ; ; ) { 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; } /* 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 */ gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", hvm_sr_handlers[desc->typecode].name, desc->instance); 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 */ }