* [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 7:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses that would be truncated when stored in a
32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
address. No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 3 ++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..76cceecee5ab 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 7:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses that would be truncated when stored in a
32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
address. No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 3 ++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..76cceecee5ab 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 7:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses that would be truncated when stored in a
32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
address. No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 3 ++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..76cceecee5ab 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
2026-07-29 7:07 ` Bingyu.Xian
(?)
(?)
@ 2026-07-29 7:17 ` sashiko-bot
-1 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-29 7:17 UTC (permalink / raw)
To: Bingyu.Xian; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The patch fails to resolve the 34-bit GPA truncation on RV32 because the address calculation `(trap->htval << 2)` is still evaluated using 32-bit arithmetic before assignment.
--
--- Patch [1]: [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types ---
commit 9da8ae12634bbc92cd912d48c6458250997cb454
Author: Bingyu.Xian <shanbeeyoo@gmail.com>
RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
This commit updates the G-stage page fault path to treat -EEXIST from
kvm_riscv_gstage_map_page() as a success, aligning RISC-V with other
architectures. It also updates the type of vma_pageshift to unsigned int
and fault_addr to gpa_t, intending to prevent 34-bit guest physical address
truncation on RV32.
[ ... ]
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 6c8530b9f29ed..76cceecee5aba 100644
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
> {
> struct kvm_gstage_mapping host_map;
> struct kvm_memory_slot *memslot;
> - unsigned long hva, fault_addr;
> + unsigned long hva;
> + gpa_t fault_addr;
[Severity: High]
This is a pre-existing issue, but does the calculation for fault_addr still
truncate the address on RV32 before this assignment?
The commit message notes this type change is meant to prevent 34-bit guest
physical addresses from being truncated. However, looking further down in
gstage_page_fault(), the actual calculation is:
fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
Because trap->htval is an unsigned long, the shift (trap->htval << 2) is
evaluated as a 32-bit operation on RV32. This discards the upper bits of
the 34-bit guest physical address before the final result is widened and
stored in the new 64-bit gpa_t variable.
Should trap->htval be explicitly cast to gpa_t or u64 before the shift
operation to ensure the higher bits are preserved?
> bool writable;
> gfn_t gfn;
> int ret;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260729070749.730218-1-shanbeeyoo@gmail.com?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
2026-07-29 7:07 ` Bingyu.Xian
(?)
@ 2026-07-29 7:52 ` Bingyu.Xian
-1 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:52 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses. fault_addr is widened to gpa_t (u64) to
hold the full address, and the shift reconstructing it,
(trap->htval << 2), is cast to gpa_t before the shift: htval is
unsigned long, so on RV32 the shift would otherwise be evaluated in
32-bit arithmetic and drop bits 32/33 before the result is widened.
No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
Changes since v1:
- Cast trap->htval to gpa_t before the <<2 shift so the 34-bit guest
physical address is not truncated by 32-bit arithmetic on RV32. v1
only widened the destination (fault_addr -> gpa_t); the shift itself
still dropped bits 32/33 before the result was widened.
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 7:52 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:52 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses. fault_addr is widened to gpa_t (u64) to
hold the full address, and the shift reconstructing it,
(trap->htval << 2), is cast to gpa_t before the shift: htval is
unsigned long, so on RV32 the shift would otherwise be evaluated in
32-bit arithmetic and drop bits 32/33 before the result is widened.
No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
Changes since v1:
- Cast trap->htval to gpa_t before the <<2 shift so the 34-bit guest
physical address is not truncated by 32-bit arithmetic on RV32. v1
only widened the destination (fault_addr -> gpa_t); the shift itself
still dropped bits 32/33 before the result was widened.
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 7:52 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 7:52 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, Bingyu Xian
Two small fixes to the RISC-V G-stage page fault path, both suggested
during review of the in-progress KVM Userfault port.
1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
When a concurrent vCPU installs the same G-stage mapping while we
are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating
it as one: printing "Failed to map in G-stage" to dmesg and
propagating -EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets
kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
case: with ret normalized to 0 the regular release path is correct.
2. Clean up fault path types.
- vma_pageshift: short -> unsigned int. Bit widths and shift counts
conventionally use unsigned int in the kernel.
- fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
guest physical addresses. fault_addr is widened to gpa_t (u64) to
hold the full address, and the shift reconstructing it,
(trap->htval << 2), is cast to gpa_t before the shift: htval is
unsigned long, so on RV32 the shift would otherwise be evaluated in
32-bit arithmetic and drop bits 32/33 before the result is widened.
No functional change on RV64.
These type changes are in preparation for sharing a common
struct kvm_page_fault across architectures, as requested during
review.
No functional change on RV64 beyond silencing the spurious -EEXIST.
These are independent fixes with no dependencies; they can be merged
on their own. The KVM_MEM_USERFAULT port that motivated them will be
sent separately as an RFC once the generic userfault series lands.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
Changes since v1:
- Cast trap->htval to gpa_t before the <<2 shift so the 34-bit guest
physical address is not truncated by 32-bit arithmetic on RV32. v1
only widened the destination (fault_addr -> gpa_t); the shift itself
still dropped bits 32/33 before the result was widened.
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
2026-07-29 7:52 ` Bingyu.Xian
(?)
(?)
@ 2026-07-29 8:03 ` sashiko-bot
-1 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-29 8:03 UTC (permalink / raw)
To: Bingyu.Xian; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The widened 34-bit `fault_addr` on RV32 is silently truncated back to 32 bits when passed to MMIO load/store handlers.
--
--- Patch [1]: [PATCH v2] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types ---
commit 0f1ae40b2c79a54468668b54d25a4ee2ead28522
Author: Bingyu.Xian <shanbeeyoo@gmail.com>
RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
This commit treats -EEXIST from kvm_riscv_gstage_map_page() as a quiet
success, aligning RISC-V with x86 and arm64. It also widens fault_addr to
gpa_t to prevent 34-bit guest physical addresses from being truncated by
32-bit arithmetic on RV32.
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 6c8530b9f29ed..28cf9b27bb07c 100644
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
> {
> struct kvm_gstage_mapping host_map;
> struct kvm_memory_slot *memslot;
> - unsigned long hva, fault_addr;
> + unsigned long hva;
> + gpa_t fault_addr;
> bool writable;
> gfn_t gfn;
> int ret;
>
> - fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
> + fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
[Severity: High]
This is a pre-existing issue, but since the patch explicitly widens
fault_addr to gpa_t to hold 34-bit addresses on RV32, will this address
be truncated back to 32 bits when passed to the MMIO handlers later in
this function?
Looking at arch/riscv/kvm/vcpu_insn.c, the handlers still expect an
unsigned long:
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
unsigned long fault_addr,
unsigned long htinst)
and
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
unsigned long fault_addr,
unsigned long htinst)
Does this mean MMIO accesses to addresses above 4GB on RV32 will still be
silently aliased into the lower 4GB when gstage_page_fault() calls these
handlers?
> gfn = fault_addr >> PAGE_SHIFT;
> memslot = gfn_to_memslot(vcpu->kvm, gfn);
> hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260729075230.743030-1-shanbeeyoo@gmail.com?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
2026-07-29 7:07 ` Bingyu.Xian
(?)
@ 2026-07-29 8:05 ` Anup Patel
-1 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2026-07-29 8:05 UTC (permalink / raw)
To: Bingyu.Xian
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou
On Wed, Jul 29, 2026 at 12:37 PM Bingyu.Xian <shanbeeyoo@gmail.com> wrote:
>
> Two small fixes to the RISC-V G-stage page fault path, both suggested
> during review of the in-progress KVM Userfault port.
>
> 1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
>
> When a concurrent vCPU installs the same G-stage mapping while we
> are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
> is not an error -- the page is correctly mapped and the faulting
> vCPU can simply retry the guest instruction -- but KVM was treating
> it as one: printing "Failed to map in G-stage" to dmesg and
> propagating -EEXIST all the way to userspace.
>
> Align RISC-V with x86 and arm64, which already swallow -EEXIST in
> their respective fault handlers. This also lets
> kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
> case: with ret normalized to 0 the regular release path is correct.
>
> 2. Clean up fault path types.
>
> - vma_pageshift: short -> unsigned int. Bit widths and shift counts
> conventionally use unsigned int in the kernel.
>
> - fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
> guest physical addresses that would be truncated when stored in a
> 32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
> address. No functional change on RV64.
Don't squash multiple changes into one patch.
Create separate patches with appropriate Fixes tags.
Regards,
Anup
>
> These type changes are in preparation for sharing a common
> struct kvm_page_fault across architectures, as requested during
> review.
>
> No functional change on RV64 beyond silencing the spurious -EEXIST.
>
> These are independent fixes with no dependencies; they can be merged
> on their own. The KVM_MEM_USERFAULT port that motivated them will be
> sent separately as an RFC once the generic userfault series lands.
>
> Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
> Assisted-by: YuanSheng: deepseek-v4-pro
> Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
> ---
> arch/riscv/kvm/mmu.c | 8 +++++---
> arch/riscv/kvm/vcpu_exit.c | 3 ++-
> 2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 8a0aa5e0e216..d2a06a54be17 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> kvm_pfn_t hfn;
> bool is_hugetlb;
> bool writable;
> - short vma_pageshift;
> + unsigned int vma_pageshift;
> gfn_t gfn = gpa >> PAGE_SHIFT;
> struct vm_area_struct *vma;
> struct kvm *kvm = vcpu->kvm;
> @@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> vma_pagesize, true, true, out_map);
> }
>
> - if (ret)
> + if (ret == -EEXIST)
> + ret = 0;
> + else if (ret)
> kvm_err("Failed to map in G-stage\n");
>
> out_unlock:
> - kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
> + kvm_release_faultin_page(kvm, page, ret, writable);
> write_unlock(&kvm->mmu_lock);
> return ret;
> }
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 6c8530b9f29e..76cceecee5ab 100644
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
> {
> struct kvm_gstage_mapping host_map;
> struct kvm_memory_slot *memslot;
> - unsigned long hva, fault_addr;
> + unsigned long hva;
> + gpa_t fault_addr;
> bool writable;
> gfn_t gfn;
> int ret;
> --
> 2.54.0
>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 8:05 ` Anup Patel
0 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2026-07-29 8:05 UTC (permalink / raw)
To: Bingyu.Xian
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou
On Wed, Jul 29, 2026 at 12:37 PM Bingyu.Xian <shanbeeyoo@gmail.com> wrote:
>
> Two small fixes to the RISC-V G-stage page fault path, both suggested
> during review of the in-progress KVM Userfault port.
>
> 1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
>
> When a concurrent vCPU installs the same G-stage mapping while we
> are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
> is not an error -- the page is correctly mapped and the faulting
> vCPU can simply retry the guest instruction -- but KVM was treating
> it as one: printing "Failed to map in G-stage" to dmesg and
> propagating -EEXIST all the way to userspace.
>
> Align RISC-V with x86 and arm64, which already swallow -EEXIST in
> their respective fault handlers. This also lets
> kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
> case: with ret normalized to 0 the regular release path is correct.
>
> 2. Clean up fault path types.
>
> - vma_pageshift: short -> unsigned int. Bit widths and shift counts
> conventionally use unsigned int in the kernel.
>
> - fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
> guest physical addresses that would be truncated when stored in a
> 32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
> address. No functional change on RV64.
Don't squash multiple changes into one patch.
Create separate patches with appropriate Fixes tags.
Regards,
Anup
>
> These type changes are in preparation for sharing a common
> struct kvm_page_fault across architectures, as requested during
> review.
>
> No functional change on RV64 beyond silencing the spurious -EEXIST.
>
> These are independent fixes with no dependencies; they can be merged
> on their own. The KVM_MEM_USERFAULT port that motivated them will be
> sent separately as an RFC once the generic userfault series lands.
>
> Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
> Assisted-by: YuanSheng: deepseek-v4-pro
> Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
> ---
> arch/riscv/kvm/mmu.c | 8 +++++---
> arch/riscv/kvm/vcpu_exit.c | 3 ++-
> 2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 8a0aa5e0e216..d2a06a54be17 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> kvm_pfn_t hfn;
> bool is_hugetlb;
> bool writable;
> - short vma_pageshift;
> + unsigned int vma_pageshift;
> gfn_t gfn = gpa >> PAGE_SHIFT;
> struct vm_area_struct *vma;
> struct kvm *kvm = vcpu->kvm;
> @@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> vma_pagesize, true, true, out_map);
> }
>
> - if (ret)
> + if (ret == -EEXIST)
> + ret = 0;
> + else if (ret)
> kvm_err("Failed to map in G-stage\n");
>
> out_unlock:
> - kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
> + kvm_release_faultin_page(kvm, page, ret, writable);
> write_unlock(&kvm->mmu_lock);
> return ret;
> }
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 6c8530b9f29e..76cceecee5ab 100644
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
> {
> struct kvm_gstage_mapping host_map;
> struct kvm_memory_slot *memslot;
> - unsigned long hva, fault_addr;
> + unsigned long hva;
> + gpa_t fault_addr;
> bool writable;
> gfn_t gfn;
> int ret;
> --
> 2.54.0
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types
@ 2026-07-29 8:05 ` Anup Patel
0 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2026-07-29 8:05 UTC (permalink / raw)
To: Bingyu.Xian
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou
On Wed, Jul 29, 2026 at 12:37 PM Bingyu.Xian <shanbeeyoo@gmail.com> wrote:
>
> Two small fixes to the RISC-V G-stage page fault path, both suggested
> during review of the in-progress KVM Userfault port.
>
> 1. Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet success.
>
> When a concurrent vCPU installs the same G-stage mapping while we
> are waiting for mmu_lock, gstage_map_page() returns -EEXIST. This
> is not an error -- the page is correctly mapped and the faulting
> vCPU can simply retry the guest instruction -- but KVM was treating
> it as one: printing "Failed to map in G-stage" to dmesg and
> propagating -EEXIST all the way to userspace.
>
> Align RISC-V with x86 and arm64, which already swallow -EEXIST in
> their respective fault handlers. This also lets
> kvm_release_faultin_page() drop its "ret && ret != -EEXIST" special
> case: with ret normalized to 0 the regular release path is correct.
>
> 2. Clean up fault path types.
>
> - vma_pageshift: short -> unsigned int. Bit widths and shift counts
> conventionally use unsigned int in the kernel.
>
> - fault_addr: unsigned long -> gpa_t. RV32 with Sv32x4 has 34-bit
> guest physical addresses that would be truncated when stored in a
> 32-bit unsigned long; gpa_t is u64 on RV32 and holds the full
> address. No functional change on RV64.
Don't squash multiple changes into one patch.
Create separate patches with appropriate Fixes tags.
Regards,
Anup
>
> These type changes are in preparation for sharing a common
> struct kvm_page_fault across architectures, as requested during
> review.
>
> No functional change on RV64 beyond silencing the spurious -EEXIST.
>
> These are independent fixes with no dependencies; they can be merged
> on their own. The KVM_MEM_USERFAULT port that motivated them will be
> sent separately as an RFC once the generic userfault series lands.
>
> Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
> Assisted-by: YuanSheng: deepseek-v4-pro
> Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
> Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
> ---
> arch/riscv/kvm/mmu.c | 8 +++++---
> arch/riscv/kvm/vcpu_exit.c | 3 ++-
> 2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
> index 8a0aa5e0e216..d2a06a54be17 100644
> --- a/arch/riscv/kvm/mmu.c
> +++ b/arch/riscv/kvm/mmu.c
> @@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> kvm_pfn_t hfn;
> bool is_hugetlb;
> bool writable;
> - short vma_pageshift;
> + unsigned int vma_pageshift;
> gfn_t gfn = gpa >> PAGE_SHIFT;
> struct vm_area_struct *vma;
> struct kvm *kvm = vcpu->kvm;
> @@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
> vma_pagesize, true, true, out_map);
> }
>
> - if (ret)
> + if (ret == -EEXIST)
> + ret = 0;
> + else if (ret)
> kvm_err("Failed to map in G-stage\n");
>
> out_unlock:
> - kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
> + kvm_release_faultin_page(kvm, page, ret, writable);
> write_unlock(&kvm->mmu_lock);
> return ret;
> }
> diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
> index 6c8530b9f29e..76cceecee5ab 100644
> --- a/arch/riscv/kvm/vcpu_exit.c
> +++ b/arch/riscv/kvm/vcpu_exit.c
> @@ -17,7 +17,8 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
> {
> struct kvm_gstage_mapping host_map;
> struct kvm_memory_slot *memslot;
> - unsigned long hva, fault_addr;
> + unsigned long hva;
> + gpa_t fault_addr;
> bool writable;
> gfn_t gfn;
> int ret;
> --
> 2.54.0
>
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 0/3] RISC-V: KVM: G-stage fault path fix and cleanup
2026-07-29 7:52 ` Bingyu.Xian
(?)
@ 2026-07-29 12:07 ` Bingyu.Xian
-1 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable
Three small changes to the RISC-V G-stage page fault path, sent as
separate patches per review feedback.
1/3: Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet
success, aligning RISC-V with x86 and arm64. Real bug fix;
Fixes: 9d05c1fee837, Cc: stable.
2/3: vma_pageshift: short -> unsigned int. No-functional-change
type cleanup in preparation for sharing a common
struct kvm_page_fault across architectures.
3/3: Widen the G-stage fault address to gpa_t end to end -- the
local in gstage_page_fault(), the (gpa_t) cast before the <<2
shift, and the fault_addr parameters of kvm_riscv_vcpu_mmio_load/
store(). This completes the RV32 34-bit GPA fix that v2 only
half-addressed: v2 widened the local and cast the shift, but the
address was still narrowed to 32 bits at the MMIO handler call
(unsigned long parameter), aliasing accesses above 4 GB into the
low 4 GB. The handlers' internal uses (run->mmio.phys_addr is
__u64, kvm_io_bus_read/write() take gpa_t) are already 64-bit.
Also in preparation for sharing a common struct kvm_page_fault.
No functional change on RV64. Not Cc'd to stable: RV32 KVM is
unsupported and this is untested at runtime.
Changes since v2 [1]:
- Split into separate patches per feedback.
- Completed the fault_addr widening v2 left half-done: widened the
kvm_riscv_vcpu_mmio_load/store() fault_addr parameters to gpa_t so
the 34-bit address is not truncated at the MMIO handler call.
The KVM_MEM_USERFAULT port that motivated this cleanup will follow as a
separate RFC.
[1] https://lore.kernel.org/kvm/20260729075230.743030-1-shanbeeyoo@gmail.com/
Bingyu.Xian (3):
RISC-V: KVM: Treat -EEXIST from G-stage map as success
RISC-V: KVM: Use unsigned int for vma_pageshift
RISC-V: KVM: Widen G-stage fault address to gpa_t
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
4 files changed, 12 insertions(+), 9 deletions(-)
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 0/3] RISC-V: KVM: G-stage fault path fix and cleanup
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable
Three small changes to the RISC-V G-stage page fault path, sent as
separate patches per review feedback.
1/3: Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet
success, aligning RISC-V with x86 and arm64. Real bug fix;
Fixes: 9d05c1fee837, Cc: stable.
2/3: vma_pageshift: short -> unsigned int. No-functional-change
type cleanup in preparation for sharing a common
struct kvm_page_fault across architectures.
3/3: Widen the G-stage fault address to gpa_t end to end -- the
local in gstage_page_fault(), the (gpa_t) cast before the <<2
shift, and the fault_addr parameters of kvm_riscv_vcpu_mmio_load/
store(). This completes the RV32 34-bit GPA fix that v2 only
half-addressed: v2 widened the local and cast the shift, but the
address was still narrowed to 32 bits at the MMIO handler call
(unsigned long parameter), aliasing accesses above 4 GB into the
low 4 GB. The handlers' internal uses (run->mmio.phys_addr is
__u64, kvm_io_bus_read/write() take gpa_t) are already 64-bit.
Also in preparation for sharing a common struct kvm_page_fault.
No functional change on RV64. Not Cc'd to stable: RV32 KVM is
unsupported and this is untested at runtime.
Changes since v2 [1]:
- Split into separate patches per feedback.
- Completed the fault_addr widening v2 left half-done: widened the
kvm_riscv_vcpu_mmio_load/store() fault_addr parameters to gpa_t so
the 34-bit address is not truncated at the MMIO handler call.
The KVM_MEM_USERFAULT port that motivated this cleanup will follow as a
separate RFC.
[1] https://lore.kernel.org/kvm/20260729075230.743030-1-shanbeeyoo@gmail.com/
Bingyu.Xian (3):
RISC-V: KVM: Treat -EEXIST from G-stage map as success
RISC-V: KVM: Use unsigned int for vma_pageshift
RISC-V: KVM: Widen G-stage fault address to gpa_t
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
4 files changed, 12 insertions(+), 9 deletions(-)
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 0/3] RISC-V: KVM: G-stage fault path fix and cleanup
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable
Three small changes to the RISC-V G-stage page fault path, sent as
separate patches per review feedback.
1/3: Treat -EEXIST from kvm_riscv_gstage_map_page() as a quiet
success, aligning RISC-V with x86 and arm64. Real bug fix;
Fixes: 9d05c1fee837, Cc: stable.
2/3: vma_pageshift: short -> unsigned int. No-functional-change
type cleanup in preparation for sharing a common
struct kvm_page_fault across architectures.
3/3: Widen the G-stage fault address to gpa_t end to end -- the
local in gstage_page_fault(), the (gpa_t) cast before the <<2
shift, and the fault_addr parameters of kvm_riscv_vcpu_mmio_load/
store(). This completes the RV32 34-bit GPA fix that v2 only
half-addressed: v2 widened the local and cast the shift, but the
address was still narrowed to 32 bits at the MMIO handler call
(unsigned long parameter), aliasing accesses above 4 GB into the
low 4 GB. The handlers' internal uses (run->mmio.phys_addr is
__u64, kvm_io_bus_read/write() take gpa_t) are already 64-bit.
Also in preparation for sharing a common struct kvm_page_fault.
No functional change on RV64. Not Cc'd to stable: RV32 KVM is
unsupported and this is untested at runtime.
Changes since v2 [1]:
- Split into separate patches per feedback.
- Completed the fault_addr widening v2 left half-done: widened the
kvm_riscv_vcpu_mmio_load/store() fault_addr parameters to gpa_t so
the 34-bit address is not truncated at the MMIO handler call.
The KVM_MEM_USERFAULT port that motivated this cleanup will follow as a
separate RFC.
[1] https://lore.kernel.org/kvm/20260729075230.743030-1-shanbeeyoo@gmail.com/
Bingyu.Xian (3):
RISC-V: KVM: Treat -EEXIST from G-stage map as success
RISC-V: KVM: Use unsigned int for vma_pageshift
RISC-V: KVM: Widen G-stage fault address to gpa_t
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/mmu.c | 8 +++++---
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
4 files changed, 12 insertions(+), 9 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3 1/3] RISC-V: KVM: Treat -EEXIST from G-stage map as success
2026-07-29 12:07 ` Bingyu.Xian
(?)
@ 2026-07-29 12:07 ` Bingyu.Xian
-1 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
When a concurrent vCPU installs the same G-stage mapping while we are
waiting for mmu_lock, kvm_riscv_gstage_map_page() returns -EEXIST.
This is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating it
as one: printing "Failed to map in G-stage" to dmesg and propagating
-EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets kvm_release_faultin_page()
drop its "ret && ret != -EEXIST" special case: with ret normalized to 0
the regular release path is correct.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Cc: stable@vger.kernel.org
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..943d8dc72105 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 1/3] RISC-V: KVM: Treat -EEXIST from G-stage map as success
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
When a concurrent vCPU installs the same G-stage mapping while we are
waiting for mmu_lock, kvm_riscv_gstage_map_page() returns -EEXIST.
This is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating it
as one: printing "Failed to map in G-stage" to dmesg and propagating
-EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets kvm_release_faultin_page()
drop its "ret && ret != -EEXIST" special case: with ret normalized to 0
the regular release path is correct.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Cc: stable@vger.kernel.org
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..943d8dc72105 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 1/3] RISC-V: KVM: Treat -EEXIST from G-stage map as success
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
When a concurrent vCPU installs the same G-stage mapping while we are
waiting for mmu_lock, kvm_riscv_gstage_map_page() returns -EEXIST.
This is not an error -- the page is correctly mapped and the faulting
vCPU can simply retry the guest instruction -- but KVM was treating it
as one: printing "Failed to map in G-stage" to dmesg and propagating
-EEXIST all the way to userspace.
Align RISC-V with x86 and arm64, which already swallow -EEXIST in
their respective fault handlers. This also lets kvm_release_faultin_page()
drop its "ret && ret != -EEXIST" special case: with ret normalized to 0
the regular release path is correct.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Cc: stable@vger.kernel.org
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 8a0aa5e0e216..943d8dc72105 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -652,11 +652,13 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
vma_pagesize, true, true, out_map);
}
- if (ret)
+ if (ret == -EEXIST)
+ ret = 0;
+ else if (ret)
kvm_err("Failed to map in G-stage\n");
out_unlock:
- kvm_release_faultin_page(kvm, page, ret && ret != -EEXIST, writable);
+ kvm_release_faultin_page(kvm, page, ret, writable);
write_unlock(&kvm->mmu_lock);
return ret;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 2/3] RISC-V: KVM: Use unsigned int for vma_pageshift
2026-07-29 12:07 ` Bingyu.Xian
(?)
@ 2026-07-29 12:07 ` Bingyu.Xian
-1 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
vma_pageshift in kvm_riscv_mmu_map() was declared short. Use unsigned
int, the conventional kernel type for bit widths and shift counts, in
preparation for sharing a common struct kvm_page_fault across
architectures. No functional change.
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 943d8dc72105..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 2/3] RISC-V: KVM: Use unsigned int for vma_pageshift
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
vma_pageshift in kvm_riscv_mmu_map() was declared short. Use unsigned
int, the conventional kernel type for bit widths and shift counts, in
preparation for sharing a common struct kvm_page_fault across
architectures. No functional change.
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 943d8dc72105..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 2/3] RISC-V: KVM: Use unsigned int for vma_pageshift
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
vma_pageshift in kvm_riscv_mmu_map() was declared short. Use unsigned
int, the conventional kernel type for bit widths and shift counts, in
preparation for sharing a common struct kvm_page_fault across
architectures. No functional change.
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/kvm/mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kvm/mmu.c b/arch/riscv/kvm/mmu.c
index 943d8dc72105..d2a06a54be17 100644
--- a/arch/riscv/kvm/mmu.c
+++ b/arch/riscv/kvm/mmu.c
@@ -541,7 +541,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
kvm_pfn_t hfn;
bool is_hugetlb;
bool writable;
- short vma_pageshift;
+ unsigned int vma_pageshift;
gfn_t gfn = gpa >> PAGE_SHIFT;
struct vm_area_struct *vma;
struct kvm *kvm = vcpu->kvm;
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 3/3] RISC-V: KVM: Widen G-stage fault address to gpa_t
2026-07-29 12:07 ` Bingyu.Xian
(?)
@ 2026-07-29 12:07 ` Bingyu.Xian
-1 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
fault_addr in gstage_page_fault() and the fault_addr parameter of
kvm_riscv_vcpu_mmio_load/store() are unsigned long. On RV32 with
Sv32x4, guest physical addresses are 34 bits, so a 32-bit unsigned
long truncates bits 32/33 at two points:
- reconstruction: fault_addr = (trap->htval << 2) | ... is evaluated
in 32-bit arithmetic, dropping bits 32/33 before widening;
- the MMIO handler call: even with the local widened, the handler's
unsigned long parameter narrows it back to 32 bits, aliasing
accesses above 4 GB into the low 4 GB.
Widen fault_addr to gpa_t end to end: the local in gstage_page_fault(),
the (gpa_t) cast before the <<2 shift, and the fault_addr parameters of
kvm_riscv_vcpu_mmio_load/store(). The handlers' internal uses
(run->mmio.phys_addr is __u64, kvm_io_bus_read/write() take gpa_t) are
already 64-bit, so no further changes are needed.
Also in preparation for sharing a common struct kvm_page_fault across
architectures, where fault_addr is gpa_t. No functional change on RV64.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_vcpu_insn.h b/arch/riscv/include/asm/kvm_vcpu_insn.h
index 350011c83581..a5c50dd4a884 100644
--- a/arch/riscv/include/asm/kvm_vcpu_insn.h
+++ b/arch/riscv/include/asm/kvm_vcpu_insn.h
@@ -38,10 +38,10 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
struct kvm_cpu_trap *trap);
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index f09f9251d1f0..6506411a3f78 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -371,7 +371,7 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data_buf[8];
@@ -494,7 +494,7 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data8;
--
2.54.0
--
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 3/3] RISC-V: KVM: Widen G-stage fault address to gpa_t
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
fault_addr in gstage_page_fault() and the fault_addr parameter of
kvm_riscv_vcpu_mmio_load/store() are unsigned long. On RV32 with
Sv32x4, guest physical addresses are 34 bits, so a 32-bit unsigned
long truncates bits 32/33 at two points:
- reconstruction: fault_addr = (trap->htval << 2) | ... is evaluated
in 32-bit arithmetic, dropping bits 32/33 before widening;
- the MMIO handler call: even with the local widened, the handler's
unsigned long parameter narrows it back to 32 bits, aliasing
accesses above 4 GB into the low 4 GB.
Widen fault_addr to gpa_t end to end: the local in gstage_page_fault(),
the (gpa_t) cast before the <<2 shift, and the fault_addr parameters of
kvm_riscv_vcpu_mmio_load/store(). The handlers' internal uses
(run->mmio.phys_addr is __u64, kvm_io_bus_read/write() take gpa_t) are
already 64-bit, so no further changes are needed.
Also in preparation for sharing a common struct kvm_page_fault across
architectures, where fault_addr is gpa_t. No functional change on RV64.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_vcpu_insn.h b/arch/riscv/include/asm/kvm_vcpu_insn.h
index 350011c83581..a5c50dd4a884 100644
--- a/arch/riscv/include/asm/kvm_vcpu_insn.h
+++ b/arch/riscv/include/asm/kvm_vcpu_insn.h
@@ -38,10 +38,10 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
struct kvm_cpu_trap *trap);
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index f09f9251d1f0..6506411a3f78 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -371,7 +371,7 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data_buf[8];
@@ -494,7 +494,7 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data8;
--
2.54.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3 3/3] RISC-V: KVM: Widen G-stage fault address to gpa_t
@ 2026-07-29 12:07 ` Bingyu.Xian
0 siblings, 0 replies; 23+ messages in thread
From: Bingyu.Xian @ 2026-07-29 12:07 UTC (permalink / raw)
To: Anup Patel
Cc: Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, kvm-riscv, linux-riscv, linux-kernel,
Quan Zhou, stable, Bingyu Xian
fault_addr in gstage_page_fault() and the fault_addr parameter of
kvm_riscv_vcpu_mmio_load/store() are unsigned long. On RV32 with
Sv32x4, guest physical addresses are 34 bits, so a 32-bit unsigned
long truncates bits 32/33 at two points:
- reconstruction: fault_addr = (trap->htval << 2) | ... is evaluated
in 32-bit arithmetic, dropping bits 32/33 before widening;
- the MMIO handler call: even with the local widened, the handler's
unsigned long parameter narrows it back to 32 bits, aliasing
accesses above 4 GB into the low 4 GB.
Widen fault_addr to gpa_t end to end: the local in gstage_page_fault(),
the (gpa_t) cast before the <<2 shift, and the fault_addr parameters of
kvm_riscv_vcpu_mmio_load/store(). The handlers' internal uses
(run->mmio.phys_addr is __u64, kvm_io_bus_read/write() take gpa_t) are
already 64-bit, so no further changes are needed.
Also in preparation for sharing a common struct kvm_page_fault across
architectures, where fault_addr is gpa_t. No functional change on RV64.
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Bingyu Xian <shanbeeyoo@gmail.com>
---
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++--
arch/riscv/kvm/vcpu_exit.c | 5 +++--
arch/riscv/kvm/vcpu_insn.c | 4 ++--
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_vcpu_insn.h b/arch/riscv/include/asm/kvm_vcpu_insn.h
index 350011c83581..a5c50dd4a884 100644
--- a/arch/riscv/include/asm/kvm_vcpu_insn.h
+++ b/arch/riscv/include/asm/kvm_vcpu_insn.h
@@ -38,10 +38,10 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
struct kvm_cpu_trap *trap);
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
index 6c8530b9f29e..28cf9b27bb07 100644
--- a/arch/riscv/kvm/vcpu_exit.c
+++ b/arch/riscv/kvm/vcpu_exit.c
@@ -17,12 +17,13 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
struct kvm_gstage_mapping host_map;
struct kvm_memory_slot *memslot;
- unsigned long hva, fault_addr;
+ unsigned long hva;
+ gpa_t fault_addr;
bool writable;
gfn_t gfn;
int ret;
- fault_addr = (trap->htval << 2) | (trap->stval & 0x3);
+ fault_addr = ((gpa_t)trap->htval << 2) | (trap->stval & 0x3);
gfn = fault_addr >> PAGE_SHIFT;
memslot = gfn_to_memslot(vcpu->kvm, gfn);
hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index f09f9251d1f0..6506411a3f78 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -371,7 +371,7 @@ int kvm_riscv_vcpu_virtual_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data_buf[8];
@@ -494,7 +494,7 @@ int kvm_riscv_vcpu_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
* Returns < 0 to report failure and exit run-loop
*/
int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
- unsigned long fault_addr,
+ gpa_t fault_addr,
unsigned long htinst)
{
u8 data8;
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
end of thread, other threads:[~2026-07-29 12:08 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29 7:07 [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types Bingyu.Xian
2026-07-29 7:07 ` Bingyu.Xian
2026-07-29 7:07 ` Bingyu.Xian
2026-07-29 7:17 ` sashiko-bot
2026-07-29 7:52 ` [PATCH v2] " Bingyu.Xian
2026-07-29 7:52 ` Bingyu.Xian
2026-07-29 7:52 ` Bingyu.Xian
2026-07-29 8:03 ` sashiko-bot
2026-07-29 12:07 ` [PATCH v3 0/3] RISC-V: KVM: G-stage fault path fix and cleanup Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` [PATCH v3 1/3] RISC-V: KVM: Treat -EEXIST from G-stage map as success Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` [PATCH v3 2/3] RISC-V: KVM: Use unsigned int for vma_pageshift Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` [PATCH v3 3/3] RISC-V: KVM: Widen G-stage fault address to gpa_t Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 12:07 ` Bingyu.Xian
2026-07-29 8:05 ` [PATCH] RISC-V: KVM: Fix spurious -EEXIST and clean up gstage fault path types Anup Patel
2026-07-29 8:05 ` Anup Patel
2026-07-29 8:05 ` Anup Patel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.