Commit 7d1e5cdf authored by Zhi Wang's avatar Zhi Wang Committed by Zhenyu Wang

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: default avatarZhi Wang <zhi.a.wang@intel.com>
parent f52c380a
This diff is collapsed.
...@@ -193,18 +193,16 @@ struct intel_vgpu_scratch_pt { ...@@ -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 { ...@@ -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 { ...@@ -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_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_page_track *intel_vgpu_find_tracked_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);
......
...@@ -117,18 +117,18 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, ...@@ -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, ...@@ -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, ...@@ -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);
......
...@@ -154,51 +154,53 @@ static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) ...@@ -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;
} }
......
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