diff -r 5271608211c5 sys/arch/mips/mips/mipsX_subr.S --- a/sys/arch/mips/mips/mipsX_subr.S Mon Apr 14 02:13:34 2025 +0000 +++ b/sys/arch/mips/mips/mipsX_subr.S Mon Apr 14 23:37:54 2025 +0000 @@ -1322,10 +1322,34 @@ /* * Get exception PC and fetch the instruction. We know we can do * this since the instruction actually got read. + * + * Use k0, rather than v0, for the load address to work around a + * likely Cavium bug that replaces v0 by the exception pc when + * userland continues -- we hypothesize that this will trash k0 + * instead, which is harmless because kernel exception vectors + * assume k0 is garbage anyway. + * + * It is tempting to use v1 because we are about to overwrite it + * with the output (and that appears to avoid the Cavium bug) -- + * but only if the instruction's destination register is v1, + * which we haven't determined yet. + * + * We also tried saving k0 in v0 by surrounding this stanza in + * + * move v0, k0 + * ... + * move k0, v0 + * + * rather than re-deriving k0 from k1, but that still trashed + * userland's v0 on return. + * + * See PR port-mips/59064: `jemalloc switch to 5.3 broke + * userland' for more + * background. */ - _MFC0 v0, MIPS_COP_0_EXC_PC + _MFC0 k0, MIPS_COP_0_EXC_PC MFC0_HAZARD - INT_L AT, 0(v0) + INT_L AT, 0(k0) /* * Was this rdhwr $3,$29? @@ -1346,6 +1370,8 @@ PTR_L v1, L_PRIVATE(k1) # rdhwr $3,$29 updates v1 + PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea + PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ REG_L AT, CALLFRAME_SIZ+TF_REG_AST(k0)# restore reg REG_L v0, CALLFRAME_SIZ+TF_REG_V0(k0) # restore reg eret