From: Miles Glenn <milesg@linux.ibm.com>
To: "Cédric Le Goater" <clg@redhat.com>, qemu-devel@nongnu.org
Cc: qemu-ppc@nongnu.org, npiggin@gmail.com, harshpb@linux.ibm.com,
thuth@redhat.com, rathc@linux.ibm.com,
richard.henderson@linaro.org
Subject: Re: [PATCH v2 1/4] target/ppc: Add IBM PPE42 family of processors
Date: Tue, 02 Sep 2025 11:59:04 -0500 [thread overview]
Message-ID: <6707e44ef91de579a0aa3bd265f4c4feb05c0121.camel@linux.ibm.com> (raw)
In-Reply-To: <a388fe15-f32f-45a6-accd-a85fe123a3e4@redhat.com>
On Mon, 2025-09-01 at 09:29 +0200, Cédric Le Goater wrote:
> On 8/26/25 22:17, Glenn Miles wrote:
> > Adds the IBM PPE42 family of 32-bit processors supporting
> > the PPE42, PPE42X and PPE42XM processor versions. These
> > processors are used as embedded processors in the IBM
> > Power9, Power10 and Power12 processors for various
> > tasks. It is basically a stripped down version of the
> > IBM PowerPC 405 processor, with some added instructions
> > for handling 64-bit loads and stores.
> >
> > For more information on the PPE 42 processor please visit:
> >
> > https://wiki.raptorcs.com/w/images/a/a3/PPE_42X_Core_Users_Manual.pdf
> >
> > Supports PPE42 SPR's (Including the MSR) and Exceptions.
> >
> > Does not yet support new PPE42 instructions and does not
> > prevent access to some invalid instructions and registers
> > (currently allows for access to invalid GPR's and CR fields).
> >
> > Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
>
> Could you please split these changes : CPU, exceptions, MMU ?
> Introduce the flags first in case they are needed.
>
> Thanks,
>
> C.
>
>
Will do!
Thanks,
Glenn
>
>
>
> > ---
> >
> > Changes since previous version
> > - Added "32-bit" wording to commit message
> > - Added 'unlikely' specifier to hreg_compute_hflags_value conditional
> > - Added PPE42_ prefix to ISR definitions
> > - Moved ISR_MCS* definitions from excp_helper.c to cpu.h
> > - Moved common cpu_init code to a common function
> > - Added 'likely' specifier to gen_mtmsr conditional
> > - Formatting changes to fit comments within 80 character limit
> >
> > target/ppc/cpu-models.c | 7 +
> > target/ppc/cpu-models.h | 4 +
> > target/ppc/cpu.h | 76 ++++++++++-
> > target/ppc/cpu_init.c | 241 +++++++++++++++++++++++++++++------
> > target/ppc/excp_helper.c | 163 +++++++++++++++++++++++
> > target/ppc/helper_regs.c | 28 +++-
> > target/ppc/tcg-excp_helper.c | 12 ++
> > target/ppc/translate.c | 6 +-
> > 8 files changed, 492 insertions(+), 45 deletions(-)
> >
> > diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
> > index ea86ea202a..09f73e23a8 100644
> > --- a/target/ppc/cpu-models.c
> > +++ b/target/ppc/cpu-models.c
> > @@ -116,6 +116,13 @@
> > NULL)
> > POWERPC_DEF("x2vp20", CPU_POWERPC_X2VP20, 405,
> > NULL)
> > + /* PPE42 Embedded Controllers */
> > + POWERPC_DEF("PPE42", CPU_POWERPC_PPE42, ppe42,
> > + "Generic PPE 42")
> > + POWERPC_DEF("PPE42X", CPU_POWERPC_PPE42X, ppe42x,
> > + "Generic PPE 42X")
> > + POWERPC_DEF("PPE42XM", CPU_POWERPC_PPE42XM, ppe42xm,
> > + "Generic PPE 42XM")
> > /* PowerPC 440 family */
> > #if defined(TODO_USER_ONLY)
> > POWERPC_DEF("440", CPU_POWERPC_440, 440GP,
> > diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
> > index 72ad31ba50..c6cd27f390 100644
> > --- a/target/ppc/cpu-models.h
> > +++ b/target/ppc/cpu-models.h
> > @@ -69,6 +69,10 @@ enum {
> > /* Xilinx cores */
> > CPU_POWERPC_X2VP4 = 0x20010820,
> > CPU_POWERPC_X2VP20 = 0x20010860,
> > + /* IBM PPE42 Family */
> > + CPU_POWERPC_PPE42 = 0x42000000,
> > + CPU_POWERPC_PPE42X = 0x42100000,
> > + CPU_POWERPC_PPE42XM = 0x42200000,
> > /* PowerPC 440 family */
> > /* Generic PowerPC 440 */
> > #define CPU_POWERPC_440 CPU_POWERPC_440GXf
> > diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> > index 6b90543811..c68dd4f141 100644
> > --- a/target/ppc/cpu.h
> > +++ b/target/ppc/cpu.h
> > @@ -220,6 +220,8 @@ typedef enum powerpc_excp_t {
> > POWERPC_EXCP_POWER10,
> > /* POWER11 exception model */
> > POWERPC_EXCP_POWER11,
> > + /* PPE42 exception model */
> > + POWERPC_EXCP_PPE42,
> > } powerpc_excp_t;
> >
> > /*****************************************************************************/
> > @@ -282,6 +284,8 @@ typedef enum powerpc_input_t {
> > PPC_FLAGS_INPUT_POWER9,
> > /* Freescale RCPU bus */
> > PPC_FLAGS_INPUT_RCPU,
> > + /* PPE42 bus */
> > + PPC_FLAGS_INPUT_PPE42,
> > } powerpc_input_t;
> >
> > #define PPC_INPUT(env) ((env)->bus_model)
> > @@ -433,39 +437,64 @@ typedef enum {
> > #define MSR_TM PPC_BIT_NR(31) /* Transactional Memory Available (Book3s) */
> > #define MSR_CM PPC_BIT_NR(32) /* Computation mode for BookE hflags */
> > #define MSR_ICM PPC_BIT_NR(33) /* Interrupt computation mode for BookE */
> > +#define MSR_SEM0 PPC_BIT_NR(33) /* SIB Error Mask Bit 0 (PPE42) */
> > +#define MSR_SEM1 PPC_BIT_NR(34) /* SIB Error Mask Bit 1 (PPE42) */
> > +#define MSR_SEM2 PPC_BIT_NR(35) /* SIB Error Mask Bit 2 (PPE42) */
> > #define MSR_GS PPC_BIT_NR(35) /* guest state for BookE */
> > +#define MSR_SEM3 PPC_BIT_NR(36) /* SIB Error Mask Bit 3 (PPE42) */
> > +#define MSR_SEM4 PPC_BIT_NR(37) /* SIB Error Mask Bit 4 (PPE42) */
> > #define MSR_UCLE PPC_BIT_NR(37) /* User-mode cache lock enable for BookE */
> > #define MSR_VR PPC_BIT_NR(38) /* altivec available x hflags */
> > #define MSR_SPE PPC_BIT_NR(38) /* SPE enable for BookE x hflags */
> > +#define MSR_SEM5 PPC_BIT_NR(38) /* SIB Error Mask Bit 5 (PPE42) */
> > +#define MSR_SEM6 PPC_BIT_NR(39) /* SIB Error Mask Bit 6 (PPE42) */
> > #define MSR_VSX PPC_BIT_NR(40) /* Vector Scalar Extension (>= 2.06)x hflags */
> > +#define MSR_IS0 PPC_BIT_NR(40) /* Instance Specific Bit 0 (PPE42) */
> > #define MSR_S PPC_BIT_NR(41) /* Secure state */
> > +#define MSR_SIBRC0 PPC_BIT_NR(41) /* Last SIB return code Bit 0 (PPE42) */
> > +#define MSR_SIBRC1 PPC_BIT_NR(42) /* Last SIB return code Bit 1 (PPE42) */
> > +#define MSR_SIBRC2 PPC_BIT_NR(43) /* Last SIB return code Bit 2 (PPE42) */
> > +#define MSR_LP PPC_BIT_NR(44) /* Low Priority (PPE42) */
> > #define MSR_KEY PPC_BIT_NR(44) /* key bit on 603e */
> > #define MSR_POW PPC_BIT_NR(45) /* Power management */
> > #define MSR_WE PPC_BIT_NR(45) /* Wait State Enable on 405 */
> > +#define MSR_IS1 PPC_BIT_NR(46) /* Instance Specific Bit 1 (PPE42) */
> > #define MSR_TGPR PPC_BIT_NR(46) /* TGPR usage on 602/603 x */
> > #define MSR_CE PPC_BIT_NR(46) /* Critical int. enable on embedded PPC x */
> > #define MSR_ILE PPC_BIT_NR(47) /* Interrupt little-endian mode */
> > +#define MSR_UIE PPC_BIT_NR(47) /* Unmaskable Interrupt Enable (PPE42) */
> > #define MSR_EE PPC_BIT_NR(48) /* External interrupt enable */
> > #define MSR_PR PPC_BIT_NR(49) /* Problem state hflags */
> > #define MSR_FP PPC_BIT_NR(50) /* Floating point available hflags */
> > #define MSR_ME PPC_BIT_NR(51) /* Machine check interrupt enable */
> > #define MSR_FE0 PPC_BIT_NR(52) /* Floating point exception mode 0 */
> > +#define MSR_IS2 PPC_BIT_NR(52) /* Instance Specific Bit 2 (PPE42) */
> > +#define MSR_IS3 PPC_BIT_NR(53) /* Instance Specific Bit 3 (PPE42) */
> > #define MSR_SE PPC_BIT_NR(53) /* Single-step trace enable x hflags */
> > #define MSR_DWE PPC_BIT_NR(53) /* Debug wait enable on 405 x */
> > #define MSR_UBLE PPC_BIT_NR(53) /* User BTB lock enable on e500 x */
> > #define MSR_BE PPC_BIT_NR(54) /* Branch trace enable x hflags */
> > #define MSR_DE PPC_BIT_NR(54) /* Debug int. enable on embedded PPC x */
> > #define MSR_FE1 PPC_BIT_NR(55) /* Floating point exception mode 1 */
> > +#define MSR_IPE PPC_BIT_NR(55) /* Imprecise Mode Enable (PPE42) */
> > #define MSR_AL PPC_BIT_NR(56) /* AL bit on POWER */
> > +#define MSR_SIBRCA0 PPC_BIT_NR(56) /* SIB Return Code Accumulator 0 (PPE42) */
> > +#define MSR_SIBRCA1 PPC_BIT_NR(57) /* SIB Return Code Accumulator 1 (PPE42) */
> > #define MSR_EP PPC_BIT_NR(57) /* Exception prefix on 601 */
> > #define MSR_IR PPC_BIT_NR(58) /* Instruction relocate */
> > #define MSR_IS PPC_BIT_NR(58) /* Instruction address space (BookE) */
> > +#define MSR_SIBRCA2 PPC_BIT_NR(58) /* SIB Return Code Accumulator 2 (PPE42) */
> > +#define MSR_SIBRCA3 PPC_BIT_NR(59) /* SIB Return Code Accumulator 3 (PPE42) */
> > #define MSR_DR PPC_BIT_NR(59) /* Data relocate */
> > #define MSR_DS PPC_BIT_NR(59) /* Data address space (BookE) */
> > #define MSR_PE PPC_BIT_NR(60) /* Protection enable on 403 */
> > +#define MSR_SIBRCA4 PPC_BIT_NR(60) /* SIB Return Code Accumulator 4 (PPE42) */
> > +#define MSR_SIBRCA5 PPC_BIT_NR(61) /* SIB Return Code Accumulator 5 (PPE42) */
> > #define MSR_PX PPC_BIT_NR(61) /* Protection exclusive on 403 x */
> > #define MSR_PMM PPC_BIT_NR(61) /* Performance monitor mark on POWER x */
> > #define MSR_RI PPC_BIT_NR(62) /* Recoverable interrupt 1 */
> > +#define MSR_SIBRCA6 PPC_BIT_NR(62) /* SIB Return Code Accumulator 6 (PPE42) */
> > +#define MSR_SIBRCA7 PPC_BIT_NR(63) /* SIB Return Code Accumulator 7 (PPE42) */
> > #define MSR_LE PPC_BIT_NR(63) /* Little-endian mode 1 hflags */
> >
> > FIELD(MSR, SF, MSR_SF, 1)
> > @@ -517,6 +546,9 @@ FIELD(MSR, PX, MSR_PX, 1)
> > FIELD(MSR, PMM, MSR_PMM, 1)
> > FIELD(MSR, RI, MSR_RI, 1)
> > FIELD(MSR, LE, MSR_LE, 1)
> > +FIELD(MSR, SEM, MSR_SEM6, 7)
> > +FIELD(MSR, SIBRC, MSR_SIBRC2, 3)
> > +FIELD(MSR, SIBRCA, MSR_SIBRCA7, 8)
> >
> > /*
> > * FE0 and FE1 bits are not side-by-side
> > @@ -730,6 +762,31 @@ FIELD(MSR, LE, MSR_LE, 1)
> > #define ESR_VLEMI PPC_BIT(58) /* VLE operation */
> > #define ESR_MIF PPC_BIT(62) /* Misaligned instruction (VLE) */
> >
> > +/* PPE42 Interrupt Status Register bits */
> > +#define PPE42_ISR_SRSMS0 PPC_BIT_NR(48) /* Sys Reset State Machine State 0 */
> > +#define PPE42_ISR_SRSMS1 PPC_BIT_NR(49) /* Sys Reset State Machine State 1 */
> > +#define PPE42_ISR_SRSMS2 PPC_BIT_NR(50) /* Sys Reset State Machine State 2 */
> > +#define PPE42_ISR_SRSMS3 PPC_BIT_NR(51) /* Sys Reset State Machine State 3 */
> > +#define PPE42_ISR_EP PPC_BIT_NR(53) /* MSR[EE] Maskable Event Pending */
> > +#define PPE42_ISR_PTR PPC_BIT_NR(56) /* Program Interrupt from trap */
> > +#define PPE42_ISR_ST PPC_BIT_NR(57) /* Data Interrupt caused by store */
> > +#define PPE42_ISR_MFE PPC_BIT_NR(60) /* Multiple Fault Error */
> > +#define PPE42_ISR_MCS0 PPC_BIT_NR(61) /* Machine Check Status bit0 */
> > +#define PPE42_ISR_MCS1 PPC_BIT_NR(62) /* Machine Check Status bit1 */
> > +#define PPE42_ISR_MCS2 PPC_BIT_NR(63) /* Machine Check Status bit2 */
> > +FIELD(PPE42_ISR, SRSMS, PPE42_ISR_SRSMS3, 4)
> > +FIELD(PPE42_ISR, MCS, PPE42_ISR_MCS2, 3)
> > +
> > +/* PPE42 Machine Check Status field values */
> > +#define PPE42_ISR_MCS_INSTRUCTION 0
> > +#define PPE42_ISR_MCS_DATA_LOAD 1
> > +#define PPE42_ISR_MCS_DATA_PRECISE_STORE 2
> > +#define PPE42_ISR_MCS_DATA_IMPRECISE_STORE 3
> > +#define PPE42_ISR_MCS_PROGRAM 4
> > +#define PPE42_ISR_MCS_ISI 5
> > +#define PPE42_ISR_MCS_ALIGNMENT 6
> > +#define PPE42_ISR_MCS_DSI 7
> > +
> > /* Transaction EXception And Summary Register bits */
> > #define TEXASR_FAILURE_PERSISTENT (63 - 7)
> > #define TEXASR_DISALLOWED (63 - 8)
> > @@ -785,6 +842,8 @@ enum {
> > POWERPC_FLAG_SMT_1LPAR = 0x00800000,
> > /* Has BHRB */
> > POWERPC_FLAG_BHRB = 0x01000000,
> > + /* Use PPE42-specific behavior */
> > + POWERPC_FLAG_PPE42 = 0x02000000,
> > };
> >
> > /*
> > @@ -1750,9 +1809,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_CSRR0 (0x03A)
> > #define SPR_BOOKE_CSRR1 (0x03B)
> > #define SPR_BOOKE_DEAR (0x03D)
> > +#define SPR_PPE42_EDR (0x03D)
> > #define SPR_IAMR (0x03D)
> > #define SPR_BOOKE_ESR (0x03E)
> > +#define SPR_PPE42_ISR (0x03E)
> > #define SPR_BOOKE_IVPR (0x03F)
> > +#define SPR_PPE42_IVPR (0x03F)
> > #define SPR_MPC_EIE (0x050)
> > #define SPR_MPC_EID (0x051)
> > #define SPR_MPC_NRI (0x052)
> > @@ -1818,6 +1880,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_TBU40 (0x11E)
> > #define SPR_SVR (0x11E)
> > #define SPR_BOOKE_PIR (0x11E)
> > +#define SPR_PPE42_PIR (0x11E)
> > #define SPR_PVR (0x11F)
> > #define SPR_HSPRG0 (0x130)
> > #define SPR_BOOKE_DBSR (0x130)
> > @@ -1827,6 +1890,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_EPCR (0x133)
> > #define SPR_SPURR (0x134)
> > #define SPR_BOOKE_DBCR0 (0x134)
> > +#define SPR_PPE42_DBCR (0x134)
> > #define SPR_IBCR (0x135)
> > #define SPR_PURR (0x135)
> > #define SPR_BOOKE_DBCR1 (0x135)
> > @@ -1844,6 +1908,7 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_HSRR1 (0x13B)
> > #define SPR_BOOKE_IAC4 (0x13B)
> > #define SPR_BOOKE_DAC1 (0x13C)
> > +#define SPR_PPE42_DACR (0x13C)
> > #define SPR_MMCRH (0x13C)
> > #define SPR_DABR2 (0x13D)
> > #define SPR_BOOKE_DAC2 (0x13D)
> > @@ -1853,12 +1918,14 @@ void ppc_compat_add_property(Object *obj, const char *name,
> > #define SPR_BOOKE_DVC2 (0x13F)
> > #define SPR_LPIDR (0x13F)
> > #define SPR_BOOKE_TSR (0x150)
> > +#define SPR_PPE42_TSR (0x150)
> > #define SPR_HMER (0x150)
> > #define SPR_HMEER (0x151)
> > #define SPR_PCR (0x152)
> > #define SPR_HEIR (0x153)
> > #define SPR_BOOKE_LPIDR (0x152)
> > #define SPR_BOOKE_TCR (0x154)
> > +#define SPR_PPE42_TCR (0x154)
> > #define SPR_BOOKE_TLB0PS (0x158)
> > #define SPR_BOOKE_TLB1PS (0x159)
> > #define SPR_BOOKE_TLB2PS (0x15A)
> > @@ -2528,6 +2595,12 @@ enum {
> > PPC2_MEM_LWSYNC = 0x0000000000200000ULL,
> > /* ISA 2.06 BCD assist instructions */
> > PPC2_BCDA_ISA206 = 0x0000000000400000ULL,
> > + /* PPE42 instructions */
> > + PPC2_PPE42 = 0x0000000000800000ULL,
> > + /* PPE42X instructions */
> > + PPC2_PPE42X = 0x0000000001000000ULL,
> > + /* PPE42XM instructions */
> > + PPC2_PPE42XM = 0x0000000002000000ULL,
> >
> > #define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
> > PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
> > @@ -2537,7 +2610,8 @@ enum {
> > PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
> > PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
> > PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC | \
> > - PPC2_BCDA_ISA206)
> > + PPC2_BCDA_ISA206 | PPC2_PPE42 | PPC2_PPE42X | \
> > + PPC2_PPE42XM)
> > };
> >
> > /*****************************************************************************/
> > diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> > index a0e77f2673..698d61bf0c 100644
> > --- a/target/ppc/cpu_init.c
> > +++ b/target/ppc/cpu_init.c
> > @@ -1653,6 +1653,47 @@ static void register_8xx_sprs(CPUPPCState *env)
> > * ... and more (thermal management, performance counters, ...)
> > */
> >
> > +static void register_ppe42_sprs(CPUPPCState *env)
> > +{
> > + spr_register(env, SPR_PPE42_EDR, "EDR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_ISR, "ISR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_IVPR, "IVPR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, SPR_NOACCESS,
> > + 0xfff80000);
> > + spr_register(env, SPR_PPE42_PIR, "PIR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_pir,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_DBCR, "DBCR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_40x_dbcr0,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_DACR, "DACR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_generic,
> > + 0x00000000);
> > + /* Timer */
> > + spr_register(env, SPR_DECR, "DECR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_decr, &spr_write_decr,
> > + 0x00000000);
> > + spr_register(env, SPR_PPE42_TSR, "TSR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_booke_tsr,
> > + 0x00000000);
> > + spr_register(env, SPR_BOOKE_TCR, "TCR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, &spr_write_booke_tcr,
> > + 0x00000000);
> > +}
> > +
> > /*****************************************************************************/
> > /* Exception vectors models */
> > static void init_excp_4xx(CPUPPCState *env)
> > @@ -1679,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)
> > @@ -2200,6 +2265,80 @@ POWERPC_FAMILY(405)(ObjectClass *oc, const void *data)
> > POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
> > }
> >
> > +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 */
> > + ppc40x_irq_init(env_archcpu(env));
> > +
> > + SET_FIT_PERIOD(8, 12, 16, 20);
> > + SET_WDT_PERIOD(16, 20, 24, 28);
> > +}
> > +
> > +static void ppe42_class_common_init(PowerPCCPUClass *pcc)
> > +{
> > + pcc->init_proc = init_proc_ppe42;
> > + pcc->check_pow = check_pow_nocheck;
> > + pcc->check_attn = check_attn_none;
> > + pcc->insns_flags = PPC_INSNS_BASE |
> > + PPC_WRTEE |
> > + PPC_CACHE |
> > + PPC_CACHE_DCBZ |
> > + PPC_MEM_SYNC;
> > + pcc->msr_mask = R_MSR_SEM_MASK |
> > + (1ull << MSR_IS0) |
> > + R_MSR_SIBRC_MASK |
> > + (1ull << MSR_LP) |
> > + (1ull << MSR_WE) |
> > + (1ull << MSR_IS1) |
> > + (1ull << MSR_UIE) |
> > + (1ull << MSR_EE) |
> > + (1ull << MSR_ME) |
> > + (1ull << MSR_IS2) |
> > + (1ull << MSR_IS3) |
> > + (1ull << MSR_IPE) |
> > + R_MSR_SIBRCA_MASK;
> > + pcc->mmu_model = POWERPC_MMU_REAL;
> > + 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;
> > +}
> > +
> > +POWERPC_FAMILY(ppe42)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42";
> > + pcc->insns_flags2 = PPC2_PPE42;
> > + ppe42_class_common_init(pcc);
> > +}
> > +
> > +POWERPC_FAMILY(ppe42x)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42X";
> > + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X;
> > + ppe42_class_common_init(pcc);
> > +}
> > +
> > +POWERPC_FAMILY(ppe42xm)(ObjectClass *oc, const void *data)
> > +{
> > + DeviceClass *dc = DEVICE_CLASS(oc);
> > + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
> > +
> > + dc->desc = "PPE 42XM";
> > + pcc->insns_flags2 = PPC2_PPE42 | PPC2_PPE42X | PPC2_PPE42XM;
> > + ppe42_class_common_init(pcc);
> > +}
> > +
> > static void init_proc_440EP(CPUPPCState *env)
> > {
> > register_BookE_sprs(env, 0x000000000000FFFFULL);
> > @@ -6802,53 +6941,63 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> >
> > /* MSR bits & flags consistency checks */
> > if (env->msr_mask & (1 << 25)) {
> > - switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> > + switch (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_SPE:
> > case POWERPC_FLAG_VRE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n");
> > + "Should define POWERPC_FLAG_SPE or POWERPC_FLAG_VRE\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > } else if (env->flags & (POWERPC_FLAG_SPE | POWERPC_FLAG_VRE)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n");
> > + "Should not define POWERPC_FLAG_SPE nor POWERPC_FLAG_VRE\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 17)) {
> > - switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> > + switch (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_TGPR:
> > case POWERPC_FLAG_CE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n");
> > + "Should define POWERPC_FLAG_TGPR or POWERPC_FLAG_CE\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > - } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE)) {
> > + } else if (env->flags & (POWERPC_FLAG_TGPR | POWERPC_FLAG_CE |
> > + POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n");
> > + "Should not define POWERPC_FLAG_TGPR nor POWERPC_FLAG_CE\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 10)) {
> > switch (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> > - POWERPC_FLAG_UBLE)) {
> > + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_SE:
> > case POWERPC_FLAG_DWE:
> > case POWERPC_FLAG_UBLE:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > "Should define POWERPC_FLAG_SE or POWERPC_FLAG_DWE or "
> > - "POWERPC_FLAG_UBLE\n");
> > + "POWERPC_FLAG_UBLE or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > } else if (env->flags & (POWERPC_FLAG_SE | POWERPC_FLAG_DWE |
> > - POWERPC_FLAG_UBLE)) {
> > + POWERPC_FLAG_UBLE | POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > "Should not define POWERPC_FLAG_SE nor POWERPC_FLAG_DWE nor "
> > - "POWERPC_FLAG_UBLE\n");
> > + "POWERPC_FLAG_UBLE nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 9)) {
> > @@ -6867,18 +7016,23 @@ static void init_ppc_proc(PowerPCCPU *cpu)
> > exit(1);
> > }
> > if (env->msr_mask & (1 << 2)) {
> > - switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> > + switch (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> > + POWERPC_FLAG_PPE42)) {
> > case POWERPC_FLAG_PX:
> > case POWERPC_FLAG_PMM:
> > + case POWERPC_FLAG_PPE42:
> > break;
> > default:
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n");
> > + "Should define POWERPC_FLAG_PX or POWERPC_FLAG_PMM\n"
> > + "or POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > - } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM)) {
> > + } else if (env->flags & (POWERPC_FLAG_PX | POWERPC_FLAG_PMM |
> > + POWERPC_FLAG_PPE42)) {
> > fprintf(stderr, "PowerPC MSR definition inconsistency\n"
> > - "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n");
> > + "Should not define POWERPC_FLAG_PX nor POWERPC_FLAG_PMM\n"
> > + "nor POWERPC_FLAG_PPE42\n");
> > exit(1);
> > }
> > if ((env->flags & POWERPC_FLAG_BUS_CLK) == 0) {
> > @@ -7243,39 +7397,40 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
> > }
> >
> > msr = (target_ulong)0;
> > - msr |= (target_ulong)MSR_HVB;
> > - msr |= (target_ulong)1 << MSR_EP;
> > + if (!(env->flags & POWERPC_FLAG_PPE42)) {
> > + msr |= (target_ulong)MSR_HVB;
> > + msr |= (target_ulong)1 << MSR_EP;
> > #if defined(DO_SINGLE_STEP) && 0
> > - /* Single step trace mode */
> > - msr |= (target_ulong)1 << MSR_SE;
> > - msr |= (target_ulong)1 << MSR_BE;
> > + /* Single step trace mode */
> > + msr |= (target_ulong)1 << MSR_SE;
> > + msr |= (target_ulong)1 << MSR_BE;
> > #endif
> > #if defined(CONFIG_USER_ONLY)
> > - msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> > - msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> > - msr |= (target_ulong)1 << MSR_FE1;
> > - msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> > - msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> > - msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> > - msr |= (target_ulong)1 << MSR_PR;
> > + msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
> > + msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
> > + msr |= (target_ulong)1 << MSR_FE1;
> > + msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
> > + msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
> > + msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
> > + msr |= (target_ulong)1 << MSR_PR;
> > #if defined(TARGET_PPC64)
> > - msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> > + msr |= (target_ulong)1 << MSR_TM; /* Transactional memory */
> > #endif
> > #if !TARGET_BIG_ENDIAN
> > - msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> > - if (!((env->msr_mask >> MSR_LE) & 1)) {
> > - fprintf(stderr, "Selected CPU does not support little-endian.\n");
> > - exit(1);
> > - }
> > + msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
> > + if (!((env->msr_mask >> MSR_LE) & 1)) {
> > + fprintf(stderr, "Selected CPU does not support little-endian.\n");
> > + exit(1);
> > + }
> > #endif
> > #endif
> >
> > #if defined(TARGET_PPC64)
> > - if (mmu_is_64bit(env->mmu_model)) {
> > - msr |= (1ULL << MSR_SF);
> > - }
> > + if (mmu_is_64bit(env->mmu_model)) {
> > + msr |= (1ULL << MSR_SF);
> > + }
> > #endif
> > -
> > + }
> > hreg_store_msr(env, msr, 1);
> >
> > #if !defined(CONFIG_USER_ONLY)
> > @@ -7725,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/helper_regs.c b/target/ppc/helper_regs.c
> > index 7e5726871e..9953d73884 100644
> > --- a/target/ppc/helper_regs.c
> > +++ b/target/ppc/helper_regs.c
> > @@ -186,6 +186,10 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
> > if (env->spr[SPR_LPCR] & LPCR_HR) {
> > hflags |= 1 << HFLAGS_HR;
> > }
> > + if (unlikely(ppc_flags & POWERPC_FLAG_PPE42)) {
> > + /* PPE42 has a single address space and no problem state */
> > + msr = 0;
> > + }
> >
> > #ifndef CONFIG_USER_ONLY
> > if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
> > @@ -306,9 +310,6 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
> > value &= ~(1 << MSR_ME);
> > value |= env->msr & (1 << MSR_ME);
> > }
> > - if ((value ^ env->msr) & (R_MSR_IR_MASK | R_MSR_DR_MASK)) {
> > - cpu_interrupt_exittb(cs);
> > - }
> > if ((env->mmu_model == POWERPC_MMU_BOOKE ||
> > env->mmu_model == POWERPC_MMU_BOOKE206) &&
> > ((value ^ env->msr) & R_MSR_GS_MASK)) {
> > @@ -319,8 +320,14 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
> > /* Swap temporary saved registers with GPRs */
> > hreg_swap_gpr_tgpr(env);
> > }
> > - if (unlikely((value ^ env->msr) & R_MSR_EP_MASK)) {
> > - env->excp_prefix = FIELD_EX64(value, MSR, EP) * 0xFFF00000;
> > + /* PPE42 MSR has bits overlapping with others */
> > + if (!(env->flags & POWERPC_FLAG_PPE42)) {
> > + if ((value ^ env->msr) & (R_MSR_IR_MASK | R_MSR_DR_MASK)) {
> > + cpu_interrupt_exittb(cs);
> > + }
> > + if (unlikely((value ^ env->msr) & R_MSR_EP_MASK)) {
> > + env->excp_prefix = FIELD_EX64(value, MSR, EP) * 0xFFF00000;
> > + }
> > }
> > /*
> > * If PR=1 then EE, IR and DR must be 1
> > @@ -462,6 +469,17 @@ void register_generic_sprs(PowerPCCPU *cpu)
> > SPR_NOACCESS, SPR_NOACCESS,
> > &spr_read_generic, &spr_write_generic,
> > 0x00000000);
> > +
> > + if (env->insns_flags2 & PPC2_PPE42) {
> > + spr_register(env, SPR_PVR, "PVR",
> > + SPR_NOACCESS, SPR_NOACCESS,
> > + &spr_read_generic, SPR_NOACCESS,
> > + pcc->pvr);
> > +
> > + /* PPE42 doesn't support additional SPRG regs or timebase */
> > + return;
> > + }
> > +
> > spr_register(env, SPR_SPRG1, "SPRG1",
> > SPR_NOACCESS, SPR_NOACCESS,
> > &spr_read_generic, &spr_write_generic,
> > 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;
> > diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> > index 27f90c3cc5..fc817dab54 100644
> > --- a/target/ppc/translate.c
> > +++ b/target/ppc/translate.c
> > @@ -4264,8 +4264,10 @@ static void gen_mtmsr(DisasContext *ctx)
> > /* L=1 form only updates EE and RI */
> > mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
> > } else {
> > - /* mtmsr does not alter S, ME, or LE */
> > - mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> > + if (likely(!(ctx->insns_flags2 & PPC2_PPE42))) {
> > + /* mtmsr does not alter S, ME, or LE */
> > + mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
> > + }
> >
> > /*
> > * XXX: we need to update nip before the store if we enter
next prev parent reply other threads:[~2025-09-02 16:59 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-26 20:17 [PATCH v2 0/4] Add IBM PPE42 CPU support Glenn Miles
2025-08-26 20:17 ` [PATCH v2 1/4] target/ppc: Add IBM PPE42 family of processors Glenn Miles
2025-09-01 7:29 ` Cédric Le Goater
2025-09-02 16:59 ` Miles Glenn [this message]
2025-08-26 20:17 ` [PATCH v2 2/4] target/ppc: Add IBM PPE42 special instructions Glenn Miles
2025-09-04 12:24 ` Chinmay Rath
2025-09-04 12:30 ` Chinmay Rath
2025-09-04 14:56 ` Miles Glenn
2025-08-26 20:17 ` [PATCH v2 3/4] hw/ppc: Add a test machine for the IBM PPE42 CPU Glenn Miles
2025-09-01 7:25 ` Cédric Le Goater
2025-09-01 10:15 ` BALATON Zoltan
2025-09-02 16:56 ` Miles Glenn
2025-09-03 22:50 ` Miles Glenn
2025-08-26 20:17 ` [PATCH v2 4/4] 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=6707e44ef91de579a0aa3bd265f4c4feb05c0121.camel@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).