diff mbox series

[2/4] target/ppc: Add POWER9/10 invalid-real machine check codes

Message ID 20230623081953.290875-3-npiggin@gmail.com
State New
Headers show
Series target/ppc: Catch invalid real address accesses | expand

Commit Message

Nicholas Piggin June 23, 2023, 8:19 a.m. UTC
Implement the correct register settings for  the invalid-real access
machine check for POWER9/10 processors.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 target/ppc/excp_helper.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
diff mbox series

Patch

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. */