Skip to content

Commit 7c1e5b9

Browse files
charlie-rivospalmer-dabbelt
authored andcommitted
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: 6b9391b ("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>
1 parent 2840dad commit 7c1e5b9

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

arch/riscv/mm/cacheflush.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ void __init riscv_init_cbo_blocksizes(void)
158158
#ifdef CONFIG_SMP
159159
static void set_icache_stale_mask(void)
160160
{
161+
int cpu = get_cpu();
161162
cpumask_t *mask;
162163
bool stale_cpu;
163164

@@ -168,10 +169,11 @@ static void set_icache_stale_mask(void)
168169
* concurrently on different harts.
169170
*/
170171
mask = &current->mm->context.icache_stale_mask;
171-
stale_cpu = cpumask_test_cpu(smp_processor_id(), mask);
172+
stale_cpu = cpumask_test_cpu(cpu, mask);
172173

173174
cpumask_setall(mask);
174-
cpumask_assign_cpu(smp_processor_id(), mask, stale_cpu);
175+
cpumask_assign_cpu(cpu, mask, stale_cpu);
176+
put_cpu();
175177
}
176178
#endif
177179

@@ -239,14 +241,12 @@ int riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long scope)
239241
case PR_RISCV_CTX_SW_FENCEI_OFF:
240242
switch (scope) {
241243
case PR_RISCV_SCOPE_PER_PROCESS:
242-
current->mm->context.force_icache_flush = false;
243-
244244
set_icache_stale_mask();
245+
current->mm->context.force_icache_flush = false;
245246
break;
246247
case PR_RISCV_SCOPE_PER_THREAD:
247-
current->thread.force_icache_flush = false;
248-
249248
set_icache_stale_mask();
249+
current->thread.force_icache_flush = false;
250250
break;
251251
default:
252252
return -EINVAL;

0 commit comments

Comments
 (0)