diff --git a/target/arm/machine.c b/target/arm/machine.c index 4d9158e697..476dad00ee 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -1057,6 +1057,35 @@ static gchar *print_register_name(uint64_t kvm_regidx) } } +/* + * Handle the situation where @kvmidx is on destination but not + * in the incoming stream. This never fails the migration. + */ +static void handle_cpreg_missing_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) +{ + g_autofree gchar *name = print_register_name(kvmidx); + + warn_report("%s: %s " + "expected by the destination but not in the incoming stream: " + "skip it", __func__, name); +} + +/* + * Handle the situation where @kvmidx is in the incoming stream + * but not on destination. This currently fails the migration but + * we plan to accomodate some exceptions, hence the boolean returned value. + */ +static bool handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) +{ + g_autofree gchar *name = print_register_name(kvmidx); + bool fail = true; + + error_report("%s: %s in the incoming stream but unknown on the " + "destination: fail migration", __func__, name); + + return fail; +} + static int cpu_post_load(void *opaque, int version_id) { ARMCPU *cpu = opaque; @@ -1096,21 +1125,12 @@ static int cpu_post_load(void *opaque, int version_id) for (i = 0, v = 0; i < cpu->cpreg_array_len && v < cpu->cpreg_vmstate_array_len;) { if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) { - g_autofree gchar *name = print_register_name(cpu->cpreg_indexes[i]); - - warn_report("%s: %s " - "expected by the destination but not in the incoming stream: " - "skip it", __func__, name); - i++; + handle_cpreg_missing_in_incoming_stream(cpu, cpu->cpreg_indexes[i++]); continue; } if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) { - g_autofree gchar *name = print_register_name(cpu->cpreg_vmstate_indexes[v]); - - error_report("%s: %s in the incoming stream but unknown on the destination: " - "fail migration", __func__, name); - v++; - fail = true; + fail = handle_cpreg_only_in_incoming_stream(cpu, + cpu->cpreg_vmstate_indexes[v++]); continue; } /* matching register, copy the value over */ @@ -1118,6 +1138,23 @@ static int cpu_post_load(void *opaque, int version_id) i++; v++; } + + /* + * if we have reached the end of the incoming array but there are + * still regs in cpreg, continue parsing the regs which are missing + * in the input stream + */ + for ( ; i < cpu->cpreg_array_len; i++) { + handle_cpreg_missing_in_incoming_stream(cpu, cpu->cpreg_indexes[i]); + } + /* + * if we have reached the end of the cpreg array but there are + * still regs in the input stream, continue parsing the vmstate array + */ + for ( ; v < cpu->cpreg_vmstate_array_len; v++) { + fail = handle_cpreg_only_in_incoming_stream(cpu, + cpu->cpreg_vmstate_indexes[v]); + } if (fail) { return -1; }