This patch introduces the very basic framework of GVT-g device model, includes basic prototypes, definitions, initialization. --- arch/x86/include/asm/xen/interface.h | 3 + drivers/gpu/drm/i915/Kconfig | 16 ++ drivers/gpu/drm/i915/Makefile | 2 + drivers/gpu/drm/i915/gvt/Makefile | 5 + drivers/gpu/drm/i915/gvt/debug.h | 72 +++++++ drivers/gpu/drm/i915/gvt/fb_decoder.c | 34 ++++ drivers/gpu/drm/i915/gvt/fb_decoder.h | 110 ++++++++++ drivers/gpu/drm/i915/gvt/gvt.c | 366 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gvt.h | 130 ++++++++++++ drivers/gpu/drm/i915/gvt/hypercall.h | 30 +++ drivers/gpu/drm/i915/gvt/mpt.h | 97 +++++++++ drivers/gpu/drm/i915/gvt/params.c | 29 +++ drivers/gpu/drm/i915/gvt/params.h | 34 ++++ drivers/gpu/drm/i915/gvt/reg.h | 34 ++++ drivers/gpu/drm/i915/i915_dma.c | 19 ++ drivers/gpu/drm/i915/i915_drv.h | 6 + drivers/gpu/drm/i915/i915_vgpu.h | 3 + include/xen/interface/xen.h | 1 + 18 files changed, 991 insertions(+) create mode 100644 drivers/gpu/drm/i915/gvt/Makefile create mode 100644 drivers/gpu/drm/i915/gvt/debug.h create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.c create mode 100644 drivers/gpu/drm/i915/gvt/fb_decoder.h create mode 100644 drivers/gpu/drm/i915/gvt/gvt.c create mode 100644 drivers/gpu/drm/i915/gvt/gvt.h create mode 100644 drivers/gpu/drm/i915/gvt/hypercall.h create mode 100644 drivers/gpu/drm/i915/gvt/mpt.h create mode 100644 drivers/gpu/drm/i915/gvt/params.c create mode 100644 drivers/gpu/drm/i915/gvt/params.h create mode 100644 drivers/gpu/drm/i915/gvt/reg.h diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 62ca03e..6ff4986 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -73,6 +73,9 @@ #endif #ifndef __ASSEMBLY__ + +#include <linux/types.h> + /* Explicitly size integers that represent pfns in the public interface * with Xen so that on ARM we can have one ABI that works for 32 and 64 * bit guests. */ diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 051eab3..89ff723 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -47,3 +47,19 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT option changes the default for that module option. If in doubt, say "N". + +config I915_GVT + tristate "GVT-g host driver" + depends on DRM_I915 + select IRQ_WORK + default y + help + Enabling GVT-g mediated graphics passthrough technique for Intel i915 + based integrated graphics card. With GVT-g, it's possible to have one + integrated i915 device shared by multiple VMs. Performance critical + opterations such as apperture accesses and ring buffer operations + are pass-throughed to VM, with a minimal set of conflicting resources + (e.g. display settings) mediated by vGT driver. The benefit of vGT + is on both the performance, given that each VM could directly operate + its aperture space and submit commands like running on native, and + the feature completeness, given that a true GEN hardware is exposed. diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0851de07..d4df410 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -91,6 +91,8 @@ i915-y += dvo_ch7017.o \ intel_sdvo.o \ intel_tv.o +obj-$(CONFIG_I915_GVT) += gvt/ + # virtual gpu code i915-y += i915_vgpu.o diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile new file mode 100644 index 0000000..6935b78 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/Makefile @@ -0,0 +1,5 @@ +GVT_SOURCE := gvt.o params.o fb_decoder.o + +ccflags-y += -I$(src) -I$(src)/.. -Wall -Werror -Wno-unused-function +i915_gvt-y := $(GVT_SOURCE) +obj-$(CONFIG_I915_GVT) += i915_gvt.o diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h new file mode 100644 index 0000000..18e1467 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#ifndef __GVT_DEBUG_H__ +#define __GVT_DEBUG_H__ + +#define ASSERT(x) \ + do { \ + if (!(x)) { \ + printk("Assert at %s line %d\n", \ + __FILE__, __LINE__); \ + } \ + } while (0); + +#define ASSERT_NUM(x, y) \ + do { \ + if (!(x)) { \ + printk("Assert at %s line %d para 0x%llx\n", \ + __FILE__, __LINE__, (u64)y); \ + } \ + } while (0); + +#define gvt_info(fmt, args...) \ + printk(KERN_INFO"[GVT-g] "fmt"\n", ##args) + +#define gvt_err(fmt, args...) \ + printk(KERN_ERR"%s() - %d: "fmt"\n", __func__, __LINE__, ##args) + +#define gvt_warn(fmt, args...) \ + printk(KERN_WARNING"%s() - %d: "fmt"\n", __func__, __LINE__, ##args) + +#define gvt_dbg(level, fmt, args...) do { \ + if (gvt.debug & level) \ + printk(KERN_DEBUG"%s() - %d: "fmt"\n", __func__, __LINE__, ##args); \ + }while(0) + +enum { + GVT_DBG_CORE = (1 << 0), + GVT_DBG_MM = (1 << 1), + GVT_DBG_IRQ = (1 << 2), +}; + +#define gvt_dbg_core(fmt, args...) \ + gvt_dbg(GVT_DBG_CORE, fmt, ##args) + +#define gvt_dbg_mm(fmt, args...) \ + gvt_dbg(GVT_DBG_MM, fmt, ##args) + +#define gvt_dbg_irq(fmt, args...) \ + gvt_dbg(GVT_DBG_IRQ, fmt, ##args) + +#endif diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.c b/drivers/gpu/drm/i915/gvt/fb_decoder.c new file mode 100644 index 0000000..a219819 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.c @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#include "gvt.h" + +int gvt_decode_fb_format(struct pgt_device *pdev, int vmid, struct gvt_fb_format *fb) +{ + return 0; +} + +int gvt_fb_notifier_call_chain(unsigned long val, void *data) +{ + return 0; +} diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h new file mode 100644 index 0000000..2c29ed4 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#ifndef _GVT_FB_DECODER_H_ +#define _GVT_FB_DECODER_H_ + +typedef enum { + FB_MODE_SET_START = 1, + FB_MODE_SET_END, + FB_DISPLAY_FLIP, +}gvt_fb_event_t; + +typedef enum { + DDI_PORT_NONE = 0, + DDI_PORT_B = 1, + DDI_PORT_C = 2, + DDI_PORT_D = 3, + DDI_PORT_E = 4 +} ddi_port_t; + +struct pgt_device; + +struct gvt_fb_notify_msg { + unsigned vm_id; + unsigned pipe_id; /* id starting from 0 */ + unsigned plane_id; /* primary, cursor, or sprite */ +}; + +/* color space conversion and gamma correction are not included */ +struct gvt_primary_plane_format { + u8 enabled; /* plane is enabled */ + u8 tiled; /* X-tiled */ + u8 bpp; /* bits per pixel */ + u32 hw_format; /* format field in the PRI_CTL register */ + u32 drm_format; /* format in DRM definition */ + u32 base; /* framebuffer base in graphics memory */ + u32 x_offset; /* in pixels */ + u32 y_offset; /* in lines */ + u32 width; /* in pixels */ + u32 height; /* in lines */ + u32 stride; /* in bytes */ +}; + +struct gvt_sprite_plane_format { + u8 enabled; /* plane is enabled */ + u8 tiled; /* X-tiled */ + u8 bpp; /* bits per pixel */ + u32 hw_format; /* format field in the SPR_CTL register */ + u32 drm_format; /* format in DRM definition */ + u32 base; /* sprite base in graphics memory */ + u32 x_pos; /* in pixels */ + u32 y_pos; /* in lines */ + u32 x_offset; /* in pixels */ + u32 y_offset; /* in lines */ + u32 width; /* in pixels */ + u32 height; /* in lines */ +}; + +struct gvt_cursor_plane_format { + u8 enabled; + u8 mode; /* cursor mode select */ + u8 bpp; /* bits per pixel */ + u32 drm_format; /* format in DRM definition */ + u32 base; /* cursor base in graphics memory */ + u32 x_pos; /* in pixels */ + u32 y_pos; /* in lines */ + u8 x_sign; /* X Position Sign */ + u8 y_sign; /* Y Position Sign */ + u32 width; /* in pixels */ + u32 height; /* in lines */ + u32 x_hot; /* in pixels */ + u32 y_hot; /* in pixels */ +}; + +struct gvt_pipe_format { + struct gvt_primary_plane_format primary; + struct gvt_sprite_plane_format sprite; + struct gvt_cursor_plane_format cursor; + ddi_port_t ddi_port; /* the DDI port that the pipe is connected to */ +}; + +struct gvt_fb_format{ + struct gvt_pipe_format pipes[I915_MAX_PIPES]; +}; + +extern int gvt_fb_notifier_call_chain(unsigned long val, void *data); +extern int gvt_decode_fb_format(struct pgt_device *pdev, int vmid, + struct gvt_fb_format *fb); + +#endif diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c new file mode 100644 index 0000000..041d10f --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -0,0 +1,366 @@ +/* + * 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. + */ + +#include <xen/xen.h> +#include <linux/kthread.h> + +#include "gvt.h" + +struct gvt_host gvt_host; + +extern struct gvt_kernel_dm xengt_kdm; +extern struct gvt_kernel_dm kvmgt_kdm; + +static const char *supported_hypervisors[] = { + [GVT_HYPERVISOR_TYPE_XEN] = "Xen Hypervisor", + [GVT_HYPERVISOR_TYPE_KVM] = "KVM", +}; + +static bool gvt_init_host(void) +{ + struct gvt_host *host = &gvt_host; + + if (!gvt.enable) { + gvt_dbg_core("GVT-g has been disabled by kernel parameter"); + return false; + } + + if (host->initialized) { + gvt_err("GVT-g has already been initialized!"); + return false; + } + + if (xen_initial_domain()) { + /* Xen Dom0 */ + host->kdm = try_then_request_module(symbol_get(xengt_kdm), "xengt"); + host->hypervisor_type = GVT_HYPERVISOR_TYPE_XEN; + } else if(xen_domain()) { + /* Xen DomU */ + return false; + } else { + /* not in Xen. Try KVMGT */ + host->kdm = try_then_request_module(symbol_get(kvmgt_kdm), "kvm"); + host->hypervisor_type = GVT_HYPERVISOR_TYPE_KVM; + } + + if (!host->kdm) + return false; + + if (!hypervisor_detect_host()) + return false; + + gvt_info("Running with hypervisor %s in host mode", + supported_hypervisors[host->hypervisor_type]); + + idr_init(&host->device_idr); + mutex_init(&host->device_idr_lock); + + host->initialized = true; + return true; +} + +static bool init_device_info(struct pgt_device *pdev) +{ + struct gvt_device_info *info = &pdev->device_info; + + if (!IS_BROADWELL(pdev->dev_priv)) { + gvt_err("Unsupported GEN device"); + return false; + } + + if (IS_BROADWELL(pdev->dev_priv)) { + info->max_gtt_gm_sz = (1UL << 32); + /* + * The layout of BAR0 in BDW: + * |< - MMIO 2MB ->|<- Reserved 6MB ->|<- MAX GTT 8MB->| + * + * GTT offset in BAR0 starts from 8MB to 16MB, and + * Whatever GTT size is configured in BIOS, + * the size of BAR0 is always 16MB. The actual configured + * GTT size can be found in GMCH_CTRL. + */ + info->gtt_start_offset = (1UL << 23); + info->max_gtt_size = (1UL << 23); + info->gtt_entry_size = 8; + info->gtt_entry_size_shift = 3; + info->gmadr_bytes_in_cmd = 8; + } + + gvt_info("Device info:"); + printk(" max_gtt_gm_sz: %llx\n", info->max_gtt_gm_sz); + printk(" max_gtt_size: %x\n", info->max_gtt_size); + printk(" gtt_size_entry: %x\n", info->gtt_entry_size); + printk(" gtt_entry_size_shift: %x\n", info->gtt_entry_size_shift); + printk(" gtt_start_offset: %x\n", info->gtt_start_offset); + printk(" gtt_end_offset: %x\n", info->gtt_end_offset); + + return true; +} + +static void init_initial_cfg_space_state(struct pgt_device *pdev) +{ + struct pci_dev *pci_dev = pdev->dev_priv->dev->pdev; + int i; + + gvt_dbg_core("init initial cfg space, id %d", pdev->id); + + for (i = 0; i < GVT_CFG_SPACE_SZ; i += 4) + pci_read_config_dword(pci_dev, i, + (u32 *)&pdev->initial_cfg_space[i]); + + for (i = 0; i < 3; i++) { + pdev->bar_size[i] = pci_resource_len(pci_dev, i * 2); + gvt_info("bar %d size: %llx", i, pdev->bar_size[i]); + } +} + +static void clean_initial_mmio_state(struct pgt_device *pdev) +{ + if (pdev->gttmmio_va) { + iounmap(pdev->gttmmio_va); + pdev->gttmmio_va = NULL; + } + + if (pdev->gmadr_va) { + iounmap(pdev->gmadr_va); + pdev->gmadr_va = NULL; + } +} + +static bool init_initial_mmio_state(struct pgt_device *pdev) +{ + u64 bar0, bar1; + + gvt_dbg_core("init initial mmio state, id %d", pdev->id); + + bar0 = *(u64 *)&pdev->initial_cfg_space[GVT_REG_CFG_SPACE_BAR0]; + bar1 = *(u64 *)&pdev->initial_cfg_space[GVT_REG_CFG_SPACE_BAR1]; + + pdev->gttmmio_base = bar0 & ~0xf; + pdev->mmio_size = 2 * 1024 * 1024; + pdev->reg_num = pdev->mmio_size / 4; + pdev->gmadr_base = bar1 & ~0xf; + + pdev->gttmmio_va = ioremap(pdev->gttmmio_base, pdev->bar_size[0]); + if (!pdev->gttmmio_va) { + gvt_err("fail to map GTTMMIO BAR."); + return false; + } + + pdev->gmadr_va = ioremap(pdev->gmadr_base, pdev->bar_size[2]); + if (!pdev->gmadr_va) { + gvt_err("fail to map GMADR BAR."); + goto err; + } + + gvt_info("bar0: 0x%llx, bar1: 0x%llx", bar0, bar1); + gvt_info("mmio size: %x", pdev->mmio_size); + gvt_info("gttmmio: 0x%llx, gmadr: 0x%llx", pdev->gttmmio_base, pdev->gmadr_base); + gvt_info("gttmmio_va: %p", pdev->gttmmio_va); + gvt_info("gmadr_va: %p", pdev->gmadr_va); + + return true; +err: + clean_initial_mmio_state(pdev); + return false; +} + +static int gvt_service_thread(void *data) +{ + struct pgt_device *pdev = (struct pgt_device *)data; + int r; + + gvt_dbg_core("service thread start, pgt %d", pdev->id); + + while(!kthread_should_stop()) { + r = wait_event_interruptible(pdev->service_thread_wq, + kthread_should_stop() || pdev->service_request); + + if (kthread_should_stop()) + break; + + if (r) { + gvt_warn("service thread is waken up by unexpected signal."); + continue; + } + } + return 0; +} + +static void clean_service_thread(struct pgt_device *pdev) +{ + if (pdev->service_thread) { + kthread_stop(pdev->service_thread); + pdev->service_thread = NULL; + } +} + +static bool init_service_thread(struct pgt_device *pdev) +{ + init_waitqueue_head(&pdev->service_thread_wq); + + pdev->service_thread = kthread_run(gvt_service_thread, + pdev, "gvt_service_thread%d", pdev->id); + + if (!pdev->service_thread) { + gvt_err("fail to start service thread."); + return false; + } + + return true; +} + +static void clean_pgt_device(struct pgt_device *pdev) +{ + clean_service_thread(pdev); + clean_initial_mmio_state(pdev); +} + +static bool init_pgt_device(struct pgt_device *pdev, struct drm_i915_private *dev_priv) +{ + if (!init_device_info(pdev)) + return false; + + init_initial_cfg_space_state(pdev); + + if (!init_initial_mmio_state(pdev)) + goto err; + + if (!init_service_thread(pdev)) + goto err; + + return true; +err: + clean_pgt_device(pdev); + return false; +} + +static bool post_init_pgt_device(struct pgt_device *pdev) +{ + return true; +} + +static void free_pgt_device(struct pgt_device *pdev) +{ + struct gvt_host *host = &gvt_host; + + mutex_lock(&host->device_idr_lock); + idr_remove(&host->device_idr, pdev->id); + mutex_unlock(&host->device_idr_lock); + + vfree(pdev); +} + +static struct pgt_device *alloc_pgt_device(struct drm_i915_private *dev_priv) +{ + struct gvt_host *host = &gvt_host; + struct pgt_device *pdev = NULL; + + pdev = vzalloc(sizeof(*pdev)); + if (!pdev) { + gvt_err("fail to allocate memory for pgt device."); + return NULL; + } + + mutex_lock(&host->device_idr_lock); + pdev->id = idr_alloc(&host->device_idr, pdev, 0, 0, GFP_KERNEL); + mutex_unlock(&host->device_idr_lock); + + if (pdev->id < 0) { + gvt_err("fail to allocate pgt device id."); + goto err; + } + + mutex_init(&pdev->lock); + pdev->dev_priv = dev_priv; + idr_init(&pdev->instance_idr); + + return pdev; +err: + free_pgt_device(pdev); + return NULL; +} + +void gvt_destroy_pgt_device(void *private_data) +{ + struct pgt_device *pdev = (struct pgt_device *)private_data; + + clean_pgt_device(pdev); + free_pgt_device(pdev); +} + +void *gvt_create_pgt_device(struct drm_i915_private *dev_priv) +{ + struct pgt_device *pdev = NULL; + struct gvt_host *host = &gvt_host; + + if (!host->initialized && !gvt_init_host()) { + gvt_err("gvt_init_host fail"); + return NULL; + } + + gvt_dbg_core("create new pgt device, i915 dev_priv: %p", dev_priv); + + pdev = alloc_pgt_device(dev_priv); + if (!pdev) { + gvt_err("fail to allocate memory for pgt device."); + goto err; + } + + gvt_dbg_core("init pgt device, id %d", pdev->id); + + if (!init_pgt_device(pdev, dev_priv)) { + gvt_err("fail to init physical device state."); + goto err; + } + + gvt_dbg_core("pgt device creation done, id %d", pdev->id); + + return pdev; +err: + if (pdev) { + gvt_destroy_pgt_device(pdev); + pdev = NULL; + } + return NULL; +} + +bool gvt_post_init_pgt_device(void *private_data) +{ + struct pgt_device *pdev = (struct pgt_device *)private_data; + struct gvt_host *host = &gvt_host; + + if (!host->initialized) { + gvt_err("gvt_host haven't been initialized."); + return false; + } + + gvt_dbg_core("post init pgt device %d", pdev->id); + + if (!post_init_pgt_device(pdev)) { + gvt_err("fail to post init physical device state."); + return false; + } + + return true; +} diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h new file mode 100644 index 0000000..6c85bba --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -0,0 +1,130 @@ +/* + * 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. + */ + +#ifndef _GVT_H_ +#define _GVT_H_ + +#include "i915_drv.h" +#include "i915_vgpu.h" + +#include "debug.h" +#include "params.h" +#include "reg.h" +#include "hypercall.h" +#include "mpt.h" +#include "fb_decoder.h" + +#define GVT_MAX_VGPU 8 + +enum { + GVT_HYPERVISOR_TYPE_XEN = 0, + GVT_HYPERVISOR_TYPE_KVM, +}; + +struct gvt_host { + bool initialized; + int hypervisor_type; + struct mutex device_idr_lock; + struct idr device_idr; + struct gvt_kernel_dm *kdm; +}; + +extern struct gvt_host gvt_host; + +/* Describe the limitation of HW.*/ +struct gvt_device_info { + u64 max_gtt_gm_sz; + u32 gtt_start_offset; + u32 gtt_end_offset; + u32 max_gtt_size; + u32 gtt_entry_size; + u32 gtt_entry_size_shift; + u32 gmadr_bytes_in_cmd; +}; + +struct vgt_device { + int id; + int vm_id; + struct pgt_device *pdev; + bool warn_untrack; +}; + +struct pgt_device { + struct mutex lock; + int id; + + struct drm_i915_private *dev_priv; + struct idr instance_idr; + + struct gvt_device_info device_info; + + u8 initial_cfg_space[GVT_CFG_SPACE_SZ]; + u64 bar_size[GVT_BAR_NUM]; + + u64 gttmmio_base; + void *gttmmio_va; + + u64 gmadr_base; + void *gmadr_va; + + u32 mmio_size; + u32 reg_num; + + wait_queue_head_t service_thread_wq; + struct task_struct *service_thread; + unsigned long service_request; +}; + +static inline u32 gvt_mmio_read(struct pgt_device *pdev, + u32 reg) +{ + struct drm_i915_private *dev_priv = pdev->dev_priv; + i915_reg_t tmp = {.reg = reg}; + return I915_READ(tmp); +} + +static inline void gvt_mmio_write(struct pgt_device *pdev, + u32 reg, u32 val) +{ + struct drm_i915_private *dev_priv = pdev->dev_priv; + i915_reg_t tmp = {.reg = reg}; + I915_WRITE(tmp, val); +} + +static inline u64 gvt_mmio_read64(struct pgt_device *pdev, + u32 reg) +{ + struct drm_i915_private *dev_priv = pdev->dev_priv; + i915_reg_t tmp = {.reg = reg}; + return I915_READ64(tmp); +} + +static inline void gvt_mmio_write64(struct pgt_device *pdev, + u32 reg, u64 val) +{ + struct drm_i915_private *dev_priv = pdev->dev_priv; + i915_reg_t tmp = {.reg = reg}; + I915_WRITE64(tmp, val); +} + +#endif diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h new file mode 100644 index 0000000..0a41874 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef _GVT_HYPERCALL_H_ +#define _GVT_HYPERCALL_H_ + +struct gvt_kernel_dm { +}; + +#endif /* _GVT_HYPERCALL_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h new file mode 100644 index 0000000..bbe4465 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#ifndef _GVT_MPT_H_ +#define _GVT_MPT_H_ + +struct vgt_device; + +static inline unsigned long hypervisor_g2m_pfn(struct vgt_device *vgt, + unsigned long g_pfn) +{ + return 0; +} + +static inline int hypervisor_pause_domain(struct vgt_device *vgt) +{ + return 0; +} + +static inline int hypervisor_shutdown_domain(struct vgt_device *vgt) +{ + return 0; +} + +static inline int hypervisor_set_trap_area(struct vgt_device *vgt, + uint64_t start, uint64_t end, bool map) +{ + return 0; +} + +static inline bool hypervisor_detect_host(void) +{ + return false; +} + +static inline int hypervisor_virt_to_mfn(void *addr) +{ + return 0; +} + +static inline void *hypervisor_mfn_to_virt(int mfn) +{ + return NULL; +} + +static inline void hypervisor_inject_msi(struct vgt_device *vgt) +{ + return; +} + +static inline int hypervisor_hvm_init(struct vgt_device *vgt) +{ + return 0; +} + +static inline void hypervisor_hvm_exit(struct vgt_device *vgt) +{ +} + +static inline void *hypervisor_gpa_to_va(struct vgt_device *vgt, unsigned long gpa) +{ + return NULL; +} + +static inline bool hypervisor_read_va(struct vgt_device *vgt, void *va, + void *val, int len, int atomic) +{ + return false; +} + +static inline bool hypervisor_write_va(struct vgt_device *vgt, void *va, + void *val, int len, int atomic) +{ + return false; +} + +#endif /* _GVT_MPT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/params.c b/drivers/gpu/drm/i915/gvt/params.c new file mode 100644 index 0000000..dfc33c3 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/params.c @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "gvt.h" + +struct gvt_kernel_params gvt = { + .enable = true, + .debug = 0, +}; diff --git a/drivers/gpu/drm/i915/gvt/params.h b/drivers/gpu/drm/i915/gvt/params.h new file mode 100644 index 0000000..d2955b9 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/params.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef _GVT_PARAMS_H_ +#define _GVT_PARAMS_H_ + +struct gvt_kernel_params { + bool enable; + int debug; +}; + +extern struct gvt_kernel_params gvt; + +#endif diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h new file mode 100644 index 0000000..d363b74 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef _GVT_REG_H +#define _GVT_REG_H + +#define GVT_CFG_SPACE_SZ 256 +#define GVT_BAR_NUM 4 + +#define GVT_REG_CFG_SPACE_BAR0 0x10 +#define GVT_REG_CFG_SPACE_BAR1 0x18 +#define GVT_REG_CFG_SPACE_BAR2 0x20 + +#endif diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4725e8d..eca8e50 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -943,6 +943,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_uncore_init(dev); + dev_priv->vgpu.host_private_data = gvt_create_pgt_device(dev_priv); + if(intel_gvt_host_active(dev)) + DRM_INFO("GVT-g is running in host mode\n"); + ret = i915_gem_gtt_init(dev); if (ret) goto out_freecsr; @@ -1067,6 +1071,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_power_well; } + if (intel_gvt_host_active(dev)) { + if (!gvt_post_init_pgt_device(dev_priv->vgpu.host_private_data)) { + DRM_ERROR("failed to post init pgt device\n"); + goto out_power_well; + } + } + /* * Notify a valid surface after modesetting, * when running inside a VM. @@ -1117,6 +1128,10 @@ out_gtt: i915_global_gtt_cleanup(dev); out_freecsr: intel_csr_ucode_fini(dev_priv); + if (intel_gvt_host_active(dev)) { + gvt_destroy_pgt_device(dev_priv->vgpu.host_private_data); + dev_priv->vgpu.host_private_data = NULL; + } intel_uncore_fini(dev); pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: @@ -1165,6 +1180,10 @@ int i915_driver_unload(struct drm_device *dev) intel_modeset_cleanup(dev); + if (intel_gvt_host_active(dev)) { + gvt_destroy_pgt_device(dev_priv->vgpu.host_private_data); + dev_priv->vgpu.host_private_data = NULL; + } /* * free the memory space allocated for the child device * config parsed from VBT diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 01cc982..db3c79b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1673,6 +1673,7 @@ struct i915_workarounds { struct i915_virtual_gpu { bool active; + void *host_private_data; }; struct i915_execbuffer_params { @@ -2747,6 +2748,11 @@ static inline bool intel_vgpu_active(struct drm_device *dev) return to_i915(dev)->vgpu.active; } +static inline bool intel_gvt_host_active(struct drm_device *dev) +{ + return to_i915(dev)->vgpu.host_private_data ? true : false; +} + void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask); diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h index 3c83b47..942490a 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.h +++ b/drivers/gpu/drm/i915/i915_vgpu.h @@ -113,5 +113,8 @@ struct vgt_if { extern void i915_check_vgpu(struct drm_device *dev); extern int intel_vgt_balloon(struct drm_device *dev); extern void intel_vgt_deballoon(void); +extern void *gvt_create_pgt_device(struct drm_i915_private *dev_priv); +extern bool gvt_post_init_pgt_device(void *private_data); +extern void gvt_destroy_pgt_device(void *private_data); #endif /* _I915_VGPU_H_ */ diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index d133112..78a38f1 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h @@ -28,6 +28,7 @@ #define __XEN_PUBLIC_XEN_H__ #include <asm/xen/interface.h> +#include <linux/types.h> /* * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS). -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx