From: Glenn Miles <milesg@linux.ibm.com>
To: qemu-devel@nongnu.org
Cc: Glenn Miles <milesg@linux.ibm.com>,
qemu-ppc@nongnu.org, clg@redhat.com, npiggin@gmail.com,
harshpb@linux.ibm.com, thuth@redhat.com, rathc@linux.ibm.com,
richard.henderson@linaro.org
Subject: [PATCH v4 4/9] target/ppc: Add IBM PPE42 exception model
Date: Fri, 12 Sep 2025 11:47:32 -0500 [thread overview]
Message-ID: <20250912164808.371944-5-milesg@linux.ibm.com> (raw)
In-Reply-To: <20250912164808.371944-1-milesg@linux.ibm.com>
Add support for the IBM PPE42 exception model including
new exception vectors, exception priorities and setting
of PPE42 SPRs for determining the cause of an exception.
Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
---
target/ppc/cpu_init.c | 39 ++++++++-
target/ppc/excp_helper.c | 163 +++++++++++++++++++++++++++++++++++
target/ppc/tcg-excp_helper.c | 12 +++
3 files changed, 213 insertions(+), 1 deletion(-)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index b42673c6b5..097e3b3818 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -1720,6 +1720,30 @@ static void init_excp_4xx(CPUPPCState *env)
#endif
}
+static void init_excp_ppe42(CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+ /* Machine Check vector changed after version 0 */
+ if (((env->spr[SPR_PVR] & 0xf00000ul) >> 20) == 0) {
+ env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000;
+ } else {
+ env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000020;
+ }
+ env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000040;
+ env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000060;
+ env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000080;
+ env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x000000A0;
+ env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x000000C0;
+ env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x000000E0;
+ env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000100;
+ env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000120;
+ env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000140;
+ env->ivpr_mask = 0xFFFFFE00UL;
+ /* Hardware reset vector */
+ env->hreset_vector = 0x00000040UL;
+#endif
+}
+
static void init_excp_MPC5xx(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
@@ -2245,6 +2269,7 @@ static void init_proc_ppe42(CPUPPCState *env)
{
register_ppe42_sprs(env);
+ init_excp_ppe42(env);
env->dcache_line_size = 32;
env->icache_line_size = 32;
/* Allocate hardware IRQ controller */
@@ -2278,7 +2303,7 @@ static void ppe42_class_common_init(PowerPCCPUClass *pcc)
(1ull << MSR_IPE) |
R_MSR_SIBRCA_MASK;
pcc->mmu_model = POWERPC_MMU_REAL;
- pcc->excp_model = POWERPC_EXCP_40x;
+ pcc->excp_model = POWERPC_EXCP_PPE42;
pcc->bus_model = PPC_FLAGS_INPUT_PPE42;
pcc->bfd_mach = bfd_mach_ppc_403;
pcc->flags = POWERPC_FLAG_PPE42 | POWERPC_FLAG_BUS_CLK;
@@ -7855,6 +7880,18 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
* they can be read with "p $ivor0", "p $ivor1", etc.
*/
break;
+ case POWERPC_EXCP_PPE42:
+ qemu_fprintf(f, "SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx "\n",
+ env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
+
+ qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
+ " ISR " TARGET_FMT_lx " EDR " TARGET_FMT_lx "\n",
+ env->spr[SPR_PPE42_TCR], env->spr[SPR_PPE42_TSR],
+ env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
+
+ qemu_fprintf(f, " PIR " TARGET_FMT_lx " IVPR " TARGET_FMT_lx "\n",
+ env->spr[SPR_PPE42_PIR], env->spr[SPR_PPE42_IVPR]);
+ break;
case POWERPC_EXCP_40x:
qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx
" ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n",
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 1efdc4066e..d8bca19fff 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -949,6 +949,125 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
powerpc_set_excp_state(cpu, vector, new_msr);
}
+static void powerpc_excp_ppe42(PowerPCCPU *cpu, int excp)
+{
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr, new_msr, vector;
+ target_ulong mcs = PPE42_ISR_MCS_INSTRUCTION;
+ bool promote_unmaskable;
+
+ msr = env->msr;
+
+ /*
+ * New interrupt handler msr preserves SIBRC and ME unless explicitly
+ * overridden by the exception. All other MSR bits are zeroed out.
+ */
+ new_msr = env->msr & (((target_ulong)1 << MSR_ME) | R_MSR_SIBRC_MASK);
+
+ /* HV emu assistance interrupt only exists on server arch 2.05 or later */
+ if (excp == POWERPC_EXCP_HV_EMU) {
+ excp = POWERPC_EXCP_PROGRAM;
+ }
+
+ /*
+ * Unmaskable interrupts (Program, ISI, Alignment and DSI) are promoted to
+ * machine check if MSR_UIE is 0.
+ */
+ promote_unmaskable = !(msr & ((target_ulong)1 << MSR_UIE));
+
+
+ switch (excp) {
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
+ trace_ppc_excp_dsi(env->spr[SPR_PPE42_ISR], env->spr[SPR_PPE42_EDR]);
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = PPE42_ISR_MCS_DSI;
+ }
+ break;
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ trace_ppc_excp_isi(msr, env->nip);
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = PPE42_ISR_MCS_ISI;
+ }
+ break;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = PPE42_ISR_MCS_ALIGNMENT;
+ }
+ break;
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ if (promote_unmaskable) {
+ excp = POWERPC_EXCP_MCHECK;
+ mcs = PPE42_ISR_MCS_PROGRAM;
+ }
+ switch (env->error_code & ~0xF) {
+ case POWERPC_EXCP_INVAL:
+ trace_ppc_excp_inval(env->nip);
+ env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << PPE42_ISR_PTR);
+ break;
+ case POWERPC_EXCP_TRAP:
+ env->spr[SPR_PPE42_ISR] |= ((target_ulong)1 << PPE42_ISR_PTR);
+ break;
+ default:
+ /* Should never occur */
+ cpu_abort(env_cpu(env), "Invalid program exception %d. Aborting\n",
+ env->error_code);
+ break;
+ }
+#ifdef CONFIG_TCG
+ env->spr[SPR_PPE42_EDR] = ppc_ldl_code(env, env->nip);
+#endif
+ break;
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ break;
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ trace_ppc_excp_print("FIT");
+ break;
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ trace_ppc_excp_print("WDT");
+ break;
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ /* reset exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+ break;
+ default:
+ cpu_abort(env_cpu(env), "Invalid PPE42 exception %d. Aborting\n",
+ excp);
+ break;
+ }
+
+ env->spr[SPR_SRR0] = env->nip;
+ env->spr[SPR_SRR1] = msr;
+
+ vector = env->excp_vectors[excp];
+ if (vector == (target_ulong)-1ULL) {
+ cpu_abort(env_cpu(env),
+ "Raised an exception without defined vector %d\n", excp);
+ }
+ vector |= env->spr[SPR_PPE42_IVPR];
+
+ if (excp == POWERPC_EXCP_MCHECK) {
+ /* Also set the Machine Check Status (MCS) */
+ env->spr[SPR_PPE42_ISR] &= ~R_PPE42_ISR_MCS_MASK;
+ env->spr[SPR_PPE42_ISR] |= (mcs & R_PPE42_ISR_MCS_MASK);
+ env->spr[SPR_PPE42_ISR] &= ~((target_ulong)1 << PPE42_ISR_MFE);
+
+ /* Machine checks halt execution if MSR_ME is 0 */
+ powerpc_mcheck_checkstop(env);
+
+ /* machine check exceptions don't have ME set */
+ new_msr &= ~((target_ulong)1 << MSR_ME);
+ }
+
+ powerpc_set_excp_state(cpu, vector, new_msr);
+}
+
static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
{
CPUPPCState *env = &cpu->env;
@@ -1589,6 +1708,9 @@ void powerpc_excp(PowerPCCPU *cpu, int excp)
case POWERPC_EXCP_POWER11:
powerpc_excp_books(cpu, excp);
break;
+ case POWERPC_EXCP_PPE42:
+ powerpc_excp_ppe42(cpu, excp);
+ break;
default:
g_assert_not_reached();
}
@@ -1945,6 +2067,43 @@ static int p9_next_unmasked_interrupt(CPUPPCState *env,
}
#endif /* TARGET_PPC64 */
+static int ppe42_next_unmasked_interrupt(CPUPPCState *env)
+{
+ bool async_deliver;
+
+ /* External reset */
+ if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
+ return PPC_INTERRUPT_RESET;
+ }
+ /* Machine check exception */
+ if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
+ return PPC_INTERRUPT_MCK;
+ }
+
+ async_deliver = FIELD_EX64(env->msr, MSR, EE);
+
+ if (async_deliver != 0) {
+ /* Watchdog timer */
+ if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
+ return PPC_INTERRUPT_WDT;
+ }
+ /* External Interrupt */
+ if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
+ return PPC_INTERRUPT_EXT;
+ }
+ /* Fixed interval timer */
+ if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
+ return PPC_INTERRUPT_FIT;
+ }
+ /* Decrementer exception */
+ if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
+ return PPC_INTERRUPT_DECR;
+ }
+ }
+
+ return 0;
+}
+
static int ppc_next_unmasked_interrupt(CPUPPCState *env)
{
uint32_t pending_interrupts = env->pending_interrupts;
@@ -1970,6 +2129,10 @@ static int ppc_next_unmasked_interrupt(CPUPPCState *env)
}
#endif
+ if (env->excp_model == POWERPC_EXCP_PPE42) {
+ return ppe42_next_unmasked_interrupt(env);
+ }
+
/* External reset */
if (pending_interrupts & PPC_INTERRUPT_RESET) {
return PPC_INTERRUPT_RESET;
diff --git a/target/ppc/tcg-excp_helper.c b/target/ppc/tcg-excp_helper.c
index f835be5156..edecfb8572 100644
--- a/target/ppc/tcg-excp_helper.c
+++ b/target/ppc/tcg-excp_helper.c
@@ -229,6 +229,18 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
case POWERPC_MMU_BOOKE206:
env->spr[SPR_BOOKE_DEAR] = vaddr;
break;
+ case POWERPC_MMU_REAL:
+ if (env->flags & POWERPC_FLAG_PPE42) {
+ env->spr[SPR_PPE42_EDR] = vaddr;
+ if (access_type == MMU_DATA_STORE) {
+ env->spr[SPR_PPE42_ISR] |= PPE42_ISR_ST;
+ } else {
+ env->spr[SPR_PPE42_ISR] &= ~PPE42_ISR_ST;
+ }
+ } else {
+ env->spr[SPR_DAR] = vaddr;
+ }
+ break;
default:
env->spr[SPR_DAR] = vaddr;
break;
--
2.43.0
next prev parent reply other threads:[~2025-09-12 16:51 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-12 16:47 [PATCH v4 0/9] Add IBM PPE42 CPU support Glenn Miles
2025-09-12 16:47 ` [PATCH v4 1/9] target/ppc: IBM PPE42 general regs and flags Glenn Miles
2025-09-12 16:47 ` [PATCH v4 2/9] target/ppc: Add IBM PPE42 family of processors Glenn Miles
2025-09-12 16:47 ` [PATCH v4 3/9] target/ppc: IBM PPE42 exception flags and regs Glenn Miles
2025-09-12 16:47 ` Glenn Miles [this message]
2025-09-12 16:47 ` [PATCH v4 5/9] target/ppc: Support for IBM PPE42 MMU Glenn Miles
2025-09-12 16:47 ` [PATCH v4 6/9] target/ppc: Add IBM PPE42 special instructions Glenn Miles
2025-09-16 9:12 ` Cédric Le Goater
2025-09-17 4:57 ` Harsh Prateek Bora
2025-09-17 6:20 ` Thomas Huth
2025-09-17 14:38 ` Miles Glenn
2025-09-17 16:07 ` BALATON Zoltan
2025-09-17 16:43 ` Thomas Huth
2025-09-17 16:52 ` Miles Glenn
2025-09-17 16:35 ` Cédric Le Goater
2025-09-12 16:47 ` [PATCH v4 7/9] hw/ppc: Support for an IBM PPE42 CPU decrementer Glenn Miles
2025-09-12 16:47 ` [PATCH v4 8/9] hw/ppc: Add a test machine for the IBM PPE42 CPU Glenn Miles
2025-09-12 16:47 ` [PATCH v4 9/9] tests/functional: Add test for IBM PPE42 instructions Glenn Miles
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250912164808.371944-5-milesg@linux.ibm.com \
--to=milesg@linux.ibm.com \
--cc=clg@redhat.com \
--cc=harshpb@linux.ibm.com \
--cc=npiggin@gmail.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=rathc@linux.ibm.com \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).