drm/i915/gvt: Factor intel_vgpu_page_track

As the data structure of "intel_vgpu_guest_page" will become much heavier
in future, it's better to factor out the guest memory page track mechnisim
as early as possible.

Signed-off-by: Zhi Wang <zhi.a.wang@intel.com>
This commit is contained in:
Zhi Wang 2017-09-29 02:47:55 +08:00 committed by Zhenyu Wang
parent f52c380a48
commit 7d1e5cdf01
4 changed files with 147 additions and 125 deletions

View File

@ -494,7 +494,7 @@ static inline int ppgtt_spt_get_entry(
return -EINVAL; return -EINVAL;
ret = ops->get_entry(page_table, e, index, guest, ret = ops->get_entry(page_table, e, index, guest,
spt->guest_page.gfn << GTT_PAGE_SHIFT, spt->guest_page.track.gfn << GTT_PAGE_SHIFT,
spt->vgpu); spt->vgpu);
if (ret) if (ret)
return ret; return ret;
@ -516,7 +516,7 @@ static inline int ppgtt_spt_set_entry(
return -EINVAL; return -EINVAL;
return ops->set_entry(page_table, e, index, guest, return ops->set_entry(page_table, e, index, guest,
spt->guest_page.gfn << GTT_PAGE_SHIFT, spt->guest_page.track.gfn << GTT_PAGE_SHIFT,
spt->vgpu); spt->vgpu);
} }
@ -537,84 +537,99 @@ static inline int ppgtt_spt_set_entry(
spt->shadow_page.type, e, index, false) spt->shadow_page.type, e, index, false)
/** /**
* intel_vgpu_init_guest_page - init a guest page data structure * intel_vgpu_init_page_track - init a page track data structure
* @vgpu: a vGPU * @vgpu: a vGPU
* @p: a guest page data structure * @t: a page track data structure
* @gfn: guest memory page frame number * @gfn: guest memory page frame number
* @handler: function will be called when target guest memory page has * @handler: the function will be called when target guest memory page has
* been modified. * been modified.
* *
* This function is called when user wants to track a guest memory page. * This function is called when a user wants to prepare a page track data
* structure to track a guest memory page.
* *
* Returns: * Returns:
* Zero on success, negative error code if failed. * Zero on success, negative error code if failed.
*/ */
int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, int intel_vgpu_init_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t,
unsigned long gfn,
int (*handler)(void *, u64, void *, int),
void *data)
{
INIT_HLIST_NODE(&t->node);
t->tracked = false;
t->gfn = gfn;
t->handler = handler;
t->data = data;
hash_add(vgpu->gtt.tracked_guest_page_hash_table, &t->node, t->gfn);
return 0;
}
/**
* intel_vgpu_clean_page_track - release a page track data structure
* @vgpu: a vGPU
* @t: a page track data structure
*
* This function is called before a user frees a page track data structure.
*/
void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t)
{
if (!hlist_unhashed(&t->node))
hash_del(&t->node);
if (t->tracked)
intel_gvt_hypervisor_disable_page_track(vgpu, t);
}
/**
* 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 init_guest_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *p, struct intel_vgpu_guest_page *p,
unsigned long gfn, unsigned long gfn,
int (*handler)(void *, u64, void *, int), int (*handler)(void *, u64, void *, int),
void *data) void *data)
{ {
INIT_HLIST_NODE(&p->node);
p->writeprotection = false;
p->gfn = gfn;
p->handler = handler;
p->data = data;
p->oos_page = NULL; p->oos_page = NULL;
p->write_cnt = 0; p->write_cnt = 0;
hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn); return intel_vgpu_init_page_track(vgpu, &p->track, gfn, handler, data);
return 0;
} }
static int detach_oos_page(struct intel_vgpu *vgpu, static int detach_oos_page(struct intel_vgpu *vgpu,
struct intel_vgpu_oos_page *oos_page); struct intel_vgpu_oos_page *oos_page);
/** static void clean_guest_page(struct intel_vgpu *vgpu,
* intel_vgpu_clean_guest_page - release the resource owned by guest page data
* structure
* @vgpu: a vGPU
* @p: a tracked guest page
*
* This function is called when user tries to stop tracking a guest memory
* page.
*/
void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *p) struct intel_vgpu_guest_page *p)
{ {
if (!hlist_unhashed(&p->node))
hash_del(&p->node);
if (p->oos_page) if (p->oos_page)
detach_oos_page(vgpu, p->oos_page); detach_oos_page(vgpu, p->oos_page);
if (p->writeprotection) intel_vgpu_clean_page_track(vgpu, &p->track);
intel_gvt_hypervisor_unset_wp_page(vgpu, p);
}
/**
* intel_vgpu_find_guest_page - find a guest page data structure by GFN.
* @vgpu: a vGPU
* @gfn: guest memory page frame number
*
* This function is called when emulation logic wants to know if a trapped GFN
* is a tracked guest page.
*
* Returns:
* Pointer to guest page data structure, NULL if failed.
*/
struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
struct intel_vgpu *vgpu, unsigned long gfn)
{
struct intel_vgpu_guest_page *p;
hash_for_each_possible(vgpu->gtt.guest_page_hash_table,
p, node, gfn) {
if (p->gfn == gfn)
return p;
}
return NULL;
} }
static inline int init_shadow_page(struct intel_vgpu *vgpu, static inline int init_shadow_page(struct intel_vgpu *vgpu,
@ -664,6 +679,9 @@ static inline struct intel_vgpu_shadow_page *find_shadow_page(
return NULL; return NULL;
} }
#define page_track_to_guest_page(ptr) \
container_of(ptr, struct intel_vgpu_guest_page, track)
#define guest_page_to_ppgtt_spt(ptr) \ #define guest_page_to_ppgtt_spt(ptr) \
container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page) container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page)
@ -697,7 +715,7 @@ static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type); trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type);
clean_shadow_page(spt->vgpu, &spt->shadow_page); clean_shadow_page(spt->vgpu, &spt->shadow_page);
intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page); clean_guest_page(spt->vgpu, &spt->guest_page);
list_del_init(&spt->post_shadow_list); list_del_init(&spt->post_shadow_list);
free_spt(spt); free_spt(spt);
@ -713,22 +731,24 @@ static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu)
ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp)); ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp));
} }
static int ppgtt_handle_guest_write_page_table_bytes(void *gp, static int ppgtt_handle_guest_write_page_table_bytes(
struct intel_vgpu_guest_page *gpt,
u64 pa, void *p_data, int bytes); u64 pa, void *p_data, int bytes);
static int ppgtt_write_protection_handler(void *gp, u64 pa, static int ppgtt_write_protection_handler(void *data, u64 pa,
void *p_data, int bytes) void *p_data, int bytes)
{ {
struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; struct intel_vgpu_page_track *t = data;
struct intel_vgpu_guest_page *p = page_track_to_guest_page(t);
int ret; int ret;
if (bytes != 4 && bytes != 8) if (bytes != 4 && bytes != 8)
return -EINVAL; return -EINVAL;
if (!gpt->writeprotection) if (!t->tracked)
return -EINVAL; return -EINVAL;
ret = ppgtt_handle_guest_write_page_table_bytes(gp, ret = ppgtt_handle_guest_write_page_table_bytes(p,
pa, p_data, bytes); pa, p_data, bytes);
if (ret) if (ret)
return ret; return ret;
@ -768,7 +788,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page(
goto err; goto err;
} }
ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page, ret = init_guest_page(vgpu, &spt->guest_page,
gfn, ppgtt_write_protection_handler, NULL); gfn, ppgtt_write_protection_handler, NULL);
if (ret) { if (ret) {
gvt_vgpu_err("fail to initialize guest page for spt\n"); gvt_vgpu_err("fail to initialize guest page for spt\n");
@ -856,7 +876,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
int v = atomic_read(&spt->refcount); int v = atomic_read(&spt->refcount);
trace_spt_change(spt->vgpu->id, "die", spt, trace_spt_change(spt->vgpu->id, "die", spt,
spt->guest_page.gfn, spt->shadow_page.type); spt->guest_page.track.gfn, spt->shadow_page.type);
trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1)); trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
@ -878,7 +898,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
} }
release: release:
trace_spt_change(spt->vgpu->id, "release", spt, trace_spt_change(spt->vgpu->id, "release", spt,
spt->guest_page.gfn, spt->shadow_page.type); spt->guest_page.track.gfn, spt->shadow_page.type);
ppgtt_free_shadow_page(spt); ppgtt_free_shadow_page(spt);
return 0; return 0;
fail: fail:
@ -895,6 +915,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
struct intel_vgpu_ppgtt_spt *s = NULL; struct intel_vgpu_ppgtt_spt *s = NULL;
struct intel_vgpu_guest_page *g; struct intel_vgpu_guest_page *g;
struct intel_vgpu_page_track *t;
int ret; int ret;
if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) { if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) {
@ -902,8 +923,9 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
goto fail; goto fail;
} }
g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); t = intel_vgpu_find_tracked_page(vgpu, ops->get_pfn(we));
if (g) { if (t) {
g = page_track_to_guest_page(t);
s = guest_page_to_ppgtt_spt(g); s = guest_page_to_ppgtt_spt(g);
ppgtt_get_shadow_page(s); ppgtt_get_shadow_page(s);
} else { } else {
@ -915,7 +937,8 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
goto fail; goto fail;
} }
ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page); ret = intel_gvt_hypervisor_enable_page_track(vgpu,
&s->guest_page.track);
if (ret) if (ret)
goto fail; goto fail;
@ -923,7 +946,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
if (ret) if (ret)
goto fail; goto fail;
trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn, trace_spt_change(vgpu->id, "new", s, s->guest_page.track.gfn,
s->shadow_page.type); s->shadow_page.type);
} }
return s; return s;
@ -953,7 +976,7 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
int ret; int ret;
trace_spt_change(spt->vgpu->id, "born", spt, trace_spt_change(spt->vgpu->id, "born", spt,
spt->guest_page.gfn, spt->shadow_page.type); spt->guest_page.track.gfn, spt->shadow_page.type);
if (gtt_type_is_pte_pt(spt->shadow_page.type)) { if (gtt_type_is_pte_pt(spt->shadow_page.type)) {
for_each_present_guest_entry(spt, &ge, i) { for_each_present_guest_entry(spt, &ge, i) {
@ -1082,7 +1105,7 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
index++) { index++) {
ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu); ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu);
ops->get_entry(NULL, &new, index, true, ops->get_entry(NULL, &new, index, true,
oos_page->guest_page->gfn << PAGE_SHIFT, vgpu); oos_page->guest_page->track.gfn << PAGE_SHIFT, vgpu);
if (old.val64 == new.val64 if (old.val64 == new.val64
&& !test_and_clear_bit(index, spt->post_shadow_bitmap)) && !test_and_clear_bit(index, spt->post_shadow_bitmap))
@ -1132,8 +1155,9 @@ static int attach_oos_page(struct intel_vgpu *vgpu,
struct intel_gvt *gvt = vgpu->gvt; struct intel_gvt *gvt = vgpu->gvt;
int ret; int ret;
ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT, ret = intel_gvt_hypervisor_read_gpa(vgpu,
oos_page->mem, GTT_PAGE_SIZE); gpt->track.gfn << GTT_PAGE_SHIFT,
oos_page->mem, GTT_PAGE_SIZE);
if (ret) if (ret)
return ret; return ret;
@ -1152,7 +1176,7 @@ static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu,
{ {
int ret; int ret;
ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt); ret = intel_gvt_hypervisor_enable_page_track(vgpu, &gpt->track);
if (ret) if (ret)
return ret; return ret;
@ -1200,7 +1224,7 @@ static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu,
gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head); list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head);
return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt); return intel_gvt_hypervisor_disable_page_track(vgpu, &gpt->track);
} }
/** /**
@ -1335,10 +1359,10 @@ int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu)
return 0; return 0;
} }
static int ppgtt_handle_guest_write_page_table_bytes(void *gp, static int ppgtt_handle_guest_write_page_table_bytes(
struct intel_vgpu_guest_page *gpt,
u64 pa, void *p_data, int bytes) u64 pa, void *p_data, int bytes)
{ {
struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp;
struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
struct intel_vgpu *vgpu = spt->vgpu; struct intel_vgpu *vgpu = spt->vgpu;
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
@ -2032,7 +2056,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
struct intel_vgpu_gtt *gtt = &vgpu->gtt; struct intel_vgpu_gtt *gtt = &vgpu->gtt;
struct intel_vgpu_mm *ggtt_mm; struct intel_vgpu_mm *ggtt_mm;
hash_init(gtt->guest_page_hash_table); hash_init(gtt->tracked_guest_page_hash_table);
hash_init(gtt->shadow_page_hash_table); hash_init(gtt->shadow_page_hash_table);
INIT_LIST_HEAD(&gtt->mm_list_head); INIT_LIST_HEAD(&gtt->mm_list_head);

View File

@ -193,18 +193,16 @@ struct intel_vgpu_scratch_pt {
unsigned long page_mfn; unsigned long page_mfn;
}; };
struct intel_vgpu_gtt { struct intel_vgpu_gtt {
struct intel_vgpu_mm *ggtt_mm; struct intel_vgpu_mm *ggtt_mm;
unsigned long active_ppgtt_mm_bitmap; unsigned long active_ppgtt_mm_bitmap;
struct list_head mm_list_head; struct list_head mm_list_head;
DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
atomic_t n_write_protected_guest_page; atomic_t n_tracked_guest_page;
struct list_head oos_page_list_head; struct list_head oos_page_list_head;
struct list_head post_shadow_list_head; struct list_head post_shadow_list_head;
struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX]; struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
}; };
extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
@ -228,12 +226,16 @@ struct intel_vgpu_shadow_page {
unsigned long mfn; unsigned long mfn;
}; };
struct intel_vgpu_guest_page { struct intel_vgpu_page_track {
struct hlist_node node; struct hlist_node node;
bool writeprotection; bool tracked;
unsigned long gfn; unsigned long gfn;
int (*handler)(void *, u64, void *, int); int (*handler)(void *, u64, void *, int);
void *data; void *data;
};
struct intel_vgpu_guest_page {
struct intel_vgpu_page_track track;
unsigned long write_cnt; unsigned long write_cnt;
struct intel_vgpu_oos_page *oos_page; struct intel_vgpu_oos_page *oos_page;
}; };
@ -258,22 +260,16 @@ struct intel_vgpu_ppgtt_spt {
struct list_head post_shadow_list; struct list_head post_shadow_list;
}; };
int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, int intel_vgpu_init_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page, struct intel_vgpu_page_track *t,
unsigned long gfn, unsigned long gfn,
int (*handler)(void *gp, u64, void *, int), int (*handler)(void *gp, u64, void *, int),
void *data); void *data);
void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page); struct intel_vgpu_page_track *t);
int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, struct intel_vgpu_page_track *intel_vgpu_find_tracked_page(
struct intel_vgpu_guest_page *guest_page);
void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page);
struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
struct intel_vgpu *vgpu, unsigned long gfn); struct intel_vgpu *vgpu, unsigned long gfn);
int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);

View File

@ -117,18 +117,18 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
else else
memcpy(pt, p_data, bytes); memcpy(pt, p_data, bytes);
} else if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { } else if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_guest_page *gp; struct intel_vgpu_page_track *t;
/* Since we enter the failsafe mode early during guest boot, /* Since we enter the failsafe mode early during guest boot,
* guest may not have chance to set up its ppgtt table, so * guest may not have chance to set up its ppgtt table, so
* there should not be any wp pages for guest. Keep the wp * there should not be any wp pages for guest. Keep the wp
* related code here in case we need to handle it in furture. * related code here in case we need to handle it in furture.
*/ */
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (gp) { if (t) {
/* remove write protection to prevent furture traps */ /* remove write protection to prevent furture traps */
intel_vgpu_clean_guest_page(vgpu, gp); intel_vgpu_clean_page_track(vgpu, t);
if (read) if (read)
intel_gvt_hypervisor_read_gpa(vgpu, pa, intel_gvt_hypervisor_read_gpa(vgpu, pa,
p_data, bytes); p_data, bytes);
@ -170,17 +170,17 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
return ret; return ret;
} }
if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_guest_page *gp; struct intel_vgpu_page_track *t;
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (gp) { if (t) {
ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,
p_data, bytes); p_data, bytes);
if (ret) { if (ret) {
gvt_vgpu_err("guest page read error %d, " gvt_vgpu_err("guest page read error %d, "
"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
ret, gp->gfn, pa, *(u32 *)p_data, ret, t->gfn, pa, *(u32 *)p_data,
bytes); bytes);
} }
mutex_unlock(&gvt->lock); mutex_unlock(&gvt->lock);
@ -267,17 +267,17 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
return ret; return ret;
} }
if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_guest_page *gp; struct intel_vgpu_page_track *t;
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (gp) { if (t) {
ret = gp->handler(gp, pa, p_data, bytes); ret = t->handler(t, pa, p_data, bytes);
if (ret) { if (ret) {
gvt_err("guest page write error %d, " gvt_err("guest page write error %d, "
"gfn 0x%lx, pa 0x%llx, " "gfn 0x%lx, pa 0x%llx, "
"var 0x%x, len %d\n", "var 0x%x, len %d\n",
ret, gp->gfn, pa, ret, t->gfn, pa,
*(u32 *)p_data, bytes); *(u32 *)p_data, bytes);
} }
mutex_unlock(&gvt->lock); mutex_unlock(&gvt->lock);

View File

@ -154,51 +154,53 @@ static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p)
} }
/** /**
* intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected * intel_gvt_hypervisor_enable - set a guest page to write-protected
* @vgpu: a vGPU * @vgpu: a vGPU
* @p: intel_vgpu_guest_page * @t: page track data structure
* *
* Returns: * Returns:
* Zero on success, negative error code if failed. * Zero on success, negative error code if failed.
*/ */
static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu, static inline int intel_gvt_hypervisor_enable_page_track(
struct intel_vgpu_guest_page *p) struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t)
{ {
int ret; int ret;
if (p->writeprotection) if (t->tracked)
return 0; return 0;
ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn); ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, t->gfn);
if (ret) if (ret)
return ret; return ret;
p->writeprotection = true; t->tracked = true;
atomic_inc(&vgpu->gtt.n_write_protected_guest_page); atomic_inc(&vgpu->gtt.n_tracked_guest_page);
return 0; return 0;
} }
/** /**
* intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a * intel_gvt_hypervisor_disable_page_track - remove the write-protection of a
* guest page * guest page
* @vgpu: a vGPU * @vgpu: a vGPU
* @p: intel_vgpu_guest_page * @t: page track data structure
* *
* Returns: * Returns:
* Zero on success, negative error code if failed. * Zero on success, negative error code if failed.
*/ */
static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu, static inline int intel_gvt_hypervisor_disable_page_track(
struct intel_vgpu_guest_page *p) struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t)
{ {
int ret; int ret;
if (!p->writeprotection) if (!t->tracked)
return 0; return 0;
ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn); ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, t->gfn);
if (ret) if (ret)
return ret; return ret;
p->writeprotection = false; t->tracked = false;
atomic_dec(&vgpu->gtt.n_write_protected_guest_page); atomic_dec(&vgpu->gtt.n_tracked_guest_page);
return 0; return 0;
} }