Re: [PATCH] KVM: riscv: Fix NACL hfence entry update order

From: Anup Patel

Date: Thu Sep 10 2026 - 10:54:31 EST


On Wed, Aug 26, 2026 at 1:20 PM Zongmin Zhou <min_halo@xxxxxxx> wrote:
>
> From: Zongmin Zhou <zhouzongmin@xxxxxxxxxx>
>
> The SBI v3.0 specification (section 15.1.2) requires a nested HFENCE
> entry to be populated as follows:
> 1) find an unused entry with Config.Pending == 0
> 2) update the Page_Number and Page_Count words
> 3) update the Config word with Config.Pending set
>
> __kvm_riscv_nacl_hfence() writes the Config word first, so the SBI
> implementation (or NACL hardware) can observe a pending entry with
> pnum/pcount values left over from the previous use of that entry,
> resulting in incorrect TLB flush ranges.
>
> Write pnum and pcount first and the Config word last. Since the
> consumer is an external agent on coherent shared memory, use
> WRITE_ONCE() to stop the compiler from reordering the stores and
> smp_wmb() to make the parameter words globally visible before the
> Pending bit is set.
>
> Fixes: d466c19cead5 ("RISC-V: KVM: Add common nested acceleration support")
> Signed-off-by: Zongmin Zhou <zhouzongmin@xxxxxxxxxx>

LGTM.

Reviewed-by: Anup Patel <anup@xxxxxxxxxxxxxx>

Queued this patch as fix for Linux-7.3-rcX

Thanks,
Anup

> ---
> arch/riscv/kvm/nacl.c | 20 ++++++++++++++++----
> 1 file changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kvm/nacl.c b/arch/riscv/kvm/nacl.c
> index 9aff03c4f667..a5cda9a65156 100644
> --- a/arch/riscv/kvm/nacl.c
> +++ b/arch/riscv/kvm/nacl.c
> @@ -42,12 +42,24 @@ void __kvm_riscv_nacl_hfence(void *shmem,
> }
> }
>
> - entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
> - *entp = cpu_to_lelong(control);
> + /*
> + * Per SBI v3.0 section 15.1.2, the Page_Number and Page_Count
> + * words must be updated before the Config word with its Pending
> + * bit set. WRITE_ONCE() stops the compiler from reordering the
> + * stores and smp_wmb() makes the parameter words globally
> + * visible to the SBI implementation (or NACL hardware) before
> + * the Pending bit is set.
> + */
> entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PNUM(i);
> - *entp = cpu_to_lelong(page_num);
> + WRITE_ONCE(*entp, cpu_to_lelong(page_num));
> entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_PCOUNT(i);
> - *entp = cpu_to_lelong(page_count);
> + WRITE_ONCE(*entp, cpu_to_lelong(page_count));
> +
> + /* Ensure the parameter words are visible before the Pending bit */
> + smp_wmb();
> +
> + entp = shmem + SBI_NACL_SHMEM_HFENCE_ENTRY_CONFIG(i);
> + WRITE_ONCE(*entp, cpu_to_lelong(control));
> }
>
> int kvm_riscv_nacl_enable(void)
> --
> 2.34.1
>
>
> No virus found
> Checked by Hillstone Network AntiVirus
>