Implement the correct register settings for the invalid-real access machine check for POWER9/10 processors.
Signed-off-by: Nicholas Piggin <npig...@gmail.com> --- target/ppc/excp_helper.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index c9bfa3a827..1c26828d8b 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -3139,8 +3139,6 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, case POWERPC_EXCP_970: case POWERPC_EXCP_POWER7: case POWERPC_EXCP_POWER8: - case POWERPC_EXCP_POWER9: - case POWERPC_EXCP_POWER10: /* * TODO: This does not give the correct machine check code but * it will report a NIP and DAR. @@ -3149,6 +3147,30 @@ void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, env->spr[SPR_DAR] = vaddr; } break; + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: + /* + * Machine check codes can be found in User Manual or Linux or + * skiboot source. + */ + if (access_type == MMU_DATA_LOAD) { + env->spr[SPR_DAR] = vaddr; + env->spr[SPR_DSISR] = PPC_BIT(57); + env->error_code = PPC_BIT(42); + + } else if (access_type == MMU_DATA_STORE) { + /* + * MCE for stores in POWER is asynchronous so hardware does + * not set DAR, but QEMU can do better. + */ + env->spr[SPR_DAR] = vaddr; + env->error_code = PPC_BIT(36) | PPC_BIT(43) | PPC_BIT(45); + env->error_code |= PPC_BIT(42); + } else { /* Fetch */ + + env->error_code = PPC_BIT(36) | PPC_BIT(44) | PPC_BIT(45); + } + break; #endif default: /* TODO: Check behaviour for other CPUs, for now do nothing. */ -- 2.40.1