Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
Note: File does not exist in v4.6.
  1/*
  2 * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 21 * SOFTWARE.
 22 */
 23#include "i915_drv.h"
 24#include "gvt.h"
 25
 26/**
 27 * intel_vgpu_find_page_track - find page track rcord of guest page
 28 * @vgpu: a vGPU
 29 * @gfn: the gfn of guest page
 30 *
 31 * Returns:
 32 * A pointer to struct intel_vgpu_page_track if found, else NULL returned.
 33 */
 34struct intel_vgpu_page_track *intel_vgpu_find_page_track(
 35		struct intel_vgpu *vgpu, unsigned long gfn)
 36{
 37	return radix_tree_lookup(&vgpu->page_track_tree, gfn);
 38}
 39
 40/**
 41 * intel_vgpu_register_page_track - register a guest page to be tacked
 42 * @vgpu: a vGPU
 43 * @gfn: the gfn of guest page
 44 *
 45 * Returns:
 46 * zero on success, negative error code if failed.
 47 */
 48int intel_vgpu_register_page_track(struct intel_vgpu *vgpu, unsigned long gfn,
 49		gvt_page_track_handler_t handler, void *priv)
 50{
 51	struct intel_vgpu_page_track *track;
 52	int ret;
 53
 54	track = intel_vgpu_find_page_track(vgpu, gfn);
 55	if (track)
 56		return -EEXIST;
 57
 58	track = kzalloc(sizeof(*track), GFP_KERNEL);
 59	if (!track)
 60		return -ENOMEM;
 61
 62	track->handler = handler;
 63	track->priv_data = priv;
 64
 65	ret = radix_tree_insert(&vgpu->page_track_tree, gfn, track);
 66	if (ret) {
 67		kfree(track);
 68		return ret;
 69	}
 70
 71	return 0;
 72}
 73
 74/**
 75 * intel_vgpu_unregister_page_track - unregister the tracked guest page
 76 * @vgpu: a vGPU
 77 * @gfn: the gfn of guest page
 78 *
 79 */
 80void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
 81		unsigned long gfn)
 82{
 83	struct intel_vgpu_page_track *track;
 84
 85	track = radix_tree_delete(&vgpu->page_track_tree, gfn);
 86	if (track) {
 87		if (track->tracked)
 88			intel_gvt_hypervisor_disable_page_track(vgpu, gfn);
 89		kfree(track);
 90	}
 91}
 92
 93/**
 94 * intel_vgpu_enable_page_track - set write-protection on guest page
 95 * @vgpu: a vGPU
 96 * @gfn: the gfn of guest page
 97 *
 98 * Returns:
 99 * zero on success, negative error code if failed.
100 */
101int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
102{
103	struct intel_vgpu_page_track *track;
104	int ret;
105
106	track = intel_vgpu_find_page_track(vgpu, gfn);
107	if (!track)
108		return -ENXIO;
109
110	if (track->tracked)
111		return 0;
112
113	ret = intel_gvt_hypervisor_enable_page_track(vgpu, gfn);
114	if (ret)
115		return ret;
116	track->tracked = true;
117	return 0;
118}
119
120/**
121 * intel_vgpu_enable_page_track - cancel write-protection on guest page
122 * @vgpu: a vGPU
123 * @gfn: the gfn of guest page
124 *
125 * Returns:
126 * zero on success, negative error code if failed.
127 */
128int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
129{
130	struct intel_vgpu_page_track *track;
131	int ret;
132
133	track = intel_vgpu_find_page_track(vgpu, gfn);
134	if (!track)
135		return -ENXIO;
136
137	if (!track->tracked)
138		return 0;
139
140	ret = intel_gvt_hypervisor_disable_page_track(vgpu, gfn);
141	if (ret)
142		return ret;
143	track->tracked = false;
144	return 0;
145}
146
147/**
148 * intel_vgpu_page_track_handler - called when write to write-protected page
149 * @vgpu: a vGPU
150 * @gpa: the gpa of this write
151 * @data: the writed data
152 * @bytes: the length of this write
153 *
154 * Returns:
155 * zero on success, negative error code if failed.
156 */
157int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
158		void *data, unsigned int bytes)
159{
160	struct intel_gvt *gvt = vgpu->gvt;
161	struct intel_vgpu_page_track *page_track;
162	int ret = 0;
163
164	mutex_lock(&gvt->lock);
165
166	page_track = intel_vgpu_find_page_track(vgpu, gpa >> PAGE_SHIFT);
167	if (!page_track) {
168		ret = -ENXIO;
169		goto out;
170	}
171
172	if (unlikely(vgpu->failsafe)) {
173		/* Remove write protection to prevent furture traps. */
174		intel_vgpu_disable_page_track(vgpu, gpa >> PAGE_SHIFT);
175	} else {
176		ret = page_track->handler(page_track, gpa, data, bytes);
177		if (ret)
178			gvt_err("guest page write error, gpa %llx\n", gpa);
179	}
180
181out:
182	mutex_unlock(&gvt->lock);
183	return ret;
184}