Skip to content

Commit 51781ce

Browse files
SiFiveHollandpalmer-dabbelt
authored andcommitted
riscv: Pass patch_text() the length in bytes
patch_text_nosync() already handles an arbitrary length of code, so this removes a superfluous loop and reduces the number of icache flushes. Reviewed-by: Björn Töpel <[email protected]> Signed-off-by: Samuel Holland <[email protected]> Reviewed-by: Conor Dooley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 5080ca0 commit 51781ce

File tree

4 files changed

+20
-21
lines changed

4 files changed

+20
-21
lines changed

arch/riscv/include/asm/patch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
int patch_insn_write(void *addr, const void *insn, size_t len);
1010
int patch_text_nosync(void *addr, const void *insns, size_t len);
1111
int patch_text_set_nosync(void *addr, u8 c, size_t len);
12-
int patch_text(void *addr, u32 *insns, int ninsns);
12+
int patch_text(void *addr, u32 *insns, size_t len);
1313

1414
extern int riscv_patch_in_stop_machine;
1515

arch/riscv/kernel/patch.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
struct patch_insn {
2020
void *addr;
2121
u32 *insns;
22-
int ninsns;
22+
size_t len;
2323
atomic_t cpu_count;
2424
};
2525

@@ -239,14 +239,10 @@ NOKPROBE_SYMBOL(patch_text_nosync);
239239
static int patch_text_cb(void *data)
240240
{
241241
struct patch_insn *patch = data;
242-
unsigned long len;
243-
int i, ret = 0;
242+
int ret = 0;
244243

245244
if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
246-
for (i = 0; ret == 0 && i < patch->ninsns; i++) {
247-
len = GET_INSN_LENGTH(patch->insns[i]);
248-
ret = patch_insn_write(patch->addr + i * len, &patch->insns[i], len);
249-
}
245+
ret = patch_insn_write(patch->addr, patch->insns, patch->len);
250246
/*
251247
* Make sure the patching store is effective *before* we
252248
* increment the counter which releases all waiting CPUs
@@ -266,13 +262,13 @@ static int patch_text_cb(void *data)
266262
}
267263
NOKPROBE_SYMBOL(patch_text_cb);
268264

269-
int patch_text(void *addr, u32 *insns, int ninsns)
265+
int patch_text(void *addr, u32 *insns, size_t len)
270266
{
271267
int ret;
272268
struct patch_insn patch = {
273269
.addr = addr,
274270
.insns = insns,
275-
.ninsns = ninsns,
271+
.len = len,
276272
.cpu_count = ATOMIC_INIT(0),
277273
};
278274

arch/riscv/kernel/probes/kprobes.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
2424

2525
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
2626
{
27+
size_t len = GET_INSN_LENGTH(p->opcode);
2728
u32 insn = __BUG_INSN_32;
28-
unsigned long offset = GET_INSN_LENGTH(p->opcode);
2929

30-
p->ainsn.api.restore = (unsigned long)p->addr + offset;
30+
p->ainsn.api.restore = (unsigned long)p->addr + len;
3131

32-
patch_text_nosync(p->ainsn.api.insn, &p->opcode, 1);
33-
patch_text_nosync(p->ainsn.api.insn + offset, &insn, 1);
32+
patch_text_nosync(p->ainsn.api.insn, &p->opcode, len);
33+
patch_text_nosync(p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
3434
}
3535

3636
static void __kprobes arch_prepare_simulate(struct kprobe *p)
@@ -107,16 +107,18 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
107107
/* install breakpoint in text */
108108
void __kprobes arch_arm_kprobe(struct kprobe *p)
109109
{
110-
u32 insn = (p->opcode & __INSN_LENGTH_MASK) == __INSN_LENGTH_32 ?
111-
__BUG_INSN_32 : __BUG_INSN_16;
110+
size_t len = GET_INSN_LENGTH(p->opcode);
111+
u32 insn = len == 4 ? __BUG_INSN_32 : __BUG_INSN_16;
112112

113-
patch_text(p->addr, &insn, 1);
113+
patch_text(p->addr, &insn, len);
114114
}
115115

116116
/* remove breakpoint from text */
117117
void __kprobes arch_disarm_kprobe(struct kprobe *p)
118118
{
119-
patch_text(p->addr, &p->opcode, 1);
119+
size_t len = GET_INSN_LENGTH(p->opcode);
120+
121+
patch_text(p->addr, &p->opcode, len);
120122
}
121123

122124
void __kprobes arch_remove_kprobe(struct kprobe *p)

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "bpf_jit.h"
1717

1818
#define RV_FENTRY_NINSNS 2
19+
#define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4)
1920

2021
#define RV_REG_TCC RV_REG_A6
2122
#define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
@@ -672,7 +673,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
672673
if (ret)
673674
return ret;
674675

675-
if (memcmp(ip, old_insns, RV_FENTRY_NINSNS * 4))
676+
if (memcmp(ip, old_insns, RV_FENTRY_NBYTES))
676677
return -EFAULT;
677678

678679
ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
@@ -681,8 +682,8 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
681682

682683
cpus_read_lock();
683684
mutex_lock(&text_mutex);
684-
if (memcmp(ip, new_insns, RV_FENTRY_NINSNS * 4))
685-
ret = patch_text(ip, new_insns, RV_FENTRY_NINSNS);
685+
if (memcmp(ip, new_insns, RV_FENTRY_NBYTES))
686+
ret = patch_text(ip, new_insns, RV_FENTRY_NBYTES);
686687
mutex_unlock(&text_mutex);
687688
cpus_read_unlock();
688689

0 commit comments

Comments
 (0)