Message ID | 20200320051809.24332-14-jniethe5@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Initial Prefixed Instruction support | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | warning | Failed to apply on branch powerpc/merge (8a445cbcb9f5090cb07ec6cbb89a8a1fc99a0ff7) |
snowpatch_ozlabs/apply_patch | warning | Failed to apply on branch powerpc/next (59ed2adf393109c56d383e568f2e57bb5ad6d901) |
snowpatch_ozlabs/apply_patch | warning | Failed to apply on branch linus/master (6c90b86a745a446717fdf408c4a8a4631a5e8ee3) |
snowpatch_ozlabs/apply_patch | warning | Failed to apply on branch powerpc/fixes (af3d0a68698c7e5df8b72267086b23422a3954bb) |
snowpatch_ozlabs/apply_patch | warning | Failed to apply on branch linux-next (aff7e57f8266549245eb4a272ce149b752dfce77) |
snowpatch_ozlabs/apply_patch | fail | Failed to apply to any branch |
Jordan Niethe's on March 20, 2020 3:18 pm: > Alignment interrupts can be caused by prefixed instructions accessing > memory. Prefixed instructions are not permitted to cross 64-byte > boundaries. If they do the alignment interrupt is invoked with SRR1 > BOUNDARY bit set. If this occurs send a SIGBUS to the offending process > if in user mode. If in kernel mode call bad_page_fault(). > > Signed-off-by: Jordan Niethe <jniethe5@gmail.com> > --- > v2: - Move __get_user_instr() and __get_user_instr_inatomic() to this > commit (previously in "powerpc sstep: Prepare to support prefixed > instructions"). > - Rename sufx to suffix > - Use a macro for calculating instruction length > v3: Move __get_user_{instr(), instr_inatomic()} up with the other > get_user definitions and remove nested if. > v4: Just do the things for alignment_exception(). Other changes handled > elsewhere. > --- > arch/powerpc/kernel/traps.c | 21 ++++++++++++++++++++- > 1 file changed, 20 insertions(+), 1 deletion(-) > > diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c > index a4764b039749..cd8b3043c268 100644 > --- a/arch/powerpc/kernel/traps.c > +++ b/arch/powerpc/kernel/traps.c > @@ -583,6 +583,10 @@ static inline int check_io_access(struct pt_regs *regs) > #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) > #define REASON_PRIVILEGED ESR_PPR > #define REASON_TRAP ESR_PTR > +#define REASON_PREFIXED 0 > +#define REASON_BOUNDARY 0 > + > +#define inst_length(reason) 4 > > /* single-step stuff */ > #define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC) > @@ -597,6 +601,10 @@ static inline int check_io_access(struct pt_regs *regs) > #define REASON_ILLEGAL SRR1_PROGILL > #define REASON_PRIVILEGED SRR1_PROGPRIV > #define REASON_TRAP SRR1_PROGTRAP > +#define REASON_PREFIXED SRR1_PREFIXED > +#define REASON_BOUNDARY SRR1_BOUNDARY > + > +#define inst_length(reason) (((reason) & REASON_PREFIXED) ? 8 : 4) Looks good. If you define REASON_BOUNDARY 0, then this will constant fold away so no need to define it twice. Thanks, Nick
On Mon, Mar 23, 2020 at 6:09 PM Nicholas Piggin <npiggin@gmail.com> wrote: > > Jordan Niethe's on March 20, 2020 3:18 pm: > > Alignment interrupts can be caused by prefixed instructions accessing > > memory. Prefixed instructions are not permitted to cross 64-byte > > boundaries. If they do the alignment interrupt is invoked with SRR1 > > BOUNDARY bit set. If this occurs send a SIGBUS to the offending process > > if in user mode. If in kernel mode call bad_page_fault(). > > > > Signed-off-by: Jordan Niethe <jniethe5@gmail.com> > > --- > > v2: - Move __get_user_instr() and __get_user_instr_inatomic() to this > > commit (previously in "powerpc sstep: Prepare to support prefixed > > instructions"). > > - Rename sufx to suffix > > - Use a macro for calculating instruction length > > v3: Move __get_user_{instr(), instr_inatomic()} up with the other > > get_user definitions and remove nested if. > > v4: Just do the things for alignment_exception(). Other changes handled > > elsewhere. > > --- > > arch/powerpc/kernel/traps.c | 21 ++++++++++++++++++++- > > 1 file changed, 20 insertions(+), 1 deletion(-) > > > > diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c > > index a4764b039749..cd8b3043c268 100644 > > --- a/arch/powerpc/kernel/traps.c > > +++ b/arch/powerpc/kernel/traps.c > > @@ -583,6 +583,10 @@ static inline int check_io_access(struct pt_regs *regs) > > #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) > > #define REASON_PRIVILEGED ESR_PPR > > #define REASON_TRAP ESR_PTR > > +#define REASON_PREFIXED 0 > > +#define REASON_BOUNDARY 0 > > + > > +#define inst_length(reason) 4 > > > > /* single-step stuff */ > > #define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC) > > @@ -597,6 +601,10 @@ static inline int check_io_access(struct pt_regs *regs) > > #define REASON_ILLEGAL SRR1_PROGILL > > #define REASON_PRIVILEGED SRR1_PROGPRIV > > #define REASON_TRAP SRR1_PROGTRAP > > +#define REASON_PREFIXED SRR1_PREFIXED > > +#define REASON_BOUNDARY SRR1_BOUNDARY > > + > > +#define inst_length(reason) (((reason) & REASON_PREFIXED) ? 8 : 4) > > Looks good. If you define REASON_BOUNDARY 0, then this will constant > fold away so no need to define it twice. Good point. > > Thanks, > Nick
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index a4764b039749..cd8b3043c268 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -583,6 +583,10 @@ static inline int check_io_access(struct pt_regs *regs) #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) #define REASON_PRIVILEGED ESR_PPR #define REASON_TRAP ESR_PTR +#define REASON_PREFIXED 0 +#define REASON_BOUNDARY 0 + +#define inst_length(reason) 4 /* single-step stuff */ #define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC) @@ -597,6 +601,10 @@ static inline int check_io_access(struct pt_regs *regs) #define REASON_ILLEGAL SRR1_PROGILL #define REASON_PRIVILEGED SRR1_PROGPRIV #define REASON_TRAP SRR1_PROGTRAP +#define REASON_PREFIXED SRR1_PREFIXED +#define REASON_BOUNDARY SRR1_BOUNDARY + +#define inst_length(reason) (((reason) & REASON_PREFIXED) ? 8 : 4) #define single_stepping(regs) ((regs)->msr & MSR_SE) #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) @@ -1593,11 +1601,20 @@ void alignment_exception(struct pt_regs *regs) { enum ctx_state prev_state = exception_enter(); int sig, code, fixed = 0; + unsigned long reason; /* We restore the interrupt state now */ if (!arch_irq_disabled_regs(regs)) local_irq_enable(); + reason = get_reason(regs); + + if (reason & REASON_BOUNDARY) { + sig = SIGBUS; + code = BUS_ADRALN; + goto bad; + } + if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT)) goto bail; @@ -1606,7 +1623,8 @@ void alignment_exception(struct pt_regs *regs) fixed = fix_alignment(regs); if (fixed == 1) { - regs->nip += 4; /* skip over emulated instruction */ + /* skip over emulated instruction */ + regs->nip += inst_length(reason); emulate_single_step(regs); goto bail; } @@ -1619,6 +1637,7 @@ void alignment_exception(struct pt_regs *regs) sig = SIGBUS; code = BUS_ADRALN; } +bad: if (user_mode(regs)) _exception(sig, regs, code, regs->dar); else
Alignment interrupts can be caused by prefixed instructions accessing memory. Prefixed instructions are not permitted to cross 64-byte boundaries. If they do the alignment interrupt is invoked with SRR1 BOUNDARY bit set. If this occurs send a SIGBUS to the offending process if in user mode. If in kernel mode call bad_page_fault(). Signed-off-by: Jordan Niethe <jniethe5@gmail.com> --- v2: - Move __get_user_instr() and __get_user_instr_inatomic() to this commit (previously in "powerpc sstep: Prepare to support prefixed instructions"). - Rename sufx to suffix - Use a macro for calculating instruction length v3: Move __get_user_{instr(), instr_inatomic()} up with the other get_user definitions and remove nested if. v4: Just do the things for alignment_exception(). Other changes handled elsewhere. --- arch/powerpc/kernel/traps.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)