From 6adcdf6577f23777deb4fd9f414623fbc9e2118e Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 20 May 2020 21:15:43 +0000 Subject: [PATCH] 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 Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D24931 --- sys/mips/include/md_var.h | 1 + sys/mips/mips/cpu.c | 55 +++------------------------------------ sys/mips/mips/swtch.S | 2 ++ 3 files changed, 7 insertions(+), 51 deletions(-) diff --git a/sys/mips/include/md_var.h b/sys/mips/include/md_var.h index 0150e6acd354..23ef3baa34da 100644 --- a/sys/mips/include/md_var.h +++ b/sys/mips/include/md_var.h @@ -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); diff --git a/sys/mips/mips/cpu.c b/sys/mips/mips/cpu.c index 0f8583dbd40a..f2943b941d29 100644 --- a/sys/mips/mips/cpu.c +++ b/sys/mips/mips/cpu.c @@ -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); } diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S index c96c52494f1e..ef1b7abc84b9 100644 --- a/sys/mips/mips/swtch.S +++ b/sys/mips/mips/swtch.S @@ -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