12707e444SZhi Wang /* 22707e444SZhi Wang * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 32707e444SZhi Wang * 42707e444SZhi Wang * Permission is hereby granted, free of charge, to any person obtaining a 52707e444SZhi Wang * copy of this software and associated documentation files (the "Software"), 62707e444SZhi Wang * to deal in the Software without restriction, including without limitation 72707e444SZhi Wang * the rights to use, copy, modify, merge, publish, distribute, sublicense, 82707e444SZhi Wang * and/or sell copies of the Software, and to permit persons to whom the 92707e444SZhi Wang * Software is furnished to do so, subject to the following conditions: 102707e444SZhi Wang * 112707e444SZhi Wang * The above copyright notice and this permission notice (including the next 122707e444SZhi Wang * paragraph) shall be included in all copies or substantial portions of the 132707e444SZhi Wang * Software. 142707e444SZhi Wang * 152707e444SZhi Wang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 162707e444SZhi Wang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 172707e444SZhi Wang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 182707e444SZhi Wang * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 192707e444SZhi Wang * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 202707e444SZhi Wang * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 212707e444SZhi Wang * SOFTWARE. 222707e444SZhi Wang * 232707e444SZhi Wang * Authors: 242707e444SZhi Wang * Zhi Wang <zhi.a.wang@intel.com> 252707e444SZhi Wang * Zhenyu Wang <zhenyuw@linux.intel.com> 262707e444SZhi Wang * Xiao Zheng <xiao.zheng@intel.com> 272707e444SZhi Wang * 282707e444SZhi Wang * Contributors: 292707e444SZhi Wang * Min He <min.he@intel.com> 302707e444SZhi Wang * Bing Niu <bing.niu@intel.com> 312707e444SZhi Wang * 322707e444SZhi Wang */ 332707e444SZhi Wang 342707e444SZhi Wang #ifndef _GVT_GTT_H_ 352707e444SZhi Wang #define _GVT_GTT_H_ 362707e444SZhi Wang 3733a357daSJani Nikula #include <linux/kernel.h> 3833a357daSJani Nikula #include <linux/kref.h> 3933a357daSJani Nikula #include <linux/mutex.h> 4033a357daSJani Nikula #include <linux/radix-tree.h> 412707e444SZhi Wang 4233a357daSJani Nikula #include "gt/intel_gtt.h" 4333a357daSJani Nikula 4433a357daSJani Nikula struct intel_gvt; 4533a357daSJani Nikula struct intel_vgpu; 462707e444SZhi Wang struct intel_vgpu_mm; 472707e444SZhi Wang 4833a357daSJani Nikula #define I915_GTT_PAGE_SHIFT 12 4933a357daSJani Nikula 502707e444SZhi Wang #define INTEL_GVT_INVALID_ADDR (~0UL) 512707e444SZhi Wang 522707e444SZhi Wang struct intel_gvt_gtt_entry { 532707e444SZhi Wang u64 val64; 542707e444SZhi Wang int type; 552707e444SZhi Wang }; 562707e444SZhi Wang 572707e444SZhi Wang struct intel_gvt_gtt_pte_ops { 584b2dbbc2SChangbin Du int (*get_entry)(void *pt, 592707e444SZhi Wang struct intel_gvt_gtt_entry *e, 604b2dbbc2SChangbin Du unsigned long index, 614b2dbbc2SChangbin Du bool hypervisor_access, 624b2dbbc2SChangbin Du unsigned long gpa, 632707e444SZhi Wang struct intel_vgpu *vgpu); 644b2dbbc2SChangbin Du int (*set_entry)(void *pt, 652707e444SZhi Wang struct intel_gvt_gtt_entry *e, 664b2dbbc2SChangbin Du unsigned long index, 674b2dbbc2SChangbin Du bool hypervisor_access, 684b2dbbc2SChangbin Du unsigned long gpa, 692707e444SZhi Wang struct intel_vgpu *vgpu); 702707e444SZhi Wang bool (*test_present)(struct intel_gvt_gtt_entry *e); 712707e444SZhi Wang void (*clear_present)(struct intel_gvt_gtt_entry *e); 72655c64efSZhi Wang void (*set_present)(struct intel_gvt_gtt_entry *e); 732707e444SZhi Wang bool (*test_pse)(struct intel_gvt_gtt_entry *e); 74c3e69763SChangbin Du void (*clear_pse)(struct intel_gvt_gtt_entry *e); 756fd79378SChangbin Du bool (*test_ips)(struct intel_gvt_gtt_entry *e); 766fd79378SChangbin Du void (*clear_ips)(struct intel_gvt_gtt_entry *e); 7771634848SChangbin Du bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e); 7871634848SChangbin Du void (*clear_64k_splited)(struct intel_gvt_gtt_entry *e); 7971634848SChangbin Du void (*set_64k_splited)(struct intel_gvt_gtt_entry *e); 802707e444SZhi Wang void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); 812707e444SZhi Wang unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); 822707e444SZhi Wang }; 832707e444SZhi Wang 842707e444SZhi Wang struct intel_gvt_gtt_gma_ops { 852707e444SZhi Wang unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); 862707e444SZhi Wang unsigned long (*gma_to_pte_index)(unsigned long gma); 872707e444SZhi Wang unsigned long (*gma_to_pde_index)(unsigned long gma); 882707e444SZhi Wang unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); 892707e444SZhi Wang unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); 902707e444SZhi Wang unsigned long (*gma_to_pml4_index)(unsigned long gma); 912707e444SZhi Wang }; 922707e444SZhi Wang 932707e444SZhi Wang struct intel_gvt_gtt { 942707e444SZhi Wang struct intel_gvt_gtt_pte_ops *pte_ops; 95*c41aadd2SRikard Falkeborn const struct intel_gvt_gtt_gma_ops *gma_ops; 962707e444SZhi Wang int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); 972707e444SZhi Wang void (*mm_free_page_table)(struct intel_vgpu_mm *mm); 982707e444SZhi Wang struct list_head oos_page_use_list_head; 992707e444SZhi Wang struct list_head oos_page_free_list_head; 10072aabfb8SZhenyu Wang struct mutex ppgtt_mm_lock; 101ede9d0cfSChangbin Du struct list_head ppgtt_mm_lru_list_head; 102d650ac06SPing Gao 10322115cefSZhi Wang struct page *scratch_page; 10422115cefSZhi Wang unsigned long scratch_mfn; 1052707e444SZhi Wang }; 1062707e444SZhi Wang 1070cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type { 1080cf8f58dSAleksei Gimbitskii GTT_TYPE_INVALID = 0, 1093b6411c2SPing Gao 1103b6411c2SPing Gao GTT_TYPE_GGTT_PTE, 1113b6411c2SPing Gao 1123b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_4K_ENTRY, 113b294657dSChangbin Du GTT_TYPE_PPGTT_PTE_64K_ENTRY, 1143b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_2M_ENTRY, 1153b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_1G_ENTRY, 1163b6411c2SPing Gao 1173b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_ENTRY, 1183b6411c2SPing Gao 1193b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_ENTRY, 1203b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_ENTRY, 1213b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_ENTRY, 1223b6411c2SPing Gao 1233b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_ENTRY, 1243b6411c2SPing Gao 1253b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L3_ENTRY, 1263b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L4_ENTRY, 1273b6411c2SPing Gao 1283b6411c2SPing Gao GTT_TYPE_PPGTT_ENTRY, 1293b6411c2SPing Gao 1303b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_PT, 1313b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_PT, 1323b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_PT, 1333b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_PT, 1343b6411c2SPing Gao 1353b6411c2SPing Gao GTT_TYPE_MAX, 1360cf8f58dSAleksei Gimbitskii }; 1373b6411c2SPing Gao 138ede9d0cfSChangbin Du enum intel_gvt_mm_type { 139ede9d0cfSChangbin Du INTEL_GVT_MM_GGTT, 140ede9d0cfSChangbin Du INTEL_GVT_MM_PPGTT, 141ede9d0cfSChangbin Du }; 142ede9d0cfSChangbin Du 143ede9d0cfSChangbin Du #define GVT_RING_CTX_NR_PDPS GEN8_3LVL_PDPES 144ede9d0cfSChangbin Du 145bc0686ffSHang Yuan struct intel_gvt_partial_pte { 146bc0686ffSHang Yuan unsigned long offset; 147bc0686ffSHang Yuan u64 data; 148bc0686ffSHang Yuan struct list_head list; 149bc0686ffSHang Yuan }; 150bc0686ffSHang Yuan 1512707e444SZhi Wang struct intel_vgpu_mm { 152ede9d0cfSChangbin Du enum intel_gvt_mm_type type; 153ede9d0cfSChangbin Du struct intel_vgpu *vgpu; 1542707e444SZhi Wang 1552707e444SZhi Wang struct kref ref; 1562707e444SZhi Wang atomic_t pincount; 157ede9d0cfSChangbin Du 158ede9d0cfSChangbin Du union { 159ede9d0cfSChangbin Du struct { 1600cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type; 161ede9d0cfSChangbin Du /* 162ede9d0cfSChangbin Du * The 4 PDPs in ring context. For 48bit addressing, 163ede9d0cfSChangbin Du * only PDP0 is valid and point to PML4. For 32it 164ede9d0cfSChangbin Du * addressing, all 4 are used as true PDPs. 165ede9d0cfSChangbin Du */ 166ede9d0cfSChangbin Du u64 guest_pdps[GVT_RING_CTX_NR_PDPS]; 167ede9d0cfSChangbin Du u64 shadow_pdps[GVT_RING_CTX_NR_PDPS]; 168ede9d0cfSChangbin Du bool shadowed; 169ede9d0cfSChangbin Du 170ede9d0cfSChangbin Du struct list_head list; 1712707e444SZhi Wang struct list_head lru_list; 172bec3df93SZhenyu Wang struct list_head link; /* possible LRI shadow mm list */ 173ede9d0cfSChangbin Du } ppgtt_mm; 174ede9d0cfSChangbin Du struct { 175ede9d0cfSChangbin Du void *virtual_ggtt; 1765f60b12eSColin Xu /* Save/restore for PM */ 1775f60b12eSColin Xu u64 *host_ggtt_aperture; 1785f60b12eSColin Xu u64 *host_ggtt_hidden; 179bc0686ffSHang Yuan struct list_head partial_pte_list; 180ede9d0cfSChangbin Du } ggtt_mm; 181ede9d0cfSChangbin Du }; 1822707e444SZhi Wang }; 1832707e444SZhi Wang 184ede9d0cfSChangbin Du struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu, 1850cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type, u64 pdps[]); 1861bc25851SChangbin Du 1871bc25851SChangbin Du static inline void intel_vgpu_mm_get(struct intel_vgpu_mm *mm) 1881bc25851SChangbin Du { 1891bc25851SChangbin Du kref_get(&mm->ref); 1901bc25851SChangbin Du } 1911bc25851SChangbin Du 1921bc25851SChangbin Du void _intel_vgpu_mm_release(struct kref *mm_ref); 1931bc25851SChangbin Du 1941bc25851SChangbin Du static inline void intel_vgpu_mm_put(struct intel_vgpu_mm *mm) 1951bc25851SChangbin Du { 1961bc25851SChangbin Du kref_put(&mm->ref, _intel_vgpu_mm_release); 1971bc25851SChangbin Du } 1981bc25851SChangbin Du 1991bc25851SChangbin Du static inline void intel_vgpu_destroy_mm(struct intel_vgpu_mm *mm) 2001bc25851SChangbin Du { 2011bc25851SChangbin Du intel_vgpu_mm_put(mm); 2021bc25851SChangbin Du } 2032707e444SZhi Wang 2042707e444SZhi Wang struct intel_vgpu_guest_page; 2052707e444SZhi Wang 2065c35258dSZhenyu Wang struct intel_vgpu_scratch_pt { 2073b6411c2SPing Gao struct page *page; 2085c35258dSZhenyu Wang unsigned long page_mfn; 2093b6411c2SPing Gao }; 2103b6411c2SPing Gao 2112707e444SZhi Wang struct intel_vgpu_gtt { 2122707e444SZhi Wang struct intel_vgpu_mm *ggtt_mm; 2132707e444SZhi Wang unsigned long active_ppgtt_mm_bitmap; 214ede9d0cfSChangbin Du struct list_head ppgtt_mm_list_head; 215b6c126a3SChangbin Du struct radix_tree_root spt_tree; 2162707e444SZhi Wang struct list_head oos_page_list_head; 2172707e444SZhi Wang struct list_head post_shadow_list_head; 2185c35258dSZhenyu Wang struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX]; 2192707e444SZhi Wang }; 2202707e444SZhi Wang 221b5893ffcSJanusz Krzysztofik int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); 222b5893ffcSJanusz Krzysztofik void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); 223f4c43db3SChangbin Du void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old); 224730c8eadSZhi Wang void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu); 2252707e444SZhi Wang 226b5893ffcSJanusz Krzysztofik int intel_gvt_init_gtt(struct intel_gvt *gvt); 2274d3e67bbSChuanxiao Dong void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu); 228b5893ffcSJanusz Krzysztofik void intel_gvt_clean_gtt(struct intel_gvt *gvt); 2292707e444SZhi Wang 230b5893ffcSJanusz Krzysztofik struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, 231b5893ffcSJanusz Krzysztofik int page_table_level, 232b5893ffcSJanusz Krzysztofik void *root_entry); 2332707e444SZhi Wang 2342707e444SZhi Wang struct intel_vgpu_oos_page { 23544b46733SChangbin Du struct intel_vgpu_ppgtt_spt *spt; 2362707e444SZhi Wang struct list_head list; 2372707e444SZhi Wang struct list_head vm_list; 2382707e444SZhi Wang int id; 239ed47c5cbSZhao Yakui void *mem; 2402707e444SZhi Wang }; 2412707e444SZhi Wang 2422707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512 2432707e444SZhi Wang 24444b46733SChangbin Du /* Represent a vgpu shadow page table. */ 2452707e444SZhi Wang struct intel_vgpu_ppgtt_spt { 2462707e444SZhi Wang atomic_t refcount; 2472707e444SZhi Wang struct intel_vgpu *vgpu; 24844b46733SChangbin Du 24944b46733SChangbin Du struct { 2500cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type type; 25140b27176SChangbin Du bool pde_ips; /* for 64KB PTEs */ 25244b46733SChangbin Du void *vaddr; 25344b46733SChangbin Du struct page *page; 25444b46733SChangbin Du unsigned long mfn; 25544b46733SChangbin Du } shadow_page; 25644b46733SChangbin Du 25744b46733SChangbin Du struct { 2580cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type type; 25940b27176SChangbin Du bool pde_ips; /* for 64KB PTEs */ 26044b46733SChangbin Du unsigned long gfn; 26144b46733SChangbin Du unsigned long write_cnt; 26244b46733SChangbin Du struct intel_vgpu_oos_page *oos_page; 26344b46733SChangbin Du } guest_page; 26444b46733SChangbin Du 2652707e444SZhi Wang DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE); 2662707e444SZhi Wang struct list_head post_shadow_list; 2672707e444SZhi Wang }; 2682707e444SZhi Wang 2692707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); 2702707e444SZhi Wang 2712707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); 2722707e444SZhi Wang 2732707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); 2742707e444SZhi Wang 2752707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); 2762707e444SZhi Wang 2772707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, 2782707e444SZhi Wang unsigned long gma); 2792707e444SZhi Wang 2802707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 281ede9d0cfSChangbin Du u64 pdps[]); 2822707e444SZhi Wang 283e6e9c46fSChangbin Du struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu, 2840cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type, u64 pdps[]); 2852707e444SZhi Wang 286e6e9c46fSChangbin Du int intel_vgpu_put_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]); 2872707e444SZhi Wang 288a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu, 2892707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 2902707e444SZhi Wang 291a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, 2922707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 2932707e444SZhi Wang 294ba25d977SColin Xu void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu); 2955f60b12eSColin Xu void intel_gvt_restore_ggtt(struct intel_gvt *gvt); 296ba25d977SColin Xu 2972707e444SZhi Wang #endif /* _GVT_GTT_H_ */ 298