mirror of
https://github.com/torvalds/linux.git
synced 2024-11-04 11:04:38 +00:00
[SPARC64]: Fix some SUN4V TLB handling bugs.
1) Add error return checking for TLB load hypervisor calls. 2) Don't fallthru to dtlb tsb miss handler from itlb tsb miss handler, oops. 3) On window fixups, propagate fault information to fixup handler correctly. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
12e126ad22
commit
6c8927c963
@ -84,8 +84,9 @@ sun4v_itlb_load:
|
||||
mov %g3, %o2 ! PTE
|
||||
mov HV_MMU_IMMU, %o3 ! flags
|
||||
ta HV_MMU_MAP_ADDR_TRAP
|
||||
brnz,pn %o0, sun4v_itlb_error
|
||||
mov %g2, %o1 ! restore %o1
|
||||
mov %g1, %o0 ! restore %o0
|
||||
mov %g2, %o1 ! restore %o1
|
||||
mov %g5, %o2 ! restore %o2
|
||||
mov %g7, %o3 ! restore %o3
|
||||
|
||||
@ -126,8 +127,9 @@ sun4v_dtlb_load:
|
||||
mov %g3, %o2 ! PTE
|
||||
mov HV_MMU_DMMU, %o3 ! flags
|
||||
ta HV_MMU_MAP_ADDR_TRAP
|
||||
brnz,pn %o0, sun4v_dtlb_error
|
||||
mov %g2, %o1 ! restore %o1
|
||||
mov %g1, %o0 ! restore %o0
|
||||
mov %g2, %o1 ! restore %o1
|
||||
mov %g5, %o2 ! restore %o2
|
||||
mov %g7, %o3 ! restore %o3
|
||||
|
||||
@ -154,6 +156,7 @@ sun4v_itsb_miss:
|
||||
ldxa [%g1] ASI_SCRATCHPAD, %g1
|
||||
brz,pn %g5, kvmap_itlb_4v
|
||||
mov FAULT_CODE_ITLB, %g3
|
||||
ba,a,pt %xcc, sun4v_tsb_miss_common
|
||||
|
||||
/* Called from trap table with TAG TARGET placed into
|
||||
* %g6 and SCRATCHPAD_UTSBREG1 contents in %g1.
|
||||
@ -182,6 +185,56 @@ sun4v_tsb_miss_common:
|
||||
ba,pt %xcc, tsb_miss_page_table_walk_sun4v_fastpath
|
||||
ldx [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7
|
||||
|
||||
sun4v_itlb_error:
|
||||
sethi %hi(sun4v_err_itlb_vaddr), %g1
|
||||
stx %g4, [%g1 + %lo(sun4v_err_itlb_vaddr)]
|
||||
sethi %hi(sun4v_err_itlb_ctx), %g1
|
||||
srlx %g6, 48, %o1 ! ctx
|
||||
stx %o1, [%g1 + %lo(sun4v_err_itlb_ctx)]
|
||||
sethi %hi(sun4v_err_itlb_pte), %g1
|
||||
stx %g3, [%g1 + %lo(sun4v_err_itlb_pte)]
|
||||
sethi %hi(sun4v_err_itlb_error), %g1
|
||||
stx %o0, [%g1 + %lo(sun4v_err_itlb_error)]
|
||||
|
||||
rdpr %tl, %g4
|
||||
cmp %g4, 1
|
||||
ble,pt %icc, 1f
|
||||
sethi %hi(2f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
or %g7, %lo(2f), %g7
|
||||
|
||||
1: ba,pt %xcc, etrap
|
||||
2: or %g7, %lo(2b), %g7
|
||||
call sun4v_itlb_error_report
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
/* NOTREACHED */
|
||||
|
||||
sun4v_dtlb_error:
|
||||
sethi %hi(sun4v_err_dtlb_vaddr), %g1
|
||||
stx %g4, [%g1 + %lo(sun4v_err_dtlb_vaddr)]
|
||||
sethi %hi(sun4v_err_dtlb_ctx), %g1
|
||||
srlx %g6, 48, %o1 ! ctx
|
||||
stx %o1, [%g1 + %lo(sun4v_err_dtlb_ctx)]
|
||||
sethi %hi(sun4v_err_dtlb_pte), %g1
|
||||
stx %g3, [%g1 + %lo(sun4v_err_dtlb_pte)]
|
||||
sethi %hi(sun4v_err_dtlb_error), %g1
|
||||
stx %o0, [%g1 + %lo(sun4v_err_dtlb_error)]
|
||||
|
||||
rdpr %tl, %g4
|
||||
cmp %g4, 1
|
||||
ble,pt %icc, 1f
|
||||
sethi %hi(2f), %g7
|
||||
ba,pt %xcc, etraptl1
|
||||
or %g7, %lo(2f), %g7
|
||||
|
||||
1: ba,pt %xcc, etrap
|
||||
2: or %g7, %lo(2b), %g7
|
||||
call sun4v_dtlb_error_report
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
|
||||
/* NOTREACHED */
|
||||
|
||||
/* Instruction Access Exception, tl0. */
|
||||
sun4v_iacc:
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g2
|
||||
|
@ -1928,6 +1928,40 @@ void sun4v_nonresum_overflow(struct pt_regs *regs)
|
||||
atomic_inc(&sun4v_nonresum_oflow_cnt);
|
||||
}
|
||||
|
||||
unsigned long sun4v_err_itlb_vaddr;
|
||||
unsigned long sun4v_err_itlb_ctx;
|
||||
unsigned long sun4v_err_itlb_pte;
|
||||
unsigned long sun4v_err_itlb_error;
|
||||
|
||||
void sun4v_itlb_error_report(struct pt_regs *regs, int tl)
|
||||
{
|
||||
if (tl > 1)
|
||||
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
|
||||
|
||||
printk("SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl);
|
||||
printk("SUN4V-ITLB: vaddr[%lx] ctx[%lx] pte[%lx] error[%lx]\n",
|
||||
sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx,
|
||||
sun4v_err_itlb_pte, sun4v_err_itlb_error);
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
unsigned long sun4v_err_dtlb_vaddr;
|
||||
unsigned long sun4v_err_dtlb_ctx;
|
||||
unsigned long sun4v_err_dtlb_pte;
|
||||
unsigned long sun4v_err_dtlb_error;
|
||||
|
||||
void sun4v_dtlb_error_report(struct pt_regs *regs, int tl)
|
||||
{
|
||||
if (tl > 1)
|
||||
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
|
||||
|
||||
printk("SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl);
|
||||
printk("SUN4V-DTLB: vaddr[%lx] ctx[%lx] pte[%lx] error[%lx]\n",
|
||||
sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx,
|
||||
sun4v_err_dtlb_pte, sun4v_err_dtlb_error);
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
void do_fpe_common(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->tstate & TSTATE_PRIV) {
|
||||
|
@ -135,8 +135,8 @@ tsb_do_fault:
|
||||
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
nop
|
||||
nop
|
||||
SET_GL(1)
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g2
|
||||
.previous
|
||||
|
||||
bne,pn %xcc, tsb_do_itlb_fault
|
||||
@ -150,7 +150,7 @@ tsb_do_dtlb_fault:
|
||||
ldxa [%g4] ASI_DMMU, %g5
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
mov %g4, %g5
|
||||
ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g5
|
||||
nop
|
||||
.previous
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user