[tech-speculation-barriers] [PATCH] riscv, bpf: Emit fence.i for BPF_NOSPEC

Stefan O'Rear sorear at fastmail.com
Thu Jan 8 21:36:48 PST 2026


On Thu, Jan 8, 2026, at 10:37 PM, Bo Gan via lists.riscv.org wrote:
> Hi Lukas,
>
> Stefan and I have some doubts on fence.i's effectiveness as speculation
> barrier. Flushing entire local instruction cache and instruction pipeline
> is not absolutely necessary on impl having coherent I/D caches. Quoting
> from Unprivileged SPEC ver. 20250508:
>
> "The FENCE.I instruction was designed to support a wide variety of
>   implementations. A simple implementation can flush the local instruction
>   cache and the instruction pipeline when the FENCE.I is executed. A more
>   complex implementation might snoop the instruction (data) cache on every
>   data (instruction) cache miss, or use an inclusive unified private L2
>   cache to invalidate lines from the primary instruction cache when they
>   are being written by a local store instruction. If instruction and data
>   caches are kept coherent in this way, or if the memory system consists of
>   only uncached RAMs, then just the fetch pipeline needs to be flushed at a
>   FENCE.I"

Note that this is non-normative text and the actual range of allowed
implementations is wider than this.

I'm particularly concerned that the security property we appear to need (I am
more familiar with u-arch vulnerabilities than BPF ISA details) is an _issue
barrier_, but correctness for FENCE.I as currently specified only requires
a _retirement barrier_.

FENCE.I requires that instructions after the FENCE.I in program order not
retire unless the hart can verify that they were not overwritten in memory
between the time they were fetched and the memory-order point of the FENCE.I.
Simple implementations will probably achieve this by re-fetching and
preventing retirement of all instructions after the FENCE.I, but if the
instructions speculatively execute then it is not useful for a Spectre v1
barrier. Issuing an instruction which cannot possibly retire wastes energy,
but if FENCE.I is assumed to be an extremely rare operation this may not be
a priority.

Particularly complex implementations can go as far as to treat FENCE.I as a
no-op if they snoop the reorder buffer as well as the instruction cache.

> There's the question on overhead, too. Perhaps there's a more accurate and
> lightweight insn available? I'm not an expert in u-arch. My gut feeling is
> that we should not be dependent on specific impl's behavior and the riscv
> SPEC should provide guidelines on speculation barrier instructions and how
> to use them. Thus, I'm forwarding this to the Speculation Barriers Task-
> Group, which I hope should be the perfect place to discuss such kind of
> issues. @Speculation Barriers TG Please share your thoughts. Note that we
> are dealing with existing HW, so we expect something to be working with
> current SPEC and actual silicon. I'd be happy if I'm proven wrong, and
> fence.i can actually be a speculation barrier. That's also a relief. Thank
> you everyone.

The JH7110 has 512 I-cache lines per core, all of which must be invalidated
on a FENCE.I. I'm not sure how many cycles that takes for the invalidation,
but some fraction of those will subsequently be needed before they would
otherwise be evicted, which could add up to several thousand cycles of
overhead depending on the cache miss latency, for a BPF program with a single
BPF_NOSPEC. Compared to roughly one thousand cycles for a kernel entry and
exit, it may be more practical to disable BPF and rely on userspace event
processing for affected hardware, even if FENCE.I is otherwise useful as a
speculation barrier.

I don't think it's possible to define a set of speculation barriers that apply
to all possible existing and future hardware with the current specifications,
because the ratified specifications cannot be changed and other than Zkt/Zvkt
do not constrain uarch side channels.

The TG is defining a new specification which includes semantically rich
barriers that can have optimal overhead on new hardware. If we find a set of
speculation barriers that work on some or (optimistically) all existing
hardware, we would need to define a retroactive specification which documents
that behavior, much like Zkt/Zvkt or many of the extensions defined in the
profiles specification.

> BTW, per SPEC:
>
>   "The FENCE.I only synchronizes the local hart, and the OS can reschedule
>    the user hart to a different physical hart after the FENCE.I. This would
>    require the OS to execute an additional FENCE.I as part of every context
>    migration"
>
> fence.i is local. I know some core does a broadcast and try to make it a
> global fence.i, but this is not required by the SPEC.

The speculation fences that are used on other architectures are all core-local
operations so I don't think this is, itself, a problem.

-s

> Bo
>
> On 12/28/25 09:37, Lukas Gerlach wrote:
>> The BPF verifier inserts BPF_NOSPEC instructions to create speculation
>> barriers. However, the RISC-V BPF JIT emits nothing for this
>> instruction, leaving programs vulnerable to speculative execution
>> attacks.
>> 
>> Originally, BPF_NOSPEC was used only for Spectre v4 mitigation, programs
>> containing potential Spectre v1 gadgets were rejected by the verifier.
>> With the VeriFence changes, the verifier now accepts these
>> programs and inserts BPF_NOSPEC barriers for Spectre v1 mitigation as
>> well. On RISC-V, this means programs that were previously rejected are
>> now accepted but left unprotected against both v1 and v4 attacks.
>> 
>> RISC-V lacks a dedicated speculation barrier instruction.
>> This patch uses the fence.i instruction as a stopgap solution.
>> However an alternative and safer approach would be to reject vulnerable bpf
>> programs again.
>> 
>> Fixes: f5e81d111750 ("bpf: Introduce BPF nospec instruction for mitigating Spectre v4")
>> Fixes: 5fcf896efe28 ("Merge branch 'bpf-mitigate-spectre-v1-using-barriers'")
>> Signed-off-by: Lukas Gerlach <lukas.gerlach at cispa.de>
>> ---
>>   arch/riscv/net/bpf_jit.h        | 10 ++++++++++
>>   arch/riscv/net/bpf_jit_comp32.c |  6 +++++-
>>   arch/riscv/net/bpf_jit_comp64.c |  6 +++++-
>>   3 files changed, 20 insertions(+), 2 deletions(-)
>> 
>> diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
>> index 632ced07bca4..e70b3bc19206 100644
>> --- a/arch/riscv/net/bpf_jit.h
>> +++ b/arch/riscv/net/bpf_jit.h
>> @@ -619,6 +619,16 @@ static inline void emit_fence_rw_rw(struct rv_jit_context *ctx)
>>   	emit(rv_fence(0x3, 0x3), ctx);
>>   }
>>   
>> +static inline u32 rv_fence_i(void)
>> +{
>> +	return rv_i_insn(0, 0, 1, 0, 0x0f);
>> +}
>> +
>> +static inline void emit_fence_i(struct rv_jit_context *ctx)
>> +{
>> +	emit(rv_fence_i(), ctx);
>> +}
>> +
>>   static inline u32 rv_nop(void)
>>   {
>>   	return rv_i_insn(0, 0, 0, 0, 0x13);
>> diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c
>> index 592dd86fbf81..d9a6f55a7e8e 100644
>> --- a/arch/riscv/net/bpf_jit_comp32.c
>> +++ b/arch/riscv/net/bpf_jit_comp32.c
>> @@ -1248,8 +1248,12 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
>>   			return -1;
>>   		break;
>>   
>> -	/* speculation barrier */
>> +	/*
>> +	 * Speculation barrier using fence.i for pipeline serialization.
>> +	 * RISC-V lacks a dedicated speculation barrier instruction.
>> +	 */
>>   	case BPF_ST | BPF_NOSPEC:
>> +		emit_fence_i(ctx);
>>   		break;
>>   
>>   	case BPF_ST | BPF_MEM | BPF_B:
>> diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
>> index 45cbc7c6fe49..fabafbebde0c 100644
>> --- a/arch/riscv/net/bpf_jit_comp64.c
>> +++ b/arch/riscv/net/bpf_jit_comp64.c
>> @@ -1864,8 +1864,12 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
>>   		break;
>>   	}
>>   
>> -	/* speculation barrier */
>> +	/*
>> +	 * Speculation barrier using fence.i for pipeline serialization.
>> +	 * RISC-V lacks a dedicated speculation barrier instruction.
>> +	 */
>>   	case BPF_ST | BPF_NOSPEC:
>> +		emit_fence_i(ctx);
>>   		break;
>>   
>>   	/* ST: *(size *)(dst + off) = imm */
>
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#19): 
> https://lists.riscv.org/g/tech-speculation-barriers/message/19
> Mute This Topic: https://lists.riscv.org/mt/117170030/7725087
> Group Owner: tech-speculation-barriers+owner at lists.riscv.org
> Unsubscribe: 
> https://lists.riscv.org/g/tech-speculation-barriers/leave/14814957/7725087/301854996/xyzzy 
> [sorear at fastmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-



More information about the linux-riscv mailing list