mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
riscv: Disable preemption while handling PR_RISCV_CTX_SW_FENCEI_OFF
The icache will be flushed in switch_to() if force_icache_flush is true,
or in flush_icache_deferred() if icache_stale_mask is set. Between
setting force_icache_flush to false and calculating the new
icache_stale_mask, preemption needs to be disabled. There are two
reasons for this:
1. If CPU migration happens between force_icache_flush = false, and the
icache_stale_mask is set, an icache flush will not be emitted.
2. smp_processor_id() is used in set_icache_stale_mask() to mark the
current CPU as not needing another flush since a flush will have
happened either by userspace or by the kernel when performing the
migration. smp_processor_id() is currently called twice with preemption
enabled which causes a race condition. It allows
icache_stale_mask to be populated with inconsistent CPU ids.
Resolve these two issues by setting the icache_stale_mask before setting
force_icache_flush to false, and using get_cpu()/put_cpu() to obtain the
smp_processor_id().
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Fixes: 6b9391b581
("riscv: Include riscv_set_icache_flush_ctx prctl")
Link: https://lore.kernel.org/r/20240903-fix_fencei_optimization-v2-1-8025f20171fc@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
2840dadf0d
commit
7c1e5b9690
1 changed files with 6 additions and 6 deletions
|
@ -158,6 +158,7 @@ void __init riscv_init_cbo_blocksizes(void)
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void set_icache_stale_mask(void)
|
static void set_icache_stale_mask(void)
|
||||||
{
|
{
|
||||||
|
int cpu = get_cpu();
|
||||||
cpumask_t *mask;
|
cpumask_t *mask;
|
||||||
bool stale_cpu;
|
bool stale_cpu;
|
||||||
|
|
||||||
|
@ -168,10 +169,11 @@ static void set_icache_stale_mask(void)
|
||||||
* concurrently on different harts.
|
* concurrently on different harts.
|
||||||
*/
|
*/
|
||||||
mask = ¤t->mm->context.icache_stale_mask;
|
mask = ¤t->mm->context.icache_stale_mask;
|
||||||
stale_cpu = cpumask_test_cpu(smp_processor_id(), mask);
|
stale_cpu = cpumask_test_cpu(cpu, mask);
|
||||||
|
|
||||||
cpumask_setall(mask);
|
cpumask_setall(mask);
|
||||||
cpumask_assign_cpu(smp_processor_id(), mask, stale_cpu);
|
cpumask_assign_cpu(cpu, mask, stale_cpu);
|
||||||
|
put_cpu();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -239,14 +241,12 @@ int riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long scope)
|
||||||
case PR_RISCV_CTX_SW_FENCEI_OFF:
|
case PR_RISCV_CTX_SW_FENCEI_OFF:
|
||||||
switch (scope) {
|
switch (scope) {
|
||||||
case PR_RISCV_SCOPE_PER_PROCESS:
|
case PR_RISCV_SCOPE_PER_PROCESS:
|
||||||
current->mm->context.force_icache_flush = false;
|
|
||||||
|
|
||||||
set_icache_stale_mask();
|
set_icache_stale_mask();
|
||||||
|
current->mm->context.force_icache_flush = false;
|
||||||
break;
|
break;
|
||||||
case PR_RISCV_SCOPE_PER_THREAD:
|
case PR_RISCV_SCOPE_PER_THREAD:
|
||||||
current->thread.force_icache_flush = false;
|
|
||||||
|
|
||||||
set_icache_stale_mask();
|
set_icache_stale_mask();
|
||||||
|
current->thread.force_icache_flush = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Add table
Reference in a new issue