From: Fabiano Rosas <farosas@linux.ibm.com>
To: qemu-devel@nongnu.org
Cc: danielhb413@gmail.com, qemu-ppc@nongnu.org, clg@kaod.org,
david@gibson.dropbear.id.au
Subject: [RFC v2 07/12] target/ppc: Introduce PPCInterrupt
Date: Mon, 20 Dec 2021 15:18:58 -0300 [thread overview]
Message-ID: <20211220181903.3456898-8-farosas@linux.ibm.com> (raw)
In-Reply-To: <20211220181903.3456898-1-farosas@linux.ibm.com>
Now that each interrupt has its own routine, we can have an array of
interrupts and drop the big switch in powerpc_excp(). That will allow
us to later split the interrupt list between the various powerpc
implementations (book3s, booke, 32bit, kvm, etc).
No functional change.
Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com>
---
target/ppc/excp_helper.c | 172 +++----------------------------
target/ppc/interrupts.c | 212 +++++++++++++++++++++++++++++++++++++++
target/ppc/ppc_intr.h | 9 ++
3 files changed, 236 insertions(+), 157 deletions(-)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index bc20499b6c..4f8a6c4ec8 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -31,7 +31,6 @@
#ifdef CONFIG_TCG
#include "exec/helper-proto.h"
-#include "exec/cpu_ldst.h"
#endif
/*****************************************************************************/
@@ -274,11 +273,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp)
CPUPPCState *env = &cpu->env;
int excp_model = env->excp_model;
PPCIntrArgs regs;
+ PPCInterrupt *intr;
bool ignore = false;
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
" => %08x (%02x)\n", env->nip, excp, env->error_code);
+ if (excp == POWERPC_EXCP_NONE) {
+ /* Should never happen */
+ return;
+ }
+
/* new srr1 value excluding must-be-zero bits */
if (excp_model == POWERPC_EXCP_BOOKE) {
regs.msr = env->msr;
@@ -336,165 +341,18 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp)
regs.new_nip |= env->excp_prefix;
- switch (excp) {
- case POWERPC_EXCP_NONE:
- /* Should never happen */
- return;
-
- case POWERPC_EXCP_CRITICAL: /* Critical input */
- ppc_intr_critical(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_MCHECK: /* Machine check exception */
- ppc_intr_machine_check(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_DSI: /* Data storage exception */
- ppc_intr_data_storage(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_ISI: /* Instruction storage exception */
- ppc_intr_insn_storage(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_EXTERNAL: /* External input */
- ppc_intr_external(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_ALIGN: /* Alignment exception */
- ppc_intr_alignment(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_PROGRAM: /* Program exception */
- ppc_intr_program(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SYSCALL: /* System call exception */
- ppc_intr_system_call(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
- ppc_intr_system_call_vectored(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- case POWERPC_EXCP_DECR: /* Decrementer exception */
- break;
- case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
- ppc_intr_fit(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
- ppc_intr_watchdog(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_DTLB: /* Data TLB error */
- case POWERPC_EXCP_ITLB: /* Instruction TLB error */
- break;
- case POWERPC_EXCP_DEBUG: /* Debug interrupt */
- ppc_intr_debug(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */
- ppc_intr_spe_unavailable(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
- ppc_intr_embedded_fp_data(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
- ppc_intr_embedded_fp_round(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
- ppc_intr_embedded_perf_monitor(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
- break;
- case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
- ppc_intr_embedded_doorbell_crit(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_RESET: /* System reset exception */
- ppc_intr_system_reset(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_DSEG: /* Data segment exception */
- case POWERPC_EXCP_ISEG: /* Instruction segment exception */
- case POWERPC_EXCP_TRACE: /* Trace exception */
- break;
- case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
- ppc_intr_hv_insn_storage(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
- ppc_intr_hv_decrementer(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
- ppc_intr_hv_data_storage(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
- ppc_intr_hv_data_segment(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
- ppc_intr_hv_insn_segment(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
- ppc_intr_hv_doorbell(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HV_EMU:
- ppc_intr_hv_emulation(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
- ppc_intr_hv_virtualization(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
- case POWERPC_EXCP_FU: /* Facility unavailable exception */
- ppc_intr_facility_unavail(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
- ppc_intr_hv_facility_unavail(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
- ppc_intr_programmable_timer(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_IO: /* IO error exception */
- ppc_intr_io_error(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_RUNM: /* Run mode exception */
- ppc_intr_run_mode(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_EMUL: /* Emulation trap exception */
- ppc_intr_emulation(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
- case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
- case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
- ppc_intr_tlb_miss(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_FPA: /* Floating-point assist exception */
- ppc_intr_fpa(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_DABR: /* Data address breakpoint */
- ppc_intr_dabr(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
- ppc_intr_iabr(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SMI: /* System management interrupt */
- ppc_intr_smi(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_THERM: /* Thermal interrupt */
- ppc_intr_therm(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
- ppc_intr_perfm(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_VPUA: /* Vector assist exception */
- ppc_intr_vpua(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_SOFTP: /* Soft patch exception */
- ppc_intr_softp(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_MAINT: /* Maintenance exception */
- ppc_intr_maint(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
- ppc_intr_mextbr(cpu, ®s, &ignore);
- break;
- case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
- ppc_intr_nmextbr(cpu, ®s, &ignore);
- break;
- default:
+ intr = &interrupts[excp];
+ if (!intr->name) {
cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
- break;
}
+ if (!intr->fn) {
+ cpu_abort(cs, "%s exception is not implemented yet !\n", intr->name);
+ }
+
+ /* Setup interrupt-specific registers before dispatching */
+ intr->fn(cpu, ®s, &ignore);
+
if (ignore) {
/* No further setup is needed for this interrupt */
return;
diff --git a/target/ppc/interrupts.c b/target/ppc/interrupts.c
index 0168ce03a7..2dd3815167 100644
--- a/target/ppc/interrupts.c
+++ b/target/ppc/interrupts.c
@@ -17,6 +17,10 @@
/* #define DEBUG_SOFTWARE_TLB */
+void ppc_intr_noop(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore)
+{
+}
+
void ppc_intr_critical(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore)
{
CPUPPCState *env = &cpu->env;
@@ -643,3 +647,211 @@ void ppc_intr_nmextbr(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore)
cpu_abort(CPU(cpu), "Non maskable external exception "
"is not implemented yet !\n");
}
+
+PPCInterrupt interrupts[POWERPC_EXCP_NB] = {
+ [POWERPC_EXCP_ALIGN] = {
+ "Alignment", ppc_intr_alignment
+ },
+
+ [POWERPC_EXCP_CRITICAL] = {
+ "Critical input", ppc_intr_critical
+ },
+
+ [POWERPC_EXCP_DABR] = {
+ "Data address breakpoint", ppc_intr_dabr
+ },
+
+ [POWERPC_EXCP_DEBUG] = {
+ "Debug", ppc_intr_debug
+ },
+
+ [POWERPC_EXCP_DLTLB] = {
+ "Data load TLB error", ppc_intr_tlb_miss
+ },
+
+ [POWERPC_EXCP_DOORCI] = {
+ "Embedded doorbell critical", ppc_intr_embedded_doorbell_crit
+ },
+
+ [POWERPC_EXCP_DSI] = {
+ "Data storage", ppc_intr_data_storage
+ },
+
+ [POWERPC_EXCP_DSTLB] = {
+ "Data store TLB error", ppc_intr_tlb_miss
+ },
+
+ [POWERPC_EXCP_EFPDI] = {
+ "Embedded floating-point data", ppc_intr_embedded_fp_data
+ },
+
+ [POWERPC_EXCP_EFPRI] = {
+ "Embedded floating-point round", ppc_intr_embedded_fp_round
+ },
+
+ [POWERPC_EXCP_EMUL] = {
+ "Emulation trap", ppc_intr_emulation
+ },
+
+ [POWERPC_EXCP_EPERFM] = {
+ "Embedded perf. monitor", ppc_intr_embedded_perf_monitor
+ },
+
+ [POWERPC_EXCP_EXTERNAL] = {
+ "External", ppc_intr_external
+ },
+
+ [POWERPC_EXCP_FIT] = {
+ "Fixed-interval timer", ppc_intr_fit
+ },
+
+ [POWERPC_EXCP_FPA] = {
+ "Floating-point assist", ppc_intr_fpa
+ },
+
+ [POWERPC_EXCP_FU] = {
+ "Facility unavailable", ppc_intr_facility_unavail
+ },
+
+ [POWERPC_EXCP_HDECR] = {
+ "Hypervisor decrementer", ppc_intr_hv_decrementer
+ },
+
+ [POWERPC_EXCP_HDSEG] = {
+ "Hypervisor data segment", ppc_intr_hv_data_segment
+ },
+
+ [POWERPC_EXCP_HDSI] = {
+ "Hypervisor data storage", ppc_intr_hv_data_storage
+ },
+
+ [POWERPC_EXCP_HISEG] = {
+ "Hypervisor insn segment", ppc_intr_hv_insn_segment
+ },
+
+ [POWERPC_EXCP_HISI] = {
+ "Hypervisor instruction storage", ppc_intr_hv_insn_storage
+ },
+
+ [POWERPC_EXCP_HVIRT] = {
+ "Hypervisor virtualization", ppc_intr_hv_virtualization
+ },
+
+ [POWERPC_EXCP_HV_EMU] = {
+ "Hypervisor emulation assist", ppc_intr_hv_emulation
+ },
+
+ [POWERPC_EXCP_HV_FU] = {
+ "Hypervisor facility unavailable" , ppc_intr_hv_facility_unavail
+ },
+
+ [POWERPC_EXCP_IABR] = {
+ "Insn address breakpoint", ppc_intr_iabr
+ },
+
+ [POWERPC_EXCP_IFTLB] = {
+ "Insn fetch TLB error", ppc_intr_tlb_miss
+ },
+
+ [POWERPC_EXCP_IO] = {
+ "IO error", ppc_intr_io_error
+ },
+
+ [POWERPC_EXCP_ISI] = {
+ "Instruction storage", ppc_intr_insn_storage
+ },
+
+ [POWERPC_EXCP_MAINT] = {
+ "Maintenance", ppc_intr_maint
+ },
+
+ [POWERPC_EXCP_MCHECK] = {
+ "Machine check", ppc_intr_machine_check
+ },
+
+ [POWERPC_EXCP_MEXTBR] = {
+ "Maskable external", ppc_intr_mextbr
+ },
+
+ [POWERPC_EXCP_NMEXTBR] = {
+ "Non-maskable external", ppc_intr_nmextbr
+ },
+
+ [POWERPC_EXCP_PERFM] = {
+ "Performance counter", ppc_intr_perfm
+ },
+
+ [POWERPC_EXCP_PIT] = {
+ "Programmable interval timer", ppc_intr_programmable_timer
+ },
+
+ [POWERPC_EXCP_PROGRAM] = {
+ "Program", ppc_intr_program
+ },
+
+ [POWERPC_EXCP_RESET] = {
+ "System reset", ppc_intr_system_reset
+ },
+
+ [POWERPC_EXCP_RUNM] = {
+ "Run mode", ppc_intr_run_mode
+ },
+
+ [POWERPC_EXCP_SDOOR_HV] = {
+ "Hypervisor doorbell", ppc_intr_hv_doorbell
+ },
+
+ [POWERPC_EXCP_SMI] = {
+ "System management", ppc_intr_smi
+ },
+
+ [POWERPC_EXCP_SOFTP] = {
+ "Soft patch", ppc_intr_softp
+ },
+
+ [POWERPC_EXCP_SPEU] = {
+ "SPE/embedded FP unavailable/VPU", ppc_intr_spe_unavailable
+ },
+
+ [POWERPC_EXCP_SYSCALL] = {
+ "System call", ppc_intr_system_call
+ },
+
+ [POWERPC_EXCP_SYSCALL_VECTORED] = {
+ "System call vectored", ppc_intr_system_call_vectored
+ },
+
+ [POWERPC_EXCP_THERM] = {
+ "Thermal management", ppc_intr_therm
+ },
+
+ [POWERPC_EXCP_VPUA] = {
+ "Vector assist", ppc_intr_vpua
+ },
+
+ [POWERPC_EXCP_VPU] = {
+ "Vector unavailable", ppc_intr_facility_unavail
+ },
+
+ [POWERPC_EXCP_VSXU] = {
+ "VSX unavailable", ppc_intr_facility_unavail
+ },
+
+ [POWERPC_EXCP_WDT] = {
+ "Watchdog timer", ppc_intr_watchdog
+ },
+
+ [POWERPC_EXCP_APU] = { "Aux. processor unavailable", ppc_intr_noop },
+ [POWERPC_EXCP_DECR] = { "Decrementer", ppc_intr_noop },
+ [POWERPC_EXCP_DOORI] = { "Embedded doorbell", ppc_intr_noop },
+ [POWERPC_EXCP_DSEG] = { "Data segment", ppc_intr_noop },
+ [POWERPC_EXCP_DTLB] = { "Data TLB error", ppc_intr_noop },
+ [POWERPC_EXCP_FPU] = { "Floating-point unavailable", ppc_intr_noop },
+ [POWERPC_EXCP_ISEG] = { "Instruction segment", ppc_intr_noop },
+ [POWERPC_EXCP_ITLB] = { "Instruction TLB error", ppc_intr_noop },
+ [POWERPC_EXCP_TRACE] = { "Trace", ppc_intr_noop },
+
+/* Not implemented */
+ [POWERPC_EXCP_HV_MAINT] = { "Hypervisor maintenance" },
+ [POWERPC_EXCP_SDOOR] = { "Server doorbell" },
+};
diff --git a/target/ppc/ppc_intr.h b/target/ppc/ppc_intr.h
index 25c11710f9..82372ca227 100644
--- a/target/ppc/ppc_intr.h
+++ b/target/ppc/ppc_intr.h
@@ -2,6 +2,8 @@
#define PPC_INTR_H
typedef struct PPCIntrArgs PPCIntrArgs;
+typedef struct PPCInterrupt PPCInterrupt;
+typedef void (*ppc_intr_fn_t)(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
struct PPCIntrArgs {
target_ulong nip;
@@ -12,6 +14,11 @@ struct PPCIntrArgs {
int sprn_srr1;
};
+struct PPCInterrupt {
+ const char *name;
+ ppc_intr_fn_t fn;
+};
+
void ppc_intr_alignment(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
void ppc_intr_critical(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
void ppc_intr_dabr(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
@@ -58,4 +65,6 @@ void ppc_intr_tlb_miss(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
void ppc_intr_vpua(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
void ppc_intr_watchdog(PowerPCCPU *cpu, PPCIntrArgs *regs, bool *ignore);
+extern PPCInterrupt interrupts[POWERPC_EXCP_NB];
+
#endif /* PPC_INTR_H */
--
2.33.1
next prev parent reply other threads:[~2021-12-20 18:57 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-20 18:18 [RFC v2 00/12] target/ppc: powerpc_excp improvements Fabiano Rosas
2021-12-20 18:18 ` [RFC v2 01/12] target/ppc: powerpc_excp: Set alternate SRRs directly Fabiano Rosas
2021-12-21 23:32 ` Richard Henderson
2021-12-22 6:46 ` Cédric Le Goater
2021-12-23 4:39 ` David Gibson
2021-12-20 18:18 ` [RFC v2 02/12] target/ppc: powerpc_excp: Set vector earlier Fabiano Rosas
2021-12-22 6:48 ` Cédric Le Goater
2021-12-25 10:45 ` Nicholas Piggin
2021-12-24 0:11 ` Richard Henderson
2021-12-24 11:14 ` Fabiano Rosas
2021-12-20 18:18 ` [RFC v2 03/12] target/ppc: powerpc_excp: Move system call vectored code together Fabiano Rosas
2021-12-22 6:48 ` Cédric Le Goater
2021-12-24 0:12 ` Richard Henderson
2021-12-20 18:18 ` [RFC v2 04/12] target/ppc: powerpc_excp: Stop passing excp_model around Fabiano Rosas
2021-12-22 6:48 ` Cédric Le Goater
2021-12-24 0:13 ` Richard Henderson
2021-12-25 6:33 ` David Gibson
2021-12-20 18:18 ` [RFC v2 05/12] target/ppc: powerpc_excp: Standardize arguments to interrupt code Fabiano Rosas
2021-12-25 6:35 ` David Gibson
2021-12-27 17:13 ` Fabiano Rosas
2021-12-20 18:18 ` [RFC v2 06/12] target/ppc: Extract interrupt routines into a new file Fabiano Rosas
2021-12-20 18:18 ` Fabiano Rosas [this message]
2021-12-20 18:18 ` [RFC v2 08/12] target/ppc: Remove unimplemented interrupt code Fabiano Rosas
2021-12-20 18:19 ` [RFC v2 09/12] target/ppc: Use common code for Hypervisor interrupts Fabiano Rosas
2021-12-20 18:19 ` [RFC v2 10/12] target/ppc: Split powerpc_excp into book3s, booke and 32 bit Fabiano Rosas
2021-12-20 18:19 ` [RFC v2 11/12] target/ppc: Create new files for book3s, booke and ppc32 exception code Fabiano Rosas
2021-12-20 18:19 ` [RFC v2 12/12] target/ppc: Do not enable all interrupts when running KVM Fabiano Rosas
2021-12-26 16:48 ` [RFC v2 00/12] target/ppc: powerpc_excp improvements Cédric Le Goater
2021-12-29 14:18 ` Fabiano Rosas
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=20211220181903.3456898-8-farosas@linux.ibm.com \
--to=farosas@linux.ibm.com \
--cc=clg@kaod.org \
--cc=danielhb413@gmail.com \
--cc=david@gibson.dropbear.id.au \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.