xref: /linux/drivers/gpu/drm/i915/gvt/cfg_space.c (revision 815e260a18a3af4dab59025ee99a7156c0e8b5e0)
1 /*
2  * Copyright(c) 2011-2016 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  * Authors:
24  *    Eddie Dong <eddie.dong@intel.com>
25  *    Jike Song <jike.song@intel.com>
26  *
27  * Contributors:
28  *    Zhi Wang <zhi.a.wang@intel.com>
29  *    Min He <min.he@intel.com>
30  *    Bing Niu <bing.niu@intel.com>
31  *
32  */
33 
34 #include <drm/drm_print.h>
35 
36 #include "i915_drv.h"
37 #include "gvt.h"
38 #include "intel_pci_config.h"
39 
40 enum {
41 	INTEL_GVT_PCI_BAR_GTTMMIO = 0,
42 	INTEL_GVT_PCI_BAR_APERTURE,
43 	INTEL_GVT_PCI_BAR_PIO,
44 	INTEL_GVT_PCI_BAR_MAX,
45 };
46 
47 /* bitmap for writable bits (RW or RW1C bits, but cannot co-exist in one
48  * byte) byte by byte in standard pci configuration space. (not the full
49  * 256 bytes.)
50  */
51 static const u8 pci_cfg_space_rw_bmp[PCI_INTERRUPT_LINE + 4] = {
52 	[PCI_COMMAND]		= 0xff, 0x07,
53 	[PCI_STATUS]		= 0x00, 0xf9, /* the only one RW1C byte */
54 	[PCI_CACHE_LINE_SIZE]	= 0xff,
55 	[PCI_BASE_ADDRESS_0 ... PCI_CARDBUS_CIS - 1] = 0xff,
56 	[PCI_ROM_ADDRESS]	= 0x01, 0xf8, 0xff, 0xff,
57 	[PCI_INTERRUPT_LINE]	= 0xff,
58 };
59 
60 /**
61  * vgpu_pci_cfg_mem_write - write virtual cfg space memory
62  * @vgpu: target vgpu
63  * @off: offset
64  * @src: src ptr to write
65  * @bytes: number of bytes
66  *
67  * Use this function to write virtual cfg space memory.
68  * For standard cfg space, only RW bits can be changed,
69  * and we emulates the RW1C behavior of PCI_STATUS register.
70  */
71 static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off,
72 				   u8 *src, unsigned int bytes)
73 {
74 	u8 *cfg_base = vgpu_cfg_space(vgpu);
75 	u8 mask, new, old;
76 	pci_power_t pwr;
77 	int i = 0;
78 
79 	for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) {
80 		mask = pci_cfg_space_rw_bmp[off + i];
81 		old = cfg_base[off + i];
82 		new = src[i] & mask;
83 
84 		/**
85 		 * The PCI_STATUS high byte has RW1C bits, here
86 		 * emulates clear by writing 1 for these bits.
87 		 * Writing a 0b to RW1C bits has no effect.
88 		 */
89 		if (off + i == PCI_STATUS + 1)
90 			new = (~new & old) & mask;
91 
92 		cfg_base[off + i] = (old & ~mask) | new;
93 	}
94 
95 	/* For other configuration space directly copy as it is. */
96 	if (i < bytes)
97 		memcpy(cfg_base + off + i, src + i, bytes - i);
98 
99 	if (off == vgpu->cfg_space.pmcsr_off && vgpu->cfg_space.pmcsr_off) {
100 		pwr = (pci_power_t __force)(*(u16*)(&vgpu_cfg_space(vgpu)[off])
101 			& PCI_PM_CTRL_STATE_MASK);
102 		if (pwr == PCI_D3hot)
103 			vgpu->d3_entered = true;
104 		gvt_dbg_core("vgpu-%d power status changed to %d\n",
105 			     vgpu->id, pwr);
106 	}
107 }
108 
109 /**
110  * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
111  * @vgpu: target vgpu
112  * @offset: offset
113  * @p_data: return data ptr
114  * @bytes: number of bytes to read
115  *
116  * Returns:
117  * Zero on success, negative error code if failed.
118  */
119 int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
120 	void *p_data, unsigned int bytes)
121 {
122 	struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
123 
124 	if (drm_WARN_ON(&i915->drm, bytes > 4))
125 		return -EINVAL;
126 
127 	if (drm_WARN_ON(&i915->drm,
128 			offset + bytes > vgpu->gvt->device_info.cfg_space_size))
129 		return -EINVAL;
130 
131 	memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes);
132 	return 0;
133 }
134 
135 static void map_aperture(struct intel_vgpu *vgpu, bool map)
136 {
137 	if (map != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
138 		vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
139 }
140 
141 static void trap_gttmmio(struct intel_vgpu *vgpu, bool trap)
142 {
143 	if (trap != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked)
144 		vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap;
145 }
146 
147 static int emulate_pci_command_write(struct intel_vgpu *vgpu,
148 	unsigned int offset, void *p_data, unsigned int bytes)
149 {
150 	u8 old = vgpu_cfg_space(vgpu)[offset];
151 	u8 new = *(u8 *)p_data;
152 	u8 changed = old ^ new;
153 
154 	vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
155 	if (!(changed & PCI_COMMAND_MEMORY))
156 		return 0;
157 
158 	if (old & PCI_COMMAND_MEMORY) {
159 		trap_gttmmio(vgpu, false);
160 		map_aperture(vgpu, false);
161 	} else {
162 		trap_gttmmio(vgpu, true);
163 		map_aperture(vgpu, true);
164 	}
165 
166 	return 0;
167 }
168 
169 static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu,
170 	unsigned int offset, void *p_data, unsigned int bytes)
171 {
172 	u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset);
173 	u32 new = *(u32 *)(p_data);
174 
175 	if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK)
176 		/* We don't have rom, return size of 0. */
177 		*pval = 0;
178 	else
179 		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
180 	return 0;
181 }
182 
183 static void emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
184 	void *p_data, unsigned int bytes)
185 {
186 	u32 new = *(u32 *)(p_data);
187 	bool lo = IS_ALIGNED(offset, 8);
188 	u64 size;
189 	bool mmio_enabled =
190 		vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY;
191 	struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar;
192 
193 	/*
194 	 * Power-up software can determine how much address
195 	 * space the device requires by writing a value of
196 	 * all 1's to the register and then reading the value
197 	 * back. The device will return 0's in all don't-care
198 	 * address bits.
199 	 */
200 	if (new == 0xffffffff) {
201 		switch (offset) {
202 		case PCI_BASE_ADDRESS_0:
203 		case PCI_BASE_ADDRESS_1:
204 			size = ~(bars[INTEL_GVT_PCI_BAR_GTTMMIO].size -1);
205 			intel_vgpu_write_pci_bar(vgpu, offset,
206 						size >> (lo ? 0 : 32), lo);
207 			/*
208 			 * Untrap the BAR, since guest hasn't configured a
209 			 * valid GPA
210 			 */
211 			trap_gttmmio(vgpu, false);
212 			break;
213 		case PCI_BASE_ADDRESS_2:
214 		case PCI_BASE_ADDRESS_3:
215 			size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1);
216 			intel_vgpu_write_pci_bar(vgpu, offset,
217 						size >> (lo ? 0 : 32), lo);
218 			map_aperture(vgpu, false);
219 			break;
220 		default:
221 			/* Unimplemented BARs */
222 			intel_vgpu_write_pci_bar(vgpu, offset, 0x0, false);
223 		}
224 	} else {
225 		switch (offset) {
226 		case PCI_BASE_ADDRESS_0:
227 		case PCI_BASE_ADDRESS_1:
228 			/*
229 			 * Untrap the old BAR first, since guest has
230 			 * re-configured the BAR
231 			 */
232 			trap_gttmmio(vgpu, false);
233 			intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
234 			trap_gttmmio(vgpu, mmio_enabled);
235 			break;
236 		case PCI_BASE_ADDRESS_2:
237 		case PCI_BASE_ADDRESS_3:
238 			map_aperture(vgpu, false);
239 			intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
240 			map_aperture(vgpu, mmio_enabled);
241 			break;
242 		default:
243 			intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
244 		}
245 	}
246 }
247 
248 /**
249  * intel_vgpu_emulate_cfg_write - emulate vGPU configuration space write
250  * @vgpu: target vgpu
251  * @offset: offset
252  * @p_data: write data ptr
253  * @bytes: number of bytes to write
254  *
255  * Returns:
256  * Zero on success, negative error code if failed.
257  */
258 int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
259 	void *p_data, unsigned int bytes)
260 {
261 	struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
262 	int ret;
263 
264 	if (drm_WARN_ON(&i915->drm, bytes > 4))
265 		return -EINVAL;
266 
267 	if (drm_WARN_ON(&i915->drm,
268 			offset + bytes > vgpu->gvt->device_info.cfg_space_size))
269 		return -EINVAL;
270 
271 	/* First check if it's PCI_COMMAND */
272 	if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) {
273 		if (drm_WARN_ON(&i915->drm, bytes > 2))
274 			return -EINVAL;
275 		return emulate_pci_command_write(vgpu, offset, p_data, bytes);
276 	}
277 
278 	switch (rounddown(offset, 4)) {
279 	case PCI_ROM_ADDRESS:
280 		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4)))
281 			return -EINVAL;
282 		return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes);
283 
284 	case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
285 		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4)))
286 			return -EINVAL;
287 		emulate_pci_bar_write(vgpu, offset, p_data, bytes);
288 		break;
289 	case INTEL_GVT_PCI_SWSCI:
290 		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4)))
291 			return -EINVAL;
292 		ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data);
293 		if (ret)
294 			return ret;
295 		break;
296 
297 	case INTEL_GVT_PCI_OPREGION:
298 		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4)))
299 			return -EINVAL;
300 		ret = intel_vgpu_opregion_base_write_handler(vgpu,
301 						   *(u32 *)p_data);
302 		if (ret)
303 			return ret;
304 
305 		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
306 		break;
307 	default:
308 		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
309 		break;
310 	}
311 	return 0;
312 }
313 
314 /**
315  * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU
316  *
317  * @vgpu: a vGPU
318  * @primary: is the vGPU presented as primary
319  *
320  */
321 void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
322 			       bool primary)
323 {
324 	struct intel_gvt *gvt = vgpu->gvt;
325 	struct pci_dev *pdev = to_pci_dev(gvt->gt->i915->drm.dev);
326 	const struct intel_gvt_device_info *info = &gvt->device_info;
327 	u16 *gmch_ctl;
328 	u8 next;
329 
330 	memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
331 	       info->cfg_space_size);
332 
333 	if (!primary) {
334 		vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
335 			INTEL_GVT_PCI_CLASS_VGA_OTHER;
336 		vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
337 			INTEL_GVT_PCI_CLASS_VGA_OTHER;
338 	}
339 
340 	/* Show guest that there isn't any stolen memory.*/
341 	gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
342 	*gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
343 
344 	intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
345 				 gvt_aperture_pa_base(gvt), true);
346 
347 	vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
348 					     | PCI_COMMAND_MEMORY
349 					     | PCI_COMMAND_MASTER);
350 	/*
351 	 * Clear the bar upper 32bit and let guest to assign the new value
352 	 */
353 	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
354 	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
355 	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_4, 0, 8);
356 	memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
357 
358 	vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size =
359 		pci_resource_len(pdev, GEN4_GTTMMADR_BAR);
360 	vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size =
361 		pci_resource_len(pdev, GEN4_GMADR_BAR);
362 
363 	memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4);
364 
365 	/* PM Support */
366 	vgpu->cfg_space.pmcsr_off = 0;
367 	if (vgpu_cfg_space(vgpu)[PCI_STATUS] & PCI_STATUS_CAP_LIST) {
368 		next = vgpu_cfg_space(vgpu)[PCI_CAPABILITY_LIST];
369 		do {
370 			if (vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_ID] == PCI_CAP_ID_PM) {
371 				vgpu->cfg_space.pmcsr_off = next + PCI_PM_CTRL;
372 				break;
373 			}
374 			next = vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_NEXT];
375 		} while (next);
376 	}
377 }
378 
379 /**
380  * intel_vgpu_reset_cfg_space - reset vGPU configuration space
381  *
382  * @vgpu: a vGPU
383  *
384  */
385 void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)
386 {
387 	u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];
388 	bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=
389 				INTEL_GVT_PCI_CLASS_VGA_OTHER;
390 
391 	if (cmd & PCI_COMMAND_MEMORY) {
392 		trap_gttmmio(vgpu, false);
393 		map_aperture(vgpu, false);
394 	}
395 
396 	/**
397 	 * Currently we only do such reset when vGPU is not
398 	 * owned by any VM, so we simply restore entire cfg
399 	 * space to default value.
400 	 */
401 	intel_vgpu_init_cfg_space(vgpu, primary);
402 }
403