@@ -1363,6 +1363,8 @@ static inline int kvm_vcpu_map_readonly(struct kvm_vcpu *vcpu, gpa_t gpa,
unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn);
unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable);
+int kvm_vcpu_validate_gpa_range(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned long len,
+ bool write_access);
int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset,
int len);
int kvm_vcpu_read_guest_atomic(struct kvm_vcpu *vcpu, gpa_t gpa, void *data,
@@ -3283,6 +3283,27 @@ int kvm_vcpu_write_guest(struct kvm_vcpu *vcpu, gpa_t gpa, const void *data,
}
EXPORT_SYMBOL_GPL(kvm_vcpu_write_guest);
+int kvm_vcpu_validate_gpa_range(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned long len,
+ bool write_access)
+{
+ gfn_t gfn = gpa >> PAGE_SHIFT;
+ int seg;
+ int offset = offset_in_page(gpa);
+ bool writable = false;
+ unsigned long hva;
+
+ while ((seg = next_segment(len, offset)) != 0) {
+ hva = kvm_vcpu_gfn_to_hva_prot(vcpu, gfn, &writable);
+ if (kvm_is_error_hva(hva) || (writable ^ write_access))
+ return -EPERM;
+ offset = 0;
+ len -= seg;
+ ++gfn;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_vcpu_validate_gpa_range);
+
static int __kvm_gfn_to_hva_cache_init(struct kvm_memslots *slots,
struct gfn_to_hva_cache *ghc,
gpa_t gpa, unsigned long len)
The arch specific code may need to validate a gpa range if it is a shared memory between the host and the guest. Currently, there are few places where it is used in RISC-V implementation. Given the nature of the function it may be used for other architectures. Hence, a common helper function is added. Signed-off-by: Atish Patra <atishp@rivosinc.com> --- include/linux/kvm_host.h | 2 ++ virt/kvm/kvm_main.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+)