[PATCH v2 14/15] drm/i915/gvt: Provide generic page_track infrastructure for write-protected page
Zhenyu Wang
zhenyuw at linux.intel.com
Wed Jan 3 07:45:58 UTC 2018
On 2018.01.02 16:29:45 +0800, changbin.du at intel.com wrote:
> From: Changbin Du <changbin.du at intel.com>
>
> This patch provide generic page_track infrastructure for write-protected
> guest page. The old page_track logic gets rewrote and now stays in a new
> standalone page_track.c. This page track infrastructure can be both used
> by vGUC and GTT shadowing.
>
> The important change is that it uses radix tree instead of hash table.
> We don't have a predictable number of pages that will be tracked.
>
> Here is some performance data (duration in us) of looking up a element:
> Before: (aka. intel_vgpu_find_tracked_page)
> 0.091 0.089 0.090 ... 0.093 0.091 0.087 ... 0.292 0.285 0.292 0.291
> After: (aka. intel_vgpu_find_page_track)
> 0.104 0.105 0.100 0.102 0.102 0.100 ... 0.101 0.101 0.105 0.105
>
what's scenario of this test case? Are these recorded function call time?
> The hash table has good performance at beginning, but turns bad with
> more pages being tracked even no 3D applications are running. As
> expected, radix tree has stable duration and very quick.
>
> Signed-off-by: Changbin Du <changbin.du at intel.com>
> ---
> drivers/gpu/drm/i915/gvt/Makefile | 2 +-
> drivers/gpu/drm/i915/gvt/gtt.c | 120 +++++-----------------
> drivers/gpu/drm/i915/gvt/gtt.h | 14 ---
> drivers/gpu/drm/i915/gvt/gvt.c | 2 +-
> drivers/gpu/drm/i915/gvt/gvt.h | 2 +
> drivers/gpu/drm/i915/gvt/page_track.c | 181 ++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/gvt/page_track.h | 56 +++++++++++
> drivers/gpu/drm/i915/gvt/vgpu.c | 1 +
> 8 files changed, 266 insertions(+), 112 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/gvt/page_track.c
> create mode 100644 drivers/gpu/drm/i915/gvt/page_track.h
>
> diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile
> index 347116f..b016dc7 100644
> --- a/drivers/gpu/drm/i915/gvt/Makefile
> +++ b/drivers/gpu/drm/i915/gvt/Makefile
> @@ -3,7 +3,7 @@ GVT_DIR := gvt
> GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
> interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
> execlist.o scheduler.o sched_policy.o mmio_context.o cmd_parser.o debugfs.o \
> - fb_decoder.o dmabuf.o
> + fb_decoder.o dmabuf.o page_track.o
>
> ccflags-y += -I$(src) -I$(src)/$(GVT_DIR)
> i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
> index f7a8022..2ed7dbb 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.c
> +++ b/drivers/gpu/drm/i915/gvt/gtt.c
> @@ -559,7 +559,7 @@ static inline int ppgtt_spt_get_entry(
> return -EINVAL;
>
> ret = ops->get_entry(page_table, e, index, guest,
> - spt->guest_page.track.gfn << I915_GTT_PAGE_SHIFT,
> + spt->guest_page.gfn << I915_GTT_PAGE_SHIFT,
> spt->vgpu);
> if (ret)
> return ret;
> @@ -587,7 +587,7 @@ static inline int ppgtt_spt_set_entry(
> type, e->type, index, e->val64);
>
> return ops->set_entry(page_table, e, index, guest,
> - spt->guest_page.track.gfn << I915_GTT_PAGE_SHIFT,
> + spt->guest_page.gfn << I915_GTT_PAGE_SHIFT,
> spt->vgpu);
> }
>
> @@ -607,9 +607,6 @@ static inline int ppgtt_spt_set_entry(
> ppgtt_spt_set_entry(spt, spt->shadow_page.vaddr, \
> spt->shadow_page.type, e, index, false)
>
> -#define page_track_to_ppgtt_spt(ptr) \
> - container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page.track)
> -
> static void *alloc_spt(gfp_t gfp_mask)
> {
> struct intel_vgpu_ppgtt_spt *spt;
> @@ -632,30 +629,6 @@ static void free_spt(struct intel_vgpu_ppgtt_spt *spt)
> kfree(spt);
> }
>
> -/**
> - * intel_vgpu_find_tracked_page - find a tracked guest page
> - * @vgpu: a vGPU
> - * @gfn: guest memory page frame number
> - *
> - * This function is called when the emulation layer wants to figure out if a
> - * trapped GFN is a tracked guest page.
> - *
> - * Returns:
> - * Pointer to page track data structure, NULL if not found.
> - */
> -struct intel_vgpu_page_track *intel_vgpu_find_tracked_page(
> - struct intel_vgpu *vgpu, unsigned long gfn)
> -{
> - struct intel_vgpu_page_track *t;
> -
> - hash_for_each_possible(vgpu->gtt.tracked_guest_page_hash_table,
> - t, node, gfn) {
> - if (t->gfn == gfn)
> - return t;
> - }
> - return NULL;
> -}
> -
> static int detach_oos_page(struct intel_vgpu *vgpu,
> struct intel_vgpu_oos_page *oos_page);
>
> @@ -673,12 +646,7 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt *spt)
> if (spt->guest_page.oos_page)
> detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
>
> - if (!hlist_unhashed(&spt->guest_page.track.node))
> - hash_del(&spt->guest_page.track.node);
> -
> - if (spt->guest_page.track.tracked)
> - intel_gvt_hypervisor_unset_wp_page(spt->vgpu,
> - spt->guest_page.track.gfn);
> + intel_vgpu_unregister_page_track(spt->vgpu, spt->guest_page.gfn);
>
> list_del_init(&spt->post_shadow_list);
> free_spt(spt);
> @@ -698,21 +666,18 @@ static int ppgtt_handle_guest_write_page_table_bytes(
> struct intel_vgpu_ppgtt_spt *spt,
> u64 pa, void *p_data, int bytes);
>
> -static int ppgtt_write_protection_handler(void *data, u64 pa,
> - void *p_data, int bytes)
> +static int ppgtt_write_protection_handler(
> + struct intel_vgpu_page_track *page_track,
> + u64 gpa, void *data, int bytes)
> {
> - struct intel_vgpu_page_track *t = data;
> - struct intel_vgpu_ppgtt_spt *spt = page_track_to_ppgtt_spt(t);
> + struct intel_vgpu_ppgtt_spt *spt = page_track->priv_data;
> +
> int ret;
>
> if (bytes != 4 && bytes != 8)
> return -EINVAL;
>
> - if (!t->tracked)
> - return -EINVAL;
> -
> - ret = ppgtt_handle_guest_write_page_table_bytes(spt,
> - pa, p_data, bytes);
> + ret = ppgtt_handle_guest_write_page_table_bytes(spt, gpa, data, bytes);
> if (ret)
> return ret;
> return ret;
> @@ -724,9 +689,9 @@ static struct intel_vgpu_ppgtt_spt *intel_vgpu_find_spt_by_gfn(
> {
> struct intel_vgpu_page_track *track;
>
> - track = intel_vgpu_find_tracked_page(vgpu, gfn);
> - if (track)
> - return page_track_to_ppgtt_spt(track);
> + track = intel_vgpu_find_page_track(vgpu, gfn);
> + if (track && track->handler == ppgtt_write_protection_handler)
> + return track->priv_data;
>
> return NULL;
> }
> @@ -752,6 +717,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
> struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev;
> struct intel_vgpu_ppgtt_spt *spt = NULL;
> dma_addr_t daddr;
> + int ret;
>
> retry:
> spt = alloc_spt(GFP_KERNEL | __GFP_ZERO);
> @@ -787,10 +753,13 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
> spt->guest_page.type = type;
> spt->guest_page.gfn = gfn;
>
> - spt->guest_page.track.gfn = gfn;
> - spt->guest_page.track.handler = ppgtt_write_protection_handler;
> - hash_add(vgpu->gtt.tracked_guest_page_hash_table,
> - &spt->guest_page.track.node, gfn);
> + ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
> + ppgtt_write_protection_handler, spt);
> + if (ret) {
> + free_spt(spt);
> + dma_unmap_page(kdev, daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
> + return ERR_PTR(ret);
> + }
>
> INIT_HLIST_NODE(&spt->node);
> hash_add(vgpu->gtt.spt_hash_table, &spt->node, spt->shadow_page.mfn);
> @@ -926,11 +895,10 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_spt_by_guest_entry(
> goto fail;
> }
>
> - ret = intel_gvt_hypervisor_set_wp_page(vgpu, spt->guest_page.track.gfn);
> + ret = intel_vgpu_enable_page_track(vgpu, spt->guest_page.gfn);
> if (ret)
> goto fail;
>
> - spt->guest_page.track.tracked = true;
> ret = ppgtt_populate_spt(spt);
> if (ret)
> goto fail;
> @@ -1000,7 +968,7 @@ static int ppgtt_populate_spt(struct intel_vgpu_ppgtt_spt *spt)
> int ret;
>
> trace_spt_change(spt->vgpu->id, "born", spt,
> - spt->guest_page.track.gfn, spt->shadow_page.type);
> + spt->guest_page.gfn, spt->shadow_page.type);
>
> for_each_present_guest_entry(spt, &ge, i) {
> if (gtt_type_is_pt(get_next_pt_type(ge.type))) {
> @@ -1188,10 +1156,9 @@ static int ppgtt_set_guest_page_sync(struct intel_vgpu_ppgtt_spt *spt)
> struct intel_vgpu_oos_page *oos_page = spt->guest_page.oos_page;
> int ret;
>
> - ret = intel_gvt_hypervisor_set_wp_page(spt->vgpu, spt->guest_page.track.gfn);
> + ret = intel_vgpu_enable_page_track(spt->vgpu, spt->guest_page.gfn);
> if (ret)
> return ret;
> - spt->guest_page.track.tracked = true;
>
> trace_oos_change(spt->vgpu->id, "set page sync", oos_page->id,
> spt, spt->guest_page.type);
> @@ -1227,7 +1194,6 @@ static int ppgtt_allocate_oos_page(struct intel_vgpu_ppgtt_spt *spt)
> static int ppgtt_set_guest_page_oos(struct intel_vgpu_ppgtt_spt *spt)
> {
> struct intel_vgpu_oos_page *oos_page = spt->guest_page.oos_page;
> - int ret;
>
> if (WARN(!oos_page, "shadow PPGTT page should have a oos page\n"))
> return -EINVAL;
> @@ -1236,11 +1202,7 @@ static int ppgtt_set_guest_page_oos(struct intel_vgpu_ppgtt_spt *spt)
> spt, spt->guest_page.type);
>
> list_add_tail(&oos_page->vm_list, &spt->vgpu->gtt.oos_page_list_head);
> - ret = intel_gvt_hypervisor_unset_wp_page(spt->vgpu, spt->guest_page.track.gfn);
> - if (ret)
> - return ret;
> - spt->guest_page.track.tracked = false;
> - return 0;
> + return intel_vgpu_disable_page_track(spt->vgpu, spt->guest_page.gfn);
> }
>
> /**
> @@ -1891,39 +1853,6 @@ int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
> return ret;
> }
>
> -int intel_vgpu_write_protect_handler(struct intel_vgpu *vgpu, u64 pa,
> - void *p_data, unsigned int bytes)
> -{
> - struct intel_gvt *gvt = vgpu->gvt;
> - int ret = 0;
> -
> - if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
> - struct intel_vgpu_page_track *t;
> -
> - mutex_lock(&gvt->lock);
> -
> - t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
> - if (t) {
> - if (unlikely(vgpu->failsafe)) {
> - /* remove write protection to prevent furture traps */
> - intel_gvt_hypervisor_unset_wp_page(vgpu, t->gfn);
> - } else {
> - ret = t->handler(t, pa, p_data, bytes);
> - if (ret) {
> - gvt_err("guest page write error %d, "
> - "gfn 0x%lx, pa 0x%llx, "
> - "var 0x%x, len %d\n",
> - ret, t->gfn, pa,
> - *(u32 *)p_data, bytes);
> - }
> - }
> - }
> - mutex_unlock(&gvt->lock);
> - }
> - return ret;
> -}
> -
> -
> static int alloc_scratch_pages(struct intel_vgpu *vgpu,
> intel_gvt_gtt_type_t type)
> {
> @@ -2038,7 +1967,6 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
> {
> struct intel_vgpu_gtt *gtt = &vgpu->gtt;
>
> - hash_init(gtt->tracked_guest_page_hash_table);
> hash_init(gtt->spt_hash_table);
>
> INIT_LIST_HEAD(>t->ppgtt_mm_list_head);
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
> index 9b7eb1b..a7fddab 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.h
> +++ b/drivers/gpu/drm/i915/gvt/gtt.h
> @@ -180,8 +180,6 @@ struct intel_vgpu_gtt {
> unsigned long active_ppgtt_mm_bitmap;
> struct list_head ppgtt_mm_list_head;
> DECLARE_HASHTABLE(spt_hash_table, INTEL_GVT_GTT_HASH_BITS);
> - DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
> - atomic_t n_tracked_guest_page;
> struct list_head oos_page_list_head;
> struct list_head post_shadow_list_head;
> struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
> @@ -198,14 +196,6 @@ extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
> extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
> int page_table_level, void *root_entry);
>
> -struct intel_vgpu_page_track {
> - struct hlist_node node;
> - bool tracked;
> - unsigned long gfn;
> - int (*handler)(void *, u64, void *, int);
> - void *data;
> -};
> -
> struct intel_vgpu_oos_page {
> struct intel_vgpu_ppgtt_spt *spt;
> struct list_head list;
> @@ -233,7 +223,6 @@ struct intel_vgpu_ppgtt_spt {
> intel_gvt_gtt_type_t type;
> unsigned long gfn;
> unsigned long write_cnt;
> - struct intel_vgpu_page_track track;
> struct intel_vgpu_oos_page *oos_page;
> } guest_page;
>
> @@ -266,7 +255,4 @@ int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu,
> int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
> unsigned int off, void *p_data, unsigned int bytes);
>
> -int intel_vgpu_write_protect_handler(struct intel_vgpu *vgpu, u64 pa,
> - void *p_data, unsigned int bytes);
> -
> #endif /* _GVT_GTT_H_ */
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
> index fac54f3..61bd14f 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.c
> +++ b/drivers/gpu/drm/i915/gvt/gvt.c
> @@ -183,7 +183,7 @@ static const struct intel_gvt_ops intel_gvt_ops = {
> .get_gvt_attrs = intel_get_gvt_attrs,
> .vgpu_query_plane = intel_vgpu_query_plane,
> .vgpu_get_dmabuf = intel_vgpu_get_dmabuf,
> - .write_protect_handler = intel_vgpu_write_protect_handler,
> + .write_protect_handler = intel_vgpu_page_track_handler,
> };
>
> /**
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index 7dc7a80..b9224ab 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -48,6 +48,7 @@
> #include "cmd_parser.h"
> #include "fb_decoder.h"
> #include "dmabuf.h"
> +#include "page_track.h"
>
> #define GVT_MAX_VGPU 8
>
> @@ -192,6 +193,7 @@ struct intel_vgpu {
> struct intel_vgpu_opregion opregion;
> struct intel_vgpu_display display;
> struct intel_vgpu_submission submission;
> + struct radix_tree_root page_track_tree;
> u32 hws_pga[I915_NUM_ENGINES];
>
> struct dentry *debugfs;
> diff --git a/drivers/gpu/drm/i915/gvt/page_track.c b/drivers/gpu/drm/i915/gvt/page_track.c
> new file mode 100644
> index 0000000..546b777
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/page_track.c
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +#include "i915_drv.h"
> +#include "gvt.h"
> +
> +/**
> + * intel_vgpu_find_page_track - find page track rcord of guest page
> + * @vgpu: a vGPU
> + * @gfn: the gfn of guest page
> + *
> + * Returns:
> + * A pointer to struct intel_vgpu_page_track if found, else NULL returned.
> + */
> +struct intel_vgpu_page_track *intel_vgpu_find_page_track(
> + struct intel_vgpu *vgpu, unsigned long gfn)
> +{
> + return radix_tree_lookup(&vgpu->page_track_tree, gfn);
> +}
> +
> +/**
> + * intel_vgpu_register_page_track - register a guest page to be tacked
> + * @vgpu: a vGPU
> + * @gfn: the gfn of guest page
> + *
> + * Returns:
> + * zero on success, negative error code if failed.
> + */
> +int intel_vgpu_register_page_track(struct intel_vgpu *vgpu, unsigned long gfn,
> + gvt_page_track_handler_t handler, void *priv)
> +{
> + struct intel_vgpu_page_track *track;
> + int ret;
> +
> + track = intel_vgpu_find_page_track(vgpu, gfn);
> + if (track)
> + return -EEXIST;
> +
> + track = kzalloc(sizeof(*track), GFP_KERNEL);
> + if (!track)
> + return -ENOMEM;
> +
> + track->handler = handler;
> + track->priv_data = priv;
> +
> + ret = radix_tree_insert(&vgpu->page_track_tree, gfn, track);
> + if (ret) {
> + kfree(track);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * intel_vgpu_unregister_page_track - unregister the tracked guest page
> + * @vgpu: a vGPU
> + * @gfn: the gfn of guest page
> + *
> + */
> +void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
> + unsigned long gfn)
> +{
> + struct intel_vgpu_page_track *track;
> +
> + track = radix_tree_delete(&vgpu->page_track_tree, gfn);
> + if (track) {
> + if (track->tracked)
> + intel_gvt_hypervisor_unset_wp_page(vgpu, gfn);
> + kfree(track);
> + }
> +}
> +
> +/**
> + * intel_vgpu_enable_page_track - set write-protection on guest page
> + * @vgpu: a vGPU
> + * @gfn: the gfn of guest page
> + *
> + * Returns:
> + * zero on success, negative error code if failed.
> + */
> +int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
> +{
> + struct intel_vgpu_page_track *track;
> + int ret;
> +
> + track = intel_vgpu_find_page_track(vgpu, gfn);
> + if (!track)
> + return -ENXIO;
> +
> + if (track->tracked)
> + return 0;
> +
> + ret = intel_gvt_hypervisor_set_wp_page(vgpu, gfn);
> + if (ret)
> + return ret;
> + track->tracked = true;
> + return 0;
> +}
> +
> +/**
> + * intel_vgpu_enable_page_track - cancel write-protection on guest page
> + * @vgpu: a vGPU
> + * @gfn: the gfn of guest page
> + *
> + * Returns:
> + * zero on success, negative error code if failed.
> + */
> +int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
> +{
> + struct intel_vgpu_page_track *track;
> + int ret;
> +
> + track = intel_vgpu_find_page_track(vgpu, gfn);
> + if (!track)
> + return -ENXIO;
> +
> + if (!track->tracked)
> + return 0;
> +
> + ret = intel_gvt_hypervisor_unset_wp_page(vgpu, gfn);
> + if (ret)
> + return ret;
> + track->tracked = false;
> + return 0;
> +}
> +
> +/**
> + * intel_vgpu_page_track_handler - called when write to write-protected page
> + * @vgpu: a vGPU
> + * @gpa: the gpa of this write
> + * @data: the writed data
> + * @bytes: the length of this write
> + *
> + * Returns:
> + * zero on success, negative error code if failed.
> + */
> +int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
> + void *data, unsigned int bytes)
> +{
> + struct intel_gvt *gvt = vgpu->gvt;
> + struct intel_vgpu_page_track *page_track;
> + int ret = 0;
> +
> + mutex_lock(&gvt->lock);
> +
> + page_track = intel_vgpu_find_page_track(vgpu, gpa >> PAGE_SHIFT);
> + if (!page_track)
> + return 0;
> +
> + if (unlikely(vgpu->failsafe)) {
> + /* Remove write protection to prevent furture traps. */
> + intel_vgpu_disable_page_track(vgpu, gpa >> PAGE_SHIFT);
> + } else {
> + ret = page_track->handler(page_track, gpa, data, bytes);
> + if (ret)
> + gvt_err("guest page write error, gpa %llx\n", gpa);
> + }
> +
> + mutex_unlock(&gvt->lock);
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/i915/gvt/page_track.h b/drivers/gpu/drm/i915/gvt/page_track.h
> new file mode 100644
> index 0000000..fa607a7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gvt/page_track.h
> @@ -0,0 +1,56 @@
> +/*
> + * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + *
> + */
> +
> +#ifndef _GVT_PAGE_TRACK_H_
> +#define _GVT_PAGE_TRACK_H_
> +
> +struct intel_vgpu_page_track;
> +
> +typedef int (*gvt_page_track_handler_t)(
> + struct intel_vgpu_page_track *page_track,
> + u64 gpa, void *data, int bytes);
> +
> +/* Track record for a write-protected guest page. */
> +struct intel_vgpu_page_track {
> + gvt_page_track_handler_t handler;
> + bool tracked;
> + void *priv_data;
> +};
> +
> +struct intel_vgpu_page_track *intel_vgpu_find_page_track(
> + struct intel_vgpu *vgpu, unsigned long gfn);
> +
> +int intel_vgpu_register_page_track(struct intel_vgpu *vgpu,
> + unsigned long gfn, gvt_page_track_handler_t handler,
> + void *priv);
> +void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
> + unsigned long gfn);
> +
> +int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn);
> +int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn);
> +
> +int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
> + void *data, unsigned int bytes);
> +
> +#endif
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 4688619..46d1f01 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -352,6 +352,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
> vgpu->gvt = gvt;
> vgpu->sched_ctl.weight = param->weight;
> INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
> + INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL);
> idr_init(&vgpu->object_idr);
> intel_vgpu_init_cfg_space(vgpu, param->primary);
>
> --
> 2.7.4
>
> _______________________________________________
> intel-gvt-dev mailing list
> intel-gvt-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
--
Open Source Technology Center, Intel ltd.
$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/intel-gvt-dev/attachments/20180103/4410741e/attachment-0001.sig>
More information about the intel-gvt-dev
mailing list