/* * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Authors: * Kevin Tian <[email protected]> * Zhi Wang <[email protected]> * * Contributors: * Min he <[email protected]> * */ #include <linux/eventfd.h> #include "i915_drv.h" #include "i915_reg.h" #include "gvt.h" #include "trace.h" struct intel_gvt_irq_info { … }; struct intel_gvt_irq_map { … }; /* common offset among interrupt control registers */ #define regbase_to_isr(base) … #define regbase_to_imr(base) … #define regbase_to_iir(base) … #define regbase_to_ier(base) … #define iir_to_regbase(iir) … #define ier_to_regbase(ier) … #define get_event_virt_handler(irq, e) … #define get_irq_info(irq, e) … #define irq_to_gvt(irq) … static void update_upstream_irq(struct intel_vgpu *vgpu, struct intel_gvt_irq_info *info); static const char * const irq_name[INTEL_GVT_EVENT_MAX] = …; static inline struct intel_gvt_irq_info *regbase_to_irq_info( struct intel_gvt *gvt, unsigned int reg) { … } /** * intel_vgpu_reg_imr_handler - Generic IMR register emulation write handler * @vgpu: a vGPU * @reg: register offset written by guest * @p_data: register data written by guest * @bytes: register data length * * This function is used to emulate the generic IMR register bit change * behavior. * * Returns: * Zero on success, negative error code if failed. * */ int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, unsigned int reg, void *p_data, unsigned int bytes) { … } /** * intel_vgpu_reg_master_irq_handler - master IRQ write emulation handler * @vgpu: a vGPU * @reg: register offset written by guest * @p_data: register data written by guest * @bytes: register data length * * This function is used to emulate the master IRQ register on gen8+. * * Returns: * Zero on success, negative error code if failed. * */ int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, unsigned int reg, void *p_data, unsigned int bytes) { … } /** * intel_vgpu_reg_ier_handler - Generic IER write emulation handler * @vgpu: a vGPU * @reg: register offset written by guest * @p_data: register data written by guest * @bytes: register data length * * This function is used to emulate the generic IER register behavior. * * Returns: * Zero on success, negative error code if failed. * */ int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu, unsigned int reg, void *p_data, unsigned int bytes) { … } /** * intel_vgpu_reg_iir_handler - Generic IIR write emulation handler * @vgpu: a vGPU * @reg: register offset written by guest * @p_data: register data written by guest * @bytes: register data length * * This function is used to emulate the generic IIR register behavior. * * Returns: * Zero on success, negative error code if failed. * */ int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg, void *p_data, unsigned int bytes) { … } static struct intel_gvt_irq_map gen8_irq_map[] = …; static void update_upstream_irq(struct intel_vgpu *vgpu, struct intel_gvt_irq_info *info) { … } static void init_irq_map(struct intel_gvt_irq *irq) { … } /* =======================vEvent injection===================== */ #define MSI_CAP_CONTROL(offset) … #define MSI_CAP_ADDRESS(offset) … #define MSI_CAP_DATA(offset) … #define MSI_CAP_EN … static void inject_virtual_interrupt(struct intel_vgpu *vgpu) { … } static void propagate_event(struct intel_gvt_irq *irq, enum intel_gvt_event_type event, struct intel_vgpu *vgpu) { … } /* =======================vEvent Handlers===================== */ static void handle_default_event_virt(struct intel_gvt_irq *irq, enum intel_gvt_event_type event, struct intel_vgpu *vgpu) { … } /* =====================GEN specific logic======================= */ /* GEN8 interrupt routines. */ #define DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(regname, regbase) … DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt0, GEN8_GT_ISR(0)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt1, GEN8_GT_ISR(1)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt2, GEN8_GT_ISR(2)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt3, GEN8_GT_ISR(3)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_a, GEN8_DE_PIPE_ISR(PIPE_A)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_b, GEN8_DE_PIPE_ISR(PIPE_B)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_c, GEN8_DE_PIPE_ISR(PIPE_C)); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_port, GEN8_DE_PORT_ISR); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_misc, GEN8_DE_MISC_ISR); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(pcu, GEN8_PCU_ISR); DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(master, GEN8_MASTER_IRQ); static struct intel_gvt_irq_info gvt_base_pch_info = …; static void gen8_check_pending_irq(struct intel_vgpu *vgpu) { … } static void gen8_init_irq( struct intel_gvt_irq *irq) { … } static const struct intel_gvt_irq_ops gen8_irq_ops = …; /** * intel_vgpu_trigger_virtual_event - Trigger a virtual event for a vGPU * @vgpu: a vGPU * @event: interrupt event * * This function is used to trigger a virtual interrupt event for vGPU. * The caller provides the event to be triggered, the framework itself * will emulate the IRQ register bit change. * */ void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu, enum intel_gvt_event_type event) { … } static void init_events( struct intel_gvt_irq *irq) { … } /** * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem * @gvt: a GVT device * * This function is called at driver loading stage, to initialize the GVT-g IRQ * emulation subsystem. * * Returns: * Zero on success, negative error code if failed. */ int intel_gvt_init_irq(struct intel_gvt *gvt) { … }