• Charlie Jenkins's avatar
    riscv: Disable preemption while handling PR_RISCV_CTX_SW_FENCEI_OFF · 7c1e5b96
    Charlie Jenkins authored
    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: default avatarCharlie Jenkins <charlie@rivosinc.com>
    Fixes: 6b9391b5 ("riscv: Include riscv_set_icache_flush_ctx prctl")
    Link: https://lore.kernel.org/r/20240903-fix_fencei_optimization-v2-1-8025f20171fc@rivosinc.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
    7c1e5b96
cacheflush.c 7.63 KB