Message ID | 1332862915-27501-2-git-send-email-mark.cave-ayland@ilande.co.uk |
---|---|
State | New |
Headers | show |
On 03/27/2012 10:41 AM, Mark Cave-Ayland wrote: > Commit 41557447d30eeb944e42069513df13585f5e6c7f introduced a new method of > calculating the MSR for the interrupt context. However this doesn't quite > agree with the PowerISA 2.06B specification (pp. 811-814) since too many > bits were being cleared. > > This patch corrects the calculation of the interrupt MSR whilst including > additional comments to clarify which bits are being changed within both the > MSR and the interrupt MSR. > > Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> > Signed-off-by: Martin Sucha <sucha14@uniba.sk> > --- > target-ppc/helper.c | 23 ++++++++++++++++++++--- > 1 files changed, 20 insertions(+), 3 deletions(-) > > diff --git a/target-ppc/helper.c b/target-ppc/helper.c > index 39dcc27..653f818 100644 > --- a/target-ppc/helper.c > +++ b/target-ppc/helper.c > @@ -2459,6 +2459,8 @@ static inline void dump_syscall(CPUPPCState *env) > /* Note that this function should be greatly optimized > * when called with a constant excp, from ppc_hw_interrupt > */ > +#define MSR_BIT(x) ((target_ulong)1 << x) If we're going to make this specific to MSRs, might as well cut down on the user's verbosity: #define MSR_BIT(x) ((target_ulong)1 << MSR_##x) ...and move it to a header file. Or possibly have the header file define a set of MSRBIT_IR, MSRBIT_DR, etc. > static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) > { > target_ulong msr, new_msr, vector; > @@ -2478,11 +2480,26 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) > qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx > " => %08x (%02x)\n", env->nip, excp, env->error_code); > > - /* new srr1 value excluding must-be-zero bits */ > + /* new srr1 value with interrupt-specific bits defaulting to zero */ > msr = env->msr & ~0x783f0000ULL; > > - /* new interrupt handler msr */ > - new_msr = env->msr & ((target_ulong)1 << MSR_ME); > + switch (excp_model) { > + case POWERPC_EXCP_BOOKE: > + /* new interrupt handler msr */ > + new_msr = env->msr & ((target_ulong)1 << MSR_ME); > + break; > + > + default: > + /* new interrupt handler msr (as per PowerISA 2.06B p.811 and p.814): > + 1) force the following bits to zero > + IR, DR, FE0, FE1, EE, BE, FP, PMM, PR, SE > + 2) default the following bits to zero (can be overidden later on) > + RI */ > + new_msr = env->msr & ~(MSR_BIT(MSR_IR) | MSR_BIT(MSR_DR) > + | MSR_BIT(MSR_FE0)| MSR_BIT(MSR_FE1) | MSR_BIT(MSR_EE) > + | MSR_BIT(MSR_BE) | MSR_BIT(MSR_FP) | MSR_BIT(MSR_PMM) > + | MSR_BIT(MSR_PR) | MSR_BIT(MSR_SE) | MSR_BIT(MSR_RI)); > + } What about POWERPC_EXCP_40x? And are all the classic chips OK with the 2.06B implementation? BTW, it's unfortunate that QEMU uses the same namespacing for PPC exceptions as for PPC exception models. Makes grepping for exception models a pain. -Scott
On Tue, Mar 27, 2012 at 12:47:32PM -0500, Scott Wood wrote: > On 03/27/2012 10:41 AM, Mark Cave-Ayland wrote: > > Commit 41557447d30eeb944e42069513df13585f5e6c7f introduced a new method of > > calculating the MSR for the interrupt context. However this doesn't quite > > agree with the PowerISA 2.06B specification (pp. 811-814) since too many > > bits were being cleared. > > > > This patch corrects the calculation of the interrupt MSR whilst including > > additional comments to clarify which bits are being changed within both the > > MSR and the interrupt MSR. > > > > Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> > > Signed-off-by: Martin Sucha <sucha14@uniba.sk> > > --- > > target-ppc/helper.c | 23 ++++++++++++++++++++--- > > 1 files changed, 20 insertions(+), 3 deletions(-) > > > > diff --git a/target-ppc/helper.c b/target-ppc/helper.c > > index 39dcc27..653f818 100644 > > --- a/target-ppc/helper.c > > +++ b/target-ppc/helper.c > > @@ -2459,6 +2459,8 @@ static inline void dump_syscall(CPUPPCState *env) > > /* Note that this function should be greatly optimized > > * when called with a constant excp, from ppc_hw_interrupt > > */ > > +#define MSR_BIT(x) ((target_ulong)1 << x) > > If we're going to make this specific to MSRs, might as well cut down on > the user's verbosity: > > #define MSR_BIT(x) ((target_ulong)1 << MSR_##x) > > ...and move it to a header file. > > Or possibly have the header file define a set of MSRBIT_IR, MSRBIT_DR, etc. > > > static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) > > { > > target_ulong msr, new_msr, vector; > > @@ -2478,11 +2480,26 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) > > qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx > > " => %08x (%02x)\n", env->nip, excp, env->error_code); > > > > - /* new srr1 value excluding must-be-zero bits */ > > + /* new srr1 value with interrupt-specific bits defaulting to zero */ > > msr = env->msr & ~0x783f0000ULL; > > > > - /* new interrupt handler msr */ > > - new_msr = env->msr & ((target_ulong)1 << MSR_ME); > > + switch (excp_model) { > > + case POWERPC_EXCP_BOOKE: > > + /* new interrupt handler msr */ > > + new_msr = env->msr & ((target_ulong)1 << MSR_ME); > > + break; > > + > > + default: > > + /* new interrupt handler msr (as per PowerISA 2.06B p.811 and p.814): > > + 1) force the following bits to zero > > + IR, DR, FE0, FE1, EE, BE, FP, PMM, PR, SE > > + 2) default the following bits to zero (can be overidden later on) > > + RI */ > > + new_msr = env->msr & ~(MSR_BIT(MSR_IR) | MSR_BIT(MSR_DR) > > + | MSR_BIT(MSR_FE0)| MSR_BIT(MSR_FE1) | MSR_BIT(MSR_EE) > > + | MSR_BIT(MSR_BE) | MSR_BIT(MSR_FP) | MSR_BIT(MSR_PMM) > > + | MSR_BIT(MSR_PR) | MSR_BIT(MSR_SE) | MSR_BIT(MSR_RI)); > > + } > > What about POWERPC_EXCP_40x? And are all the classic chips OK with the > 2.06B implementation? Hrm, yeah. I think what you ought to do is to use the new logic just for the "classic" exception models. Have the default branch remain the one that just masks ME. That's wrong, but it's the same wrong as we have already, and we can fix it later once we've verified what the right thing to do is for 40x and BookE.
On 28/03/12 01:46, David Gibson wrote: Hi David, >> If we're going to make this specific to MSRs, might as well cut down on >> the user's verbosity: >> >> #define MSR_BIT(x) ((target_ulong)1<< MSR_##x) >> >> ...and move it to a header file. >> >> Or possibly have the header file define a set of MSRBIT_IR, MSRBIT_DR, etc. I think I prefer your macro above and move it to a relevant part of target-ppc/cpu.h with the other MSR defines. >>> static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) >>> { >>> target_ulong msr, new_msr, vector; >>> @@ -2478,11 +2480,26 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) >>> qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx >>> " => %08x (%02x)\n", env->nip, excp, env->error_code); >>> >>> - /* new srr1 value excluding must-be-zero bits */ >>> + /* new srr1 value with interrupt-specific bits defaulting to zero */ >>> msr = env->msr& ~0x783f0000ULL; >>> >>> - /* new interrupt handler msr */ >>> - new_msr = env->msr& ((target_ulong)1<< MSR_ME); >>> + switch (excp_model) { >>> + case POWERPC_EXCP_BOOKE: >>> + /* new interrupt handler msr */ >>> + new_msr = env->msr& ((target_ulong)1<< MSR_ME); >>> + break; >>> + >>> + default: >>> + /* new interrupt handler msr (as per PowerISA 2.06B p.811 and p.814): >>> + 1) force the following bits to zero >>> + IR, DR, FE0, FE1, EE, BE, FP, PMM, PR, SE >>> + 2) default the following bits to zero (can be overidden later on) >>> + RI */ >>> + new_msr = env->msr& ~(MSR_BIT(MSR_IR) | MSR_BIT(MSR_DR) >>> + | MSR_BIT(MSR_FE0)| MSR_BIT(MSR_FE1) | MSR_BIT(MSR_EE) >>> + | MSR_BIT(MSR_BE) | MSR_BIT(MSR_FP) | MSR_BIT(MSR_PMM) >>> + | MSR_BIT(MSR_PR) | MSR_BIT(MSR_SE) | MSR_BIT(MSR_RI)); >>> + } >> >> What about POWERPC_EXCP_40x? And are all the classic chips OK with the >> 2.06B implementation? > > Hrm, yeah. I think what you ought to do is to use the new logic just > for the "classic" exception models. Have the default branch remain > the one that just masks ME. That's wrong, but it's the same wrong as > we have already, and we can fix it later once we've verified what the > right thing to do is for 40x and BookE. I'm actually coming at this from a fixing what was potentially an OpenBIOS bug rather than a PPC angle, so I have to admit I have no I idea which ones are the "classic" exception models. Would you consider this to be just EXCP_STD, EXCP_6* and EXCP_7*? Many thanks, Mark.
On 03/29/2012 04:11 AM, Mark Cave-Ayland wrote: >>> What about POWERPC_EXCP_40x? And are all the classic chips OK with the >>> 2.06B implementation? >> >> Hrm, yeah. I think what you ought to do is to use the new logic just >> for the "classic" exception models. Have the default branch remain >> the one that just masks ME. That's wrong, but it's the same wrong as >> we have already, and we can fix it later once we've verified what the >> right thing to do is for 40x and BookE. > > I'm actually coming at this from a fixing what was potentially an > OpenBIOS bug rather than a PPC angle, so I have to admit I have no I > idea which ones are the "classic" exception models. Would you consider > this to be just EXCP_STD, EXCP_6* and EXCP_7*? Also POWERPC_EXCP_G2, and maybe POWERPC_EXCP_970? Even on server there's a question of whether it's a 2.06 chip or previous version of the architecture. One thing that sticks out for classic chips that is missing here is MSR[POW], which should be cleared on exceptions. -Scott
On 29/03/12 20:06, Scott Wood wrote: >>> Hrm, yeah. I think what you ought to do is to use the new logic just >>> for the "classic" exception models. Have the default branch remain >>> the one that just masks ME. That's wrong, but it's the same wrong as >>> we have already, and we can fix it later once we've verified what the >>> right thing to do is for 40x and BookE. Agreed. I've just reworked the patch based on yours/David's comments so that it should minimise the effect of any changes. >> I'm actually coming at this from a fixing what was potentially an >> OpenBIOS bug rather than a PPC angle, so I have to admit I have no I >> idea which ones are the "classic" exception models. Would you consider >> this to be just EXCP_STD, EXCP_6* and EXCP_7*? > > Also POWERPC_EXCP_G2, and maybe POWERPC_EXCP_970? Even on server > there's a question of whether it's a 2.06 chip or previous version of > the architecture. > > One thing that sticks out for classic chips that is missing here is > MSR[POW], which should be cleared on exceptions. I'm not sure about _970 given that it's 64-bit, so I've left this on the old behaviour for the time being and altered the patch so that MSR_POW is now cleared in the classic exception path too. I see that Andreas has already applied the second patch in the series to ppc-next, so I'll just resubmit a revised version of the first patch shortly. ATB, Mark.
diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 39dcc27..653f818 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2459,6 +2459,8 @@ static inline void dump_syscall(CPUPPCState *env) /* Note that this function should be greatly optimized * when called with a constant excp, from ppc_hw_interrupt */ +#define MSR_BIT(x) ((target_ulong)1 << x) + static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) { target_ulong msr, new_msr, vector; @@ -2478,11 +2480,26 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %08x (%02x)\n", env->nip, excp, env->error_code); - /* new srr1 value excluding must-be-zero bits */ + /* new srr1 value with interrupt-specific bits defaulting to zero */ msr = env->msr & ~0x783f0000ULL; - /* new interrupt handler msr */ - new_msr = env->msr & ((target_ulong)1 << MSR_ME); + switch (excp_model) { + case POWERPC_EXCP_BOOKE: + /* new interrupt handler msr */ + new_msr = env->msr & ((target_ulong)1 << MSR_ME); + break; + + default: + /* new interrupt handler msr (as per PowerISA 2.06B p.811 and p.814): + 1) force the following bits to zero + IR, DR, FE0, FE1, EE, BE, FP, PMM, PR, SE + 2) default the following bits to zero (can be overidden later on) + RI */ + new_msr = env->msr & ~(MSR_BIT(MSR_IR) | MSR_BIT(MSR_DR) + | MSR_BIT(MSR_FE0)| MSR_BIT(MSR_FE1) | MSR_BIT(MSR_EE) + | MSR_BIT(MSR_BE) | MSR_BIT(MSR_FP) | MSR_BIT(MSR_PMM) + | MSR_BIT(MSR_PR) | MSR_BIT(MSR_SE) | MSR_BIT(MSR_RI)); + } /* target registers */ srr0 = SPR_SRR0;