If there is a mismatch between the cpreg indexes found on both ends, check whether a tolerance was registered for the given kvmidx. If any, silence warning/errors.
Create dedicated helper functions that print the name of the culprit reg and analyze whether a tolerance is set. According set the level of traces and analyze whether the migration must eventually fail. Signed-off-by: Eric Auger <[email protected]> --- target/arm/machine.c | 67 +++++++++++++++++++++++++++-------------- target/arm/trace-events | 2 ++ 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/target/arm/machine.c b/target/arm/machine.c index 9297a8f5b41..abc66448cef 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -1046,6 +1046,45 @@ 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); + + if (!arm_cpu_cpreg_has_mig_tolerance(cpu, kvmidx, + 0, 0, ToleranceNotOnBothEnds)) { + warn_report("%s: %s " + "expected by the destination but not in the incoming stream, " + "skip it", __func__, name); + } else { + trace_tolerate_cpreg_missing_in_incoming_stream(name); + } +} + +/* + * Handle the situation where @kvmidx is in the incoming + * stream but not on destination. This fails the migration if + * no cpreg mig tolerance is set for this @kvmidx + */ +static bool handle_cpreg_only_in_incoming_stream(ARMCPU *cpu, uint64_t kvmidx) +{ + g_autofree gchar *name = print_register_name(kvmidx); + bool fail = false; + + if (!arm_cpu_cpreg_has_mig_tolerance(cpu, kvmidx, + 0, 0, ToleranceNotOnBothEnds)) { + error_report("%s: %s in the incoming stream but unknown on the " + "destination, fail migration", __func__, name); + fail = true; + } else { + trace_tolerate_cpreg_only_in_incoming_stream(name); + } + return fail; +} + static int cpu_post_load(void *opaque, int version_id) { ARMCPU *cpu = opaque; @@ -1085,21 +1124,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 */ @@ -1113,22 +1143,15 @@ static int cpu_post_load(void *opaque, int version_id) * in the input stream */ for ( ; i < cpu->cpreg_array_len; 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); + 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++) { - 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); - fail = true; + fail = handle_cpreg_only_in_incoming_stream(cpu, + cpu->cpreg_vmstate_indexes[v]); } if (fail) { return -1; diff --git a/target/arm/trace-events b/target/arm/trace-events index 2de0406f784..dceb3c63f77 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -29,3 +29,5 @@ arm_psci_call(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint32_t cpuid # machine.c cpu_post_load(uint32_t cpreg_vmstate_array_len, uint32_t cpreg_array_len) "cpreg_vmstate_array_len=%d cpreg_array_len=%d" +tolerate_cpreg_missing_in_incoming_stream(char *name) "cpreg %s is missing in incoming stream but this is explicitly tolerated" +tolerate_cpreg_only_in_incoming_stream(char *name) "cpreg %s is in incoming stream but not on destination but this is explicitly tolerated" -- 2.53.0
