Commit f440c8a5 authored by Jike Song's avatar Jike Song Committed by Zhenyu Wang

drm/i915/gvt/kvmgt: read/write GPA via KVM API

Previously to read/write a GPA, we at first try to pin the GFN it belongs
to, then translate the pinned PFN to a kernel HVA, then read/write it.
This is however not necessary. A GFN should be pinned IFF it would be
accessed by peripheral devices (DMA), not by CPU. This patch changes
the read/write method to KVM API, which will leverage userspace HVA
and copy_{from|to}_usr instead.
Signed-off-by: default avatarJike Song <jike.song@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
parent c55b1de0
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mmu_context.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
...@@ -519,33 +520,27 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn) ...@@ -519,33 +520,27 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
return pfn; return pfn;
} }
static void *kvmgt_gpa_to_hva(unsigned long handle, unsigned long gpa)
{
unsigned long pfn;
gfn_t gfn = gpa_to_gfn(gpa);
pfn = kvmgt_gfn_to_pfn(handle, gfn);
if (!pfn)
return NULL;
return (char *)pfn_to_kaddr(pfn) + offset_in_page(gpa);
}
static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa, static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
void *buf, unsigned long len, bool write) void *buf, unsigned long len, bool write)
{ {
void *hva = NULL; struct kvmgt_guest_info *info;
struct kvm *kvm;
int ret;
bool kthread = current->mm == NULL;
hva = kvmgt_gpa_to_hva(handle, gpa); info = (struct kvmgt_guest_info *)handle;
if (!hva) kvm = info->kvm;
return -EFAULT;
if (write) if (kthread)
memcpy(hva, buf, len); use_mm(kvm->mm);
else
memcpy(buf, hva, len);
return 0; ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
kvm_read_guest(kvm, gpa, buf, len);
if (kthread)
unuse_mm(kvm->mm);
return ret;
} }
static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa, static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment