Re: [PATCH] RISC-V: KVM: Guard HFENCE range loops against overflow

Anup Patel <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,org.infradead.lists.kvm-riscv,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <CAAhSdy2J9ZAeNPPHcdyjjVs_ZLFbVeSjVXQ-nocmai0xyt0TYw@mail.gmail.com>
On Sat, Jul 18, 2026 at 10:08 AM Pengpeng Hou <[email protected]> wrote:
>
> The local HFENCE range helpers build the loop end with addr + size and
> then step through the range by the requested page order. If addr + size
> wraps, a small range near the top of the address space can be treated as
> empty and skip the intended fence. The final loop step can also wrap
> before the loop condition is evaluated again.
>
> Treat wrapped ranges conservatively as full-range HFENCE requests and stop
> each bounded loop before the next step can wrap past the computed end. This
> keeps the existing large-range fallback and only changes local GVMA/VVMA
> range construction.
>
> Fixes: 2415e46e3a9a ("RISC-V: KVM: Introduce range based local HFENCE functions")
> Signed-off-by: Pengpeng Hou <[email protected]>

LGTM.

Reviewed-by: Anup Patel <[email protected]>

Queued this patch for Linux-7.3

Thanks,
Anup


> ---
>  arch/riscv/kvm/tlb.c | 71 ++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 59 insertions(+), 12 deletions(-)
>
> diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c
> index 993b25ea94d67..b0c83e3ccc15a 100644
> --- a/arch/riscv/kvm/tlb.c
> +++ b/arch/riscv/kvm/tlb.c
> @@ -8,6 +8,7 @@
>  #include <linux/errno.h>
>  #include <linux/err.h>
>  #include <linux/module.h>
> +#include <linux/overflow.h>
>  #include <linux/smp.h>
>  #include <linux/kvm_host.h>
>  #include <asm/cacheflush.h>
> @@ -24,7 +25,12 @@ void kvm_riscv_local_hfence_gvma_vmid_gpa(unsigned long vmid,
>                                           gpa_t gpa, gpa_t gpsz,
>                                           unsigned long order)
>  {
> -       gpa_t pos;
> +       gpa_t end, pos, step = BIT(order);
> +
> +       if (check_add_overflow(gpa, gpsz, &end)) {
> +               kvm_riscv_local_hfence_gvma_vmid_all(vmid);
> +               return;
> +       }
>
>         if (PTRS_PER_PTE < (gpsz >> order)) {
>                 kvm_riscv_local_hfence_gvma_vmid_all(vmid);
> @@ -33,14 +39,20 @@ void kvm_riscv_local_hfence_gvma_vmid_gpa(unsigned long vmid,
>
>         if (has_svinval()) {
>                 asm volatile (SFENCE_W_INVAL() ::: "memory");
> -               for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
> +               for (pos = gpa; pos < end; pos += step) {
>                         asm volatile (HINVAL_GVMA(%0, %1)
>                         : : "r" (pos >> 2), "r" (vmid) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>                 asm volatile (SFENCE_INVAL_IR() ::: "memory");
>         } else {
> -               for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
> +               for (pos = gpa; pos < end; pos += step) {
>                         asm volatile (HFENCE_GVMA(%0, %1)
>                         : : "r" (pos >> 2), "r" (vmid) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>         }
>  }
>
> @@ -52,7 +64,12 @@ void kvm_riscv_local_hfence_gvma_vmid_all(unsigned long vmid)
>  void kvm_riscv_local_hfence_gvma_gpa(gpa_t gpa, gpa_t gpsz,
>                                      unsigned long order)
>  {
> -       gpa_t pos;
> +       gpa_t end, pos, step = BIT(order);
> +
> +       if (check_add_overflow(gpa, gpsz, &end)) {
> +               kvm_riscv_local_hfence_gvma_all();
> +               return;
> +       }
>
>         if (PTRS_PER_PTE < (gpsz >> order)) {
>                 kvm_riscv_local_hfence_gvma_all();
> @@ -61,14 +78,20 @@ void kvm_riscv_local_hfence_gvma_gpa(gpa_t gpa, gpa_t gpsz,
>
>         if (has_svinval()) {
>                 asm volatile (SFENCE_W_INVAL() ::: "memory");
> -               for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
> +               for (pos = gpa; pos < end; pos += step) {
>                         asm volatile(HINVAL_GVMA(%0, zero)
>                         : : "r" (pos >> 2) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>                 asm volatile (SFENCE_INVAL_IR() ::: "memory");
>         } else {
> -               for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
> +               for (pos = gpa; pos < end; pos += step) {
>                         asm volatile(HFENCE_GVMA(%0, zero)
>                         : : "r" (pos >> 2) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>         }
>  }
>
> @@ -83,7 +106,13 @@ void kvm_riscv_local_hfence_vvma_asid_gva(unsigned long vmid,
>                                           unsigned long gvsz,
>                                           unsigned long order)
>  {
> -       unsigned long pos, hgatp;
> +       unsigned long end, pos, step = BIT(order);
> +       unsigned long hgatp;
> +
> +       if (check_add_overflow(gva, gvsz, &end)) {
> +               kvm_riscv_local_hfence_vvma_asid_all(vmid, asid);
> +               return;
> +       }
>
>         if (PTRS_PER_PTE < (gvsz >> order)) {
>                 kvm_riscv_local_hfence_vvma_asid_all(vmid, asid);
> @@ -94,14 +123,20 @@ void kvm_riscv_local_hfence_vvma_asid_gva(unsigned long vmid,
>
>         if (has_svinval()) {
>                 asm volatile (SFENCE_W_INVAL() ::: "memory");
> -               for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
> +               for (pos = gva; pos < end; pos += step) {
>                         asm volatile(HINVAL_VVMA(%0, %1)
>                         : : "r" (pos), "r" (asid) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>                 asm volatile (SFENCE_INVAL_IR() ::: "memory");
>         } else {
> -               for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
> +               for (pos = gva; pos < end; pos += step) {
>                         asm volatile(HFENCE_VVMA(%0, %1)
>                         : : "r" (pos), "r" (asid) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>         }
>
>         csr_write(CSR_HGATP, hgatp);
> @@ -123,7 +158,13 @@ void kvm_riscv_local_hfence_vvma_gva(unsigned long vmid,
>                                      unsigned long gva, unsigned long gvsz,
>                                      unsigned long order)
>  {
> -       unsigned long pos, hgatp;
> +       unsigned long end, pos, step = BIT(order);
> +       unsigned long hgatp;
> +
> +       if (check_add_overflow(gva, gvsz, &end)) {
> +               kvm_riscv_local_hfence_vvma_all(vmid);
> +               return;
> +       }
>
>         if (PTRS_PER_PTE < (gvsz >> order)) {
>                 kvm_riscv_local_hfence_vvma_all(vmid);
> @@ -134,14 +175,20 @@ void kvm_riscv_local_hfence_vvma_gva(unsigned long vmid,
>
>         if (has_svinval()) {
>                 asm volatile (SFENCE_W_INVAL() ::: "memory");
> -               for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
> +               for (pos = gva; pos < end; pos += step) {
>                         asm volatile(HINVAL_VVMA(%0, zero)
>                         : : "r" (pos) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>                 asm volatile (SFENCE_INVAL_IR() ::: "memory");
>         } else {
> -               for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
> +               for (pos = gva; pos < end; pos += step) {
>                         asm volatile(HFENCE_VVMA(%0, zero)
>                         : : "r" (pos) : "memory");
> +                       if (end - pos <= step)
> +                               break;
> +               }
>         }
>
>         csr_write(CSR_HGATP, hgatp);
> --
> 2.43.0
>

_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.