__static_call_fixup() invokes __static_call_transform() without holding text_mutex, which causes lockdep to complain in text_poke_bp(). Adding the proper locking cures that, but as this is either used during early boot or during module finalizing, it's not required to use text_poke_bp(). Add an argument to __static_call_transform() which tells it to use text_poke_early() for it.
Unified · Split
| @@ -25,7 +25,8 @@ static const u8 xor5rax[] = { 0x2e, 0x2e, 0x2e, 0x31, 0xc0 }; · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | static const u8 retinsn[] = { RET_INSN_OPCODE, 0xcc, 0xcc, 0xcc, 0xcc }; |
| 27 | 27 | |
| 28 | −static void __ref __static_call_transform(void *insn, enum insn_type type, void *func) | |
| 28 | +static void __ref __static_call_transform(void *insn, enum insn_type type, | |
| 29 | + void *func, bool modinit) | |
| 29 | 30 | { |
| 30 | 31 | const void *emulate = NULL; |
| 31 | 32 | int size = CALL_INSN_SIZE; |
| @@ -60,7 +61,7 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, void · 28 unmodified lines | ||
| 60 | 61 | if (memcmp(insn, code, size) == 0) |
| 61 | 62 | return; |
| 62 | 63 | |
| 63 | − if (unlikely(system_state == SYSTEM_BOOTING)) | |
| 64 | + if (system_state == SYSTEM_BOOTING || modinit) | |
| 64 | 65 | return text_poke_early(insn, code, size); |
| 65 | 66 | |
| 66 | 67 | text_poke_bp(insn, code, size, emulate); |
| @@ -114,12 +115,12 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail) · 47 unmodified lines | ||
| 114 | 115 | |
| 115 | 116 | if (tramp) { |
| 116 | 117 | __static_call_validate(tramp, true, true); |
| 117 | − __static_call_transform(tramp, __sc_insn(!func, true), func); | |
| 118 | + __static_call_transform(tramp, __sc_insn(!func, true), func, false); | |
| 118 | 119 | } |
| 119 | 120 | |
| 120 | 121 | if (IS_ENABLED(CONFIG_HAVE_STATIC_CALL_INLINE) && site) { |
| 121 | 122 | __static_call_validate(site, tail, false); |
| 122 | − __static_call_transform(site, __sc_insn(!func, tail), func); | |
| 123 | + __static_call_transform(site, __sc_insn(!func, tail), func, false); | |
| 123 | 124 | } |
| 124 | 125 | |
| 125 | 126 | mutex_unlock(&text_mutex); |
| @@ -145,8 +146,10 @@ bool __static_call_fixup(void *tramp, u8 op, void *dest) · 19 unmodified lines | ||
| 145 | 146 | return false; |
| 146 | 147 | } |
| 147 | 148 | |
| 149 | + mutex_lock(&text_mutex); | |
| 148 | 150 | if (op == RET_INSN_OPCODE || dest == &__x86_return_thunk) |
| 149 | − __static_call_transform(tramp, RET, NULL); | |
| 151 | + __static_call_transform(tramp, RET, NULL, true); | |
| 152 | + mutex_unlock(&text_mutex); | |
| 150 | 153 | |
| 151 | 154 | return true; |
| 152 | 155 | } |