aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJike Song <jike.song@intel.com>2016-12-07 22:00:35 -0500
committerZhenyu Wang <zhenyuw@linux.intel.com>2016-12-16 03:55:26 -0500
commitf440c8a572d7e0002d5c2c8dbd740130ad8ffa5b (patch)
tree9511b191afb97fab97f0fd0747b9c7cc214568ae
parentc55b1de02d68e4343045391c0f4978c0bc5a9447 (diff)
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: Jike Song <jike.song@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index aecb657d8b99..24496ad6a942 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -31,6 +31,7 @@
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/device.h> 32#include <linux/device.h>
33#include <linux/mm.h> 33#include <linux/mm.h>
34#include <linux/mmu_context.h>
34#include <linux/types.h> 35#include <linux/types.h>
35#include <linux/list.h> 36#include <linux/list.h>
36#include <linux/rbtree.h> 37#include <linux/rbtree.h>
@@ -519,33 +520,27 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
519 return pfn; 520 return pfn;
520} 521}
521 522
522static void *kvmgt_gpa_to_hva(unsigned long handle, unsigned long gpa)
523{
524 unsigned long pfn;
525 gfn_t gfn = gpa_to_gfn(gpa);
526
527 pfn = kvmgt_gfn_to_pfn(handle, gfn);
528 if (!pfn)
529 return NULL;
530
531 return (char *)pfn_to_kaddr(pfn) + offset_in_page(gpa);
532}
533
534static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa, 523static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
535 void *buf, unsigned long len, bool write) 524 void *buf, unsigned long len, bool write)
536{ 525{
537 void *hva = NULL; 526 struct kvmgt_guest_info *info;
527 struct kvm *kvm;
528 int ret;
529 bool kthread = current->mm == NULL;
538 530
539 hva = kvmgt_gpa_to_hva(handle, gpa); 531 info = (struct kvmgt_guest_info *)handle;
540 if (!hva) 532 kvm = info->kvm;
541 return -EFAULT;
542 533
543 if (write) 534 if (kthread)
544 memcpy(hva, buf, len); 535 use_mm(kvm->mm);
545 else
546 memcpy(buf, hva, len);
547 536
548 return 0; 537 ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
538 kvm_read_guest(kvm, gpa, buf, len);
539
540 if (kthread)
541 unuse_mm(kvm->mm);
542
543 return ret;
549} 544}
550 545
551static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa, 546static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,