diff options
Diffstat (limited to 'arch/riscv/kernel/patch.c')
| -rw-r--r-- | arch/riscv/kernel/patch.c | 26 | 
1 files changed, 18 insertions, 8 deletions
| diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 4007563fb607..ab03732d06c4 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -89,6 +89,14 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)  	memset(waddr, c, len); +	/* +	 * We could have just patched a function that is about to be +	 * called so make sure we don't execute partially patched +	 * instructions by flushing the icache as soon as possible. +	 */ +	local_flush_icache_range((unsigned long)waddr, +				 (unsigned long)waddr + len); +  	patch_unmap(FIX_TEXT_POKE0);  	if (across_pages) @@ -135,6 +143,14 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)  	ret = copy_to_kernel_nofault(waddr, insn, len); +	/* +	 * We could have just patched a function that is about to be +	 * called so make sure we don't execute partially patched +	 * instructions by flushing the icache as soon as possible. +	 */ +	local_flush_icache_range((unsigned long)waddr, +				 (unsigned long)waddr + len); +  	patch_unmap(FIX_TEXT_POKE0);  	if (across_pages) @@ -189,9 +205,6 @@ int patch_text_set_nosync(void *addr, u8 c, size_t len)  	ret = patch_insn_set(tp, c, len); -	if (!ret) -		flush_icache_range((uintptr_t)tp, (uintptr_t)tp + len); -  	return ret;  }  NOKPROBE_SYMBOL(patch_text_set_nosync); @@ -224,9 +237,6 @@ int patch_text_nosync(void *addr, const void *insns, size_t len)  	ret = patch_insn_write(tp, insns, len); -	if (!ret) -		flush_icache_range((uintptr_t) tp, (uintptr_t) tp + len); -  	return ret;  }  NOKPROBE_SYMBOL(patch_text_nosync); @@ -253,9 +263,9 @@ static int patch_text_cb(void *data)  	} else {  		while (atomic_read(&patch->cpu_count) <= num_online_cpus())  			cpu_relax(); -	} -	local_flush_icache_all(); +		local_flush_icache_all(); +	}  	return ret;  } |