void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { VMStateField *field = vmsd->fields; if (vmsd->pre_save) { vmsd->pre_save(opaque); } while (field->name) { if (!field->field_exists || field->field_exists(opaque, vmsd->version_id)) { void *base_addr = opaque + field->offset; int i, n_elems = 1; int size = field->size; if (field->flags & VMS_VBUFFER) { size = *(int32_t *)(opaque+field->size_offset); if (field->flags & VMS_MULTIPLY) { size *= field->size; } } if (field->flags & VMS_ARRAY) { n_elems = field->num; } else if (field->flags & VMS_VARRAY_INT32) { n_elems = *(int32_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT32) { n_elems = *(uint32_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT16) { n_elems = *(uint16_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT8) { n_elems = *(uint8_t *)(opaque+field->num_offset); } if (field->flags & VMS_POINTER) { base_addr = *(void **)base_addr + field->start; } for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { vmstate_save_state(f, field->vmsd, addr); } else { field->info->put(f, addr, size); } } } field++; } vmstate_subsection_save(f, vmsd, opaque); }
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { VMStateField *field = vmsd->fields; if (vmsd->pre_save) { vmsd->pre_save(opaque); } while (field->name) { if (!field->field_exists || field->field_exists(opaque, vmsd->version_id)) { void *base_addr = vmstate_base_addr(opaque, field); int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { vmstate_save_state(f, field->vmsd, addr); } else { field->info->put(f, addr, size); } } } else { if (field->flags & VMS_MUST_EXIST) { fprintf(stderr, "Output state validation failed: %s/%s\n", vmsd->name, field->name); assert(!(field->flags & VMS_MUST_EXIST)); } } field++; } vmstate_subsection_save(f, vmsd, opaque); }
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id) { VMStateField *field = vmsd->fields; int ret; if (version_id > vmsd->version_id) { return -EINVAL; } if (version_id < vmsd->minimum_version_id) { if (vmsd->load_state_old && version_id >= vmsd->minimum_version_id_old) { return vmsd->load_state_old(f, opaque, version_id); } return -EINVAL; } if (vmsd->pre_load) { int ret = vmsd->pre_load(opaque); if (ret) { return ret; } } while (field->name) { if ((field->field_exists && field->field_exists(opaque, version_id)) || (!field->field_exists && field->version_id <= version_id)) { void *base_addr = vmstate_base_addr(opaque, field); int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); } else { ret = field->info->get(f, addr, size); } if (ret < 0) { trace_vmstate_load_field_error(field->name, ret); return ret; } } } else if (field->flags & VMS_MUST_EXIST) { fprintf(stderr, "Input validation failed: %s/%s\n", vmsd->name, field->name); return -1; } field++; } ret = vmstate_subsection_load(f, vmsd, opaque); if (ret != 0) { return ret; } if (vmsd->post_load) { return vmsd->post_load(opaque, version_id); } return 0; }
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id) { VMStateField *field = vmsd->fields; int ret; if (version_id > vmsd->version_id) { return -EINVAL; } if (version_id < vmsd->minimum_version_id_old) { return -EINVAL; } if (version_id < vmsd->minimum_version_id) { return vmsd->load_state_old(f, opaque, version_id); } if (vmsd->pre_load) { int ret = vmsd->pre_load(opaque); if (ret) { return ret; } } while (field->name) { if ((field->field_exists && field->field_exists(opaque, version_id)) || (!field->field_exists && field->version_id <= version_id)) { void *base_addr = opaque + field->offset; int i, n_elems = 1; int size = field->size; if (field->flags & VMS_VBUFFER) { size = *(int32_t *)(opaque+field->size_offset); if (field->flags & VMS_MULTIPLY) { size *= field->size; } } if (field->flags & VMS_ARRAY) { n_elems = field->num; } else if (field->flags & VMS_VARRAY_INT32) { n_elems = *(int32_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT32) { n_elems = *(uint32_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT16) { n_elems = *(uint16_t *)(opaque+field->num_offset); } else if (field->flags & VMS_VARRAY_UINT8) { n_elems = *(uint8_t *)(opaque+field->num_offset); } if (field->flags & VMS_POINTER) { base_addr = *(void **)base_addr + field->start; } for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); } else { ret = field->info->get(f, addr, size); } if (ret < 0) { trace_vmstate_load_field_error(field->name, ret); return ret; } } } field++; } ret = vmstate_subsection_load(f, vmsd, opaque); if (ret != 0) { return ret; } if (vmsd->post_load) { return vmsd->post_load(opaque, version_id); } return 0; }
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id) { VMStateField *field = vmsd->fields; int ret = 0; trace_vmstate_load_state(vmsd->name, version_id); if (version_id > vmsd->version_id) { error_report("%s: incoming version_id %d is too new " "for local version_id %d", vmsd->name, version_id, vmsd->version_id); trace_vmstate_load_state_end(vmsd->name, "too new", -EINVAL); return -EINVAL; } if (version_id < vmsd->minimum_version_id) { if (vmsd->load_state_old && version_id >= vmsd->minimum_version_id_old) { ret = vmsd->load_state_old(f, opaque, version_id); trace_vmstate_load_state_end(vmsd->name, "old path", ret); return ret; } error_report("%s: incoming version_id %d is too old " "for local minimum version_id %d", vmsd->name, version_id, vmsd->minimum_version_id); trace_vmstate_load_state_end(vmsd->name, "too old", -EINVAL); return -EINVAL; } if (vmsd->pre_load) { int ret = vmsd->pre_load(opaque); if (ret) { return ret; } } while (field->name) { trace_vmstate_load_state_field(vmsd->name, field->name); if ((field->field_exists && field->field_exists(opaque, version_id)) || (!field->field_exists && field->version_id <= version_id)) { void *base_addr = vmstate_base_addr(opaque, field, true); int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); } else { ret = field->info->get(f, addr, size, field); } if (ret >= 0) { ret = qemu_file_get_error(f); } if (ret < 0) { qemu_file_set_error(f, ret); error_report("Failed to load %s:%s", vmsd->name, field->name); trace_vmstate_load_field_error(field->name, ret); return ret; } } } else if (field->flags & VMS_MUST_EXIST) { error_report("Input validation failed: %s/%s", vmsd->name, field->name); return -1; } field++; } ret = vmstate_subsection_load(f, vmsd, opaque); if (ret != 0) { return ret; } if (vmsd->post_load) { ret = vmsd->post_load(opaque, version_id); } trace_vmstate_load_state_end(vmsd->name, "end", ret); return ret; }
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, QJSON *vmdesc) { VMStateField *field = vmsd->fields; trace_vmstate_save_state_top(vmsd->name); if (vmsd->pre_save) { vmsd->pre_save(opaque); } if (vmdesc) { json_prop_str(vmdesc, "vmsd_name", vmsd->name); json_prop_int(vmdesc, "version", vmsd->version_id); json_start_array(vmdesc, "fields"); } while (field->name) { if (!field->field_exists || field->field_exists(opaque, vmsd->version_id)) { void *base_addr = vmstate_base_addr(opaque, field, false); int i, n_elems = vmstate_n_elems(opaque, field); int size = vmstate_size(opaque, field); int64_t old_offset, written_bytes; QJSON *vmdesc_loop = vmdesc; trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems); for (i = 0; i < n_elems; i++) { void *addr = base_addr + size * i; vmsd_desc_field_start(vmsd, vmdesc_loop, field, i, n_elems); old_offset = qemu_ftell_fast(f); if (field->flags & VMS_ARRAY_OF_POINTER) { addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); } else { field->info->put(f, addr, size, field, vmdesc_loop); } written_bytes = qemu_ftell_fast(f) - old_offset; vmsd_desc_field_end(vmsd, vmdesc_loop, field, written_bytes, i); /* Compressed arrays only care about the first element */ if (vmdesc_loop && vmsd_can_compress(field)) { vmdesc_loop = NULL; } } } else { if (field->flags & VMS_MUST_EXIST) { error_report("Output state validation failed: %s/%s", vmsd->name, field->name); assert(!(field->flags & VMS_MUST_EXIST)); } } field++; } if (vmdesc) { json_end_array(vmdesc); } vmstate_subsection_save(f, vmsd, opaque, vmdesc); }