Simplify hot-patching cpu_switch() for lack of UserLocal register.
Rather than walking all of cpu_switch looking for the sequence of instructions to patch, add a global label at the location that needs the patch applied. Reviewed by: brooks, Alfredo Mazzinghi <alfredo.mazzinghi_cl.cam.ac.uk> Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D24931
This commit is contained in:
parent
2583c3374d
commit
6adcdf6577
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=361296
@ -75,6 +75,7 @@ void mips_cpu_init(void);
|
||||
void mips_pcpu0_init(void);
|
||||
void mips_proc0_init(void);
|
||||
void mips_postboot_fixup(void);
|
||||
void cpu_switch_set_userlocal(void) __asm(__STRING(cpu_switch_set_userlocal));
|
||||
|
||||
extern int busdma_swi_pending;
|
||||
void busdma_swi(void);
|
||||
|
@ -68,44 +68,6 @@ struct mips_cpuinfo cpuinfo;
|
||||
#define _ENCODE_INSN(a,b,c,d,e) \
|
||||
((uint32_t)(((a) << 26)|((b) << 21)|((c) << 16)|((d) << 11)|(e)))
|
||||
|
||||
#if defined(__mips_n64)
|
||||
|
||||
# define _LOAD_T0_MDTLS_A1 \
|
||||
_ENCODE_INSN(OP_LD, A1, T0, 0, offsetof(struct thread, td_md.md_tls))
|
||||
|
||||
# define _LOAD_T0_MDTLS_TCV_OFFSET_A1 \
|
||||
_ENCODE_INSN(OP_LD, A1, T1, 0, \
|
||||
offsetof(struct thread, td_md.md_tls_tcb_offset))
|
||||
|
||||
# define _ADDU_V0_T0_T1 \
|
||||
_ENCODE_INSN(0, T0, T1, V0, OP_DADDU)
|
||||
|
||||
#else /* mips 32 */
|
||||
|
||||
# define _LOAD_T0_MDTLS_A1 \
|
||||
_ENCODE_INSN(OP_LW, A1, T0, 0, offsetof(struct thread, td_md.md_tls))
|
||||
|
||||
# define _LOAD_T0_MDTLS_TCV_OFFSET_A1 \
|
||||
_ENCODE_INSN(OP_LW, A1, T1, 0, \
|
||||
offsetof(struct thread, td_md.md_tls_tcb_offset))
|
||||
|
||||
# define _ADDU_V0_T0_T1 \
|
||||
_ENCODE_INSN(0, T0, T1, V0, OP_ADDU)
|
||||
|
||||
#endif /* ! __mips_n64 */
|
||||
|
||||
#if defined(__mips_n64) || defined(__mips_n32)
|
||||
|
||||
# define _MTC0_V0_USERLOCAL \
|
||||
_ENCODE_INSN(OP_COP0, OP_DMT, V0, 4, 2)
|
||||
|
||||
#else /* mips o32 */
|
||||
|
||||
# define _MTC0_V0_USERLOCAL \
|
||||
_ENCODE_INSN(OP_COP0, OP_MT, V0, 4, 2)
|
||||
|
||||
#endif /* ! (__mips_n64 || __mipsn32) */
|
||||
|
||||
#define _JR_RA _ENCODE_INSN(OP_SPECIAL, RA, 0, 0, OP_JR)
|
||||
#define _NOP 0
|
||||
|
||||
@ -120,18 +82,9 @@ remove_userlocal_code(uint32_t *cpu_switch_code)
|
||||
{
|
||||
uint32_t *instructp;
|
||||
|
||||
for (instructp = cpu_switch_code;; instructp++) {
|
||||
if (instructp[0] == _JR_RA)
|
||||
panic("%s: Unable to patch cpu_switch().", __func__);
|
||||
if (instructp[0] == _LOAD_T0_MDTLS_A1 &&
|
||||
instructp[1] == _LOAD_T0_MDTLS_TCV_OFFSET_A1 &&
|
||||
instructp[2] == _ADDU_V0_T0_T1 &&
|
||||
instructp[3] == _MTC0_V0_USERLOCAL) {
|
||||
instructp[0] = _JR_RA;
|
||||
instructp[1] = _NOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
instructp = cpu_switch_code;
|
||||
instructp[0] = _JR_RA;
|
||||
instructp[1] = _NOP;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -202,7 +155,7 @@ mips_get_identity(struct mips_cpuinfo *cpuinfo)
|
||||
* cpu_switch() and remove unsupported code.
|
||||
*/
|
||||
cpuinfo->userlocal_reg = false;
|
||||
remove_userlocal_code((uint32_t *)cpu_switch);
|
||||
remove_userlocal_code((uint32_t *)cpu_switch_set_userlocal);
|
||||
}
|
||||
|
||||
|
||||
|
@ -383,6 +383,8 @@ sw2:
|
||||
* Note that this code is removed if the CPU doesn't support ULRI by
|
||||
* remove_userlocal_code() in cpu.c.
|
||||
*/
|
||||
.globl cpu_switch_set_userlocal
|
||||
cpu_switch_set_userlocal:
|
||||
PTR_L t0, TD_MDTLS(a1) # Get TLS pointer
|
||||
PTR_L t1, TD_MDTLS_TCB_OFFSET(a1) # Get TLS/TCB offset
|
||||
PTR_ADDU v0, t0, t1
|
||||
|
Loading…
Reference in New Issue
Block a user