brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · e16e0d4 Raw
336 lines · c
1/*2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice (including the next12 * paragraph) shall be included in all copies or substantial portions of the13 * Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19 * 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 THE21 * SOFTWARE.22 *23 * Authors:24 *    Ke Yu25 *    Kevin Tian <kevin.tian@intel.com>26 *    Dexuan Cui27 *28 * Contributors:29 *    Tina Zhang <tina.zhang@intel.com>30 *    Min He <min.he@intel.com>31 *    Niu Bing <bing.niu@intel.com>32 *    Zhi Wang <zhi.a.wang@intel.com>33 *34 */35 36#include <linux/vmalloc.h>37#include "i915_drv.h"38#include "i915_reg.h"39#include "gvt.h"40 41#include "display/bxt_dpio_phy_regs.h"42#include "display/intel_dpio_phy.h"43#include "gt/intel_gt_regs.h"44 45/**46 * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset47 * @vgpu: a vGPU48 * @gpa: guest physical address49 *50 * Returns:51 * Zero on success, negative error code if failed52 */53int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)54{55	u64 gttmmio_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_0);56	return gpa - gttmmio_gpa;57}58 59#define reg_is_mmio(gvt, reg)  \60	(reg >= 0 && reg < gvt->device_info.mmio_size)61 62#define reg_is_gtt(gvt, reg)   \63	(reg >= gvt->device_info.gtt_start_offset \64	 && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))65 66static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, u64 pa,67		void *p_data, unsigned int bytes, bool read)68{69	struct intel_gvt *gvt = NULL;70	void *pt = NULL;71	unsigned int offset = 0;72 73	if (!vgpu || !p_data)74		return;75 76	gvt = vgpu->gvt;77	mutex_lock(&vgpu->vgpu_lock);78	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);79	if (reg_is_mmio(gvt, offset)) {80		if (read)81			intel_vgpu_default_mmio_read(vgpu, offset, p_data,82					bytes);83		else84			intel_vgpu_default_mmio_write(vgpu, offset, p_data,85					bytes);86	} else if (reg_is_gtt(gvt, offset)) {87		offset -= gvt->device_info.gtt_start_offset;88		pt = vgpu->gtt.ggtt_mm->ggtt_mm.virtual_ggtt + offset;89		if (read)90			memcpy(p_data, pt, bytes);91		else92			memcpy(pt, p_data, bytes);93 94	}95	mutex_unlock(&vgpu->vgpu_lock);96}97 98/**99 * intel_vgpu_emulate_mmio_read - emulate MMIO read100 * @vgpu: a vGPU101 * @pa: guest physical address102 * @p_data: data return buffer103 * @bytes: access data length104 *105 * Returns:106 * Zero on success, negative error code if failed107 */108int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, u64 pa,109		void *p_data, unsigned int bytes)110{111	struct intel_gvt *gvt = vgpu->gvt;112	struct drm_i915_private *i915 = gvt->gt->i915;113	unsigned int offset = 0;114	int ret = -EINVAL;115 116	if (vgpu->failsafe) {117		failsafe_emulate_mmio_rw(vgpu, pa, p_data, bytes, true);118		return 0;119	}120	mutex_lock(&vgpu->vgpu_lock);121 122	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);123 124	if (drm_WARN_ON(&i915->drm, bytes > 8))125		goto err;126 127	if (reg_is_gtt(gvt, offset)) {128		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4) &&129				!IS_ALIGNED(offset, 8)))130			goto err;131		if (drm_WARN_ON(&i915->drm, bytes != 4 && bytes != 8))132			goto err;133		if (drm_WARN_ON(&i915->drm,134				!reg_is_gtt(gvt, offset + bytes - 1)))135			goto err;136 137		ret = intel_vgpu_emulate_ggtt_mmio_read(vgpu, offset,138				p_data, bytes);139		if (ret)140			goto err;141		goto out;142	}143 144	if (drm_WARN_ON_ONCE(&i915->drm, !reg_is_mmio(gvt, offset))) {145		ret = intel_gvt_read_gpa(vgpu, pa, p_data, bytes);146		goto out;147	}148 149	if (drm_WARN_ON(&i915->drm, !reg_is_mmio(gvt, offset + bytes - 1)))150		goto err;151 152	if (!intel_gvt_mmio_is_unalign(gvt, offset)) {153		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, bytes)))154			goto err;155	}156 157	ret = intel_vgpu_mmio_reg_rw(vgpu, offset, p_data, bytes, true);158	if (ret < 0)159		goto err;160 161	intel_gvt_mmio_set_accessed(gvt, offset);162	ret = 0;163	goto out;164 165err:166	gvt_vgpu_err("fail to emulate MMIO read %08x len %d\n",167			offset, bytes);168out:169	mutex_unlock(&vgpu->vgpu_lock);170	return ret;171}172 173/**174 * intel_vgpu_emulate_mmio_write - emulate MMIO write175 * @vgpu: a vGPU176 * @pa: guest physical address177 * @p_data: write data buffer178 * @bytes: access data length179 *180 * Returns:181 * Zero on success, negative error code if failed182 */183int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, u64 pa,184		void *p_data, unsigned int bytes)185{186	struct intel_gvt *gvt = vgpu->gvt;187	struct drm_i915_private *i915 = gvt->gt->i915;188	unsigned int offset = 0;189	int ret = -EINVAL;190 191	if (vgpu->failsafe) {192		failsafe_emulate_mmio_rw(vgpu, pa, p_data, bytes, false);193		return 0;194	}195 196	mutex_lock(&vgpu->vgpu_lock);197 198	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);199 200	if (drm_WARN_ON(&i915->drm, bytes > 8))201		goto err;202 203	if (reg_is_gtt(gvt, offset)) {204		if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4) &&205				!IS_ALIGNED(offset, 8)))206			goto err;207		if (drm_WARN_ON(&i915->drm, bytes != 4 && bytes != 8))208			goto err;209		if (drm_WARN_ON(&i915->drm,210				!reg_is_gtt(gvt, offset + bytes - 1)))211			goto err;212 213		ret = intel_vgpu_emulate_ggtt_mmio_write(vgpu, offset,214				p_data, bytes);215		if (ret)216			goto err;217		goto out;218	}219 220	if (drm_WARN_ON_ONCE(&i915->drm, !reg_is_mmio(gvt, offset))) {221		ret = intel_gvt_write_gpa(vgpu, pa, p_data, bytes);222		goto out;223	}224 225	ret = intel_vgpu_mmio_reg_rw(vgpu, offset, p_data, bytes, false);226	if (ret < 0)227		goto err;228 229	intel_gvt_mmio_set_accessed(gvt, offset);230	ret = 0;231	goto out;232err:233	gvt_vgpu_err("fail to emulate MMIO write %08x len %d\n", offset,234		     bytes);235out:236	mutex_unlock(&vgpu->vgpu_lock);237	return ret;238}239 240 241/**242 * intel_vgpu_reset_mmio - reset virtual MMIO space243 * @vgpu: a vGPU244 * @dmlr: whether this is device model level reset245 */246void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr)247{248	struct intel_gvt *gvt = vgpu->gvt;249	const struct intel_gvt_device_info *info = &gvt->device_info;250	void  *mmio = gvt->firmware.mmio;251 252	if (dmlr) {253		memcpy(vgpu->mmio.vreg, mmio, info->mmio_size);254 255		vgpu_vreg_t(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;256 257		/* set the bit 0:2(Core C-State ) to C0 */258		vgpu_vreg_t(vgpu, GEN6_GT_CORE_STATUS) = 0;259 260		/* uc reset hw expect GS_MIA_IN_RESET */261		vgpu_vreg_t(vgpu, GUC_STATUS) |= GS_MIA_IN_RESET;262 263		if (IS_BROXTON(vgpu->gvt->gt->i915)) {264			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &=265				    ~(BIT(0) | BIT(1));266			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &=267				    ~PHY_POWER_GOOD;268			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) &=269				    ~PHY_POWER_GOOD;270			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) &=271				    ~BIT(30);272			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) &=273				    ~BIT(30);274			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) &=275				    ~BXT_PHY_LANE_ENABLED;276			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) |=277				    BXT_PHY_CMNLANE_POWERDOWN_ACK |278				    BXT_PHY_LANE_POWERDOWN_ACK;279			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) &=280				    ~BXT_PHY_LANE_ENABLED;281			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) |=282				    BXT_PHY_CMNLANE_POWERDOWN_ACK |283				    BXT_PHY_LANE_POWERDOWN_ACK;284			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) &=285				    ~BXT_PHY_LANE_ENABLED;286			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=287				    BXT_PHY_CMNLANE_POWERDOWN_ACK |288				    BXT_PHY_LANE_POWERDOWN_ACK;289			vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |=290				SKL_FUSE_DOWNLOAD_STATUS |291				SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |292				SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |293				SKL_FUSE_PG_DIST_STATUS(SKL_PG2);294		}295	} else {296#define GVT_GEN8_MMIO_RESET_OFFSET		(0x44200)297		/* only reset the engine related, so starting with 0x44200298		 * interrupt include DE,display mmio related will not be299		 * touched300		 */301		memcpy(vgpu->mmio.vreg, mmio, GVT_GEN8_MMIO_RESET_OFFSET);302	}303 304}305 306/**307 * intel_vgpu_init_mmio - init MMIO  space308 * @vgpu: a vGPU309 *310 * Returns:311 * Zero on success, negative error code if failed312 */313int intel_vgpu_init_mmio(struct intel_vgpu *vgpu)314{315	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;316 317	vgpu->mmio.vreg = vzalloc(info->mmio_size);318	if (!vgpu->mmio.vreg)319		return -ENOMEM;320 321	intel_vgpu_reset_mmio(vgpu, true);322 323	return 0;324}325 326/**327 * intel_vgpu_clean_mmio - clean MMIO space328 * @vgpu: a vGPU329 *330 */331void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu)332{333	vfree(vgpu->mmio.vreg);334	vgpu->mmio.vreg = NULL;335}336