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 379556e118SZhi Wang #define I915_GTT_PAGE_SHIFT 12 389556e118SZhi Wang #define I915_GTT_PAGE_MASK (~(I915_GTT_PAGE_SIZE - 1)) 392707e444SZhi Wang 402707e444SZhi Wang struct intel_vgpu_mm; 412707e444SZhi Wang 422707e444SZhi Wang #define INTEL_GVT_GTT_HASH_BITS 8 432707e444SZhi Wang #define INTEL_GVT_INVALID_ADDR (~0UL) 442707e444SZhi Wang 452707e444SZhi Wang struct intel_gvt_gtt_entry { 462707e444SZhi Wang u64 val64; 472707e444SZhi Wang int type; 482707e444SZhi Wang }; 492707e444SZhi Wang 502707e444SZhi Wang struct intel_gvt_gtt_pte_ops { 514b2dbbc2SChangbin Du int (*get_entry)(void *pt, 522707e444SZhi Wang struct intel_gvt_gtt_entry *e, 534b2dbbc2SChangbin Du unsigned long index, 544b2dbbc2SChangbin Du bool hypervisor_access, 554b2dbbc2SChangbin Du unsigned long gpa, 562707e444SZhi Wang struct intel_vgpu *vgpu); 574b2dbbc2SChangbin Du int (*set_entry)(void *pt, 582707e444SZhi Wang struct intel_gvt_gtt_entry *e, 594b2dbbc2SChangbin Du unsigned long index, 604b2dbbc2SChangbin Du bool hypervisor_access, 614b2dbbc2SChangbin Du unsigned long gpa, 622707e444SZhi Wang struct intel_vgpu *vgpu); 632707e444SZhi Wang bool (*test_present)(struct intel_gvt_gtt_entry *e); 642707e444SZhi Wang void (*clear_present)(struct intel_gvt_gtt_entry *e); 65655c64efSZhi Wang void (*set_present)(struct intel_gvt_gtt_entry *e); 662707e444SZhi Wang bool (*test_pse)(struct intel_gvt_gtt_entry *e); 672707e444SZhi Wang void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); 682707e444SZhi Wang unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); 692707e444SZhi Wang }; 702707e444SZhi Wang 712707e444SZhi Wang struct intel_gvt_gtt_gma_ops { 722707e444SZhi Wang unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); 732707e444SZhi Wang unsigned long (*gma_to_pte_index)(unsigned long gma); 742707e444SZhi Wang unsigned long (*gma_to_pde_index)(unsigned long gma); 752707e444SZhi Wang unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); 762707e444SZhi Wang unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); 772707e444SZhi Wang unsigned long (*gma_to_pml4_index)(unsigned long gma); 782707e444SZhi Wang }; 792707e444SZhi Wang 802707e444SZhi Wang struct intel_gvt_gtt { 812707e444SZhi Wang struct intel_gvt_gtt_pte_ops *pte_ops; 822707e444SZhi Wang struct intel_gvt_gtt_gma_ops *gma_ops; 832707e444SZhi Wang int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); 842707e444SZhi Wang void (*mm_free_page_table)(struct intel_vgpu_mm *mm); 852707e444SZhi Wang struct list_head oos_page_use_list_head; 862707e444SZhi Wang struct list_head oos_page_free_list_head; 87ede9d0cfSChangbin Du struct list_head ppgtt_mm_lru_list_head; 88d650ac06SPing Gao 8922115cefSZhi Wang struct page *scratch_page; 9022115cefSZhi Wang unsigned long scratch_mfn; 912707e444SZhi Wang }; 922707e444SZhi Wang 933b6411c2SPing Gao typedef enum { 943b6411c2SPing Gao GTT_TYPE_INVALID = -1, 953b6411c2SPing Gao 963b6411c2SPing Gao GTT_TYPE_GGTT_PTE, 973b6411c2SPing Gao 983b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_4K_ENTRY, 993b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_2M_ENTRY, 1003b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_1G_ENTRY, 1013b6411c2SPing Gao 1023b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_ENTRY, 1033b6411c2SPing Gao 1043b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_ENTRY, 1053b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_ENTRY, 1063b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_ENTRY, 1073b6411c2SPing Gao 1083b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_ENTRY, 1093b6411c2SPing Gao 1103b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L3_ENTRY, 1113b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L4_ENTRY, 1123b6411c2SPing Gao 1133b6411c2SPing Gao GTT_TYPE_PPGTT_ENTRY, 1143b6411c2SPing Gao 1153b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_PT, 1163b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_PT, 1173b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_PT, 1183b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_PT, 1193b6411c2SPing Gao 1203b6411c2SPing Gao GTT_TYPE_MAX, 1213b6411c2SPing Gao } intel_gvt_gtt_type_t; 1223b6411c2SPing Gao 123ede9d0cfSChangbin Du enum intel_gvt_mm_type { 124ede9d0cfSChangbin Du INTEL_GVT_MM_GGTT, 125ede9d0cfSChangbin Du INTEL_GVT_MM_PPGTT, 126ede9d0cfSChangbin Du }; 127ede9d0cfSChangbin Du 128ede9d0cfSChangbin Du #define GVT_RING_CTX_NR_PDPS GEN8_3LVL_PDPES 129ede9d0cfSChangbin Du 1302707e444SZhi Wang struct intel_vgpu_mm { 131ede9d0cfSChangbin Du enum intel_gvt_mm_type type; 132ede9d0cfSChangbin Du struct intel_vgpu *vgpu; 1332707e444SZhi Wang 1342707e444SZhi Wang struct kref ref; 1352707e444SZhi Wang atomic_t pincount; 136ede9d0cfSChangbin Du 137ede9d0cfSChangbin Du union { 138ede9d0cfSChangbin Du struct { 139ede9d0cfSChangbin Du intel_gvt_gtt_type_t root_entry_type; 140ede9d0cfSChangbin Du /* 141ede9d0cfSChangbin Du * The 4 PDPs in ring context. For 48bit addressing, 142ede9d0cfSChangbin Du * only PDP0 is valid and point to PML4. For 32it 143ede9d0cfSChangbin Du * addressing, all 4 are used as true PDPs. 144ede9d0cfSChangbin Du */ 145ede9d0cfSChangbin Du u64 guest_pdps[GVT_RING_CTX_NR_PDPS]; 146ede9d0cfSChangbin Du u64 shadow_pdps[GVT_RING_CTX_NR_PDPS]; 147ede9d0cfSChangbin Du bool shadowed; 148ede9d0cfSChangbin Du 149ede9d0cfSChangbin Du struct list_head list; 1502707e444SZhi Wang struct list_head lru_list; 151ede9d0cfSChangbin Du } ppgtt_mm; 152ede9d0cfSChangbin Du struct { 153ede9d0cfSChangbin Du void *virtual_ggtt; 154ede9d0cfSChangbin Du } ggtt_mm; 155ede9d0cfSChangbin Du }; 1562707e444SZhi Wang }; 1572707e444SZhi Wang 158ede9d0cfSChangbin Du struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu, 159ede9d0cfSChangbin Du intel_gvt_gtt_type_t root_entry_type, u64 pdps[]); 1601bc25851SChangbin Du 1611bc25851SChangbin Du static inline void intel_vgpu_mm_get(struct intel_vgpu_mm *mm) 1621bc25851SChangbin Du { 1631bc25851SChangbin Du kref_get(&mm->ref); 1641bc25851SChangbin Du } 1651bc25851SChangbin Du 1661bc25851SChangbin Du void _intel_vgpu_mm_release(struct kref *mm_ref); 1671bc25851SChangbin Du 1681bc25851SChangbin Du static inline void intel_vgpu_mm_put(struct intel_vgpu_mm *mm) 1691bc25851SChangbin Du { 1701bc25851SChangbin Du kref_put(&mm->ref, _intel_vgpu_mm_release); 1711bc25851SChangbin Du } 1721bc25851SChangbin Du 1731bc25851SChangbin Du static inline void intel_vgpu_destroy_mm(struct intel_vgpu_mm *mm) 1741bc25851SChangbin Du { 1751bc25851SChangbin Du intel_vgpu_mm_put(mm); 1761bc25851SChangbin Du } 1772707e444SZhi Wang 1782707e444SZhi Wang struct intel_vgpu_guest_page; 1792707e444SZhi Wang 1805c35258dSZhenyu Wang struct intel_vgpu_scratch_pt { 1813b6411c2SPing Gao struct page *page; 1825c35258dSZhenyu Wang unsigned long page_mfn; 1833b6411c2SPing Gao }; 1843b6411c2SPing Gao 1852707e444SZhi Wang struct intel_vgpu_gtt { 1862707e444SZhi Wang struct intel_vgpu_mm *ggtt_mm; 1872707e444SZhi Wang unsigned long active_ppgtt_mm_bitmap; 188ede9d0cfSChangbin Du struct list_head ppgtt_mm_list_head; 1892707e444SZhi Wang DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 1907d1e5cdfSZhi Wang DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 1917d1e5cdfSZhi Wang atomic_t n_tracked_guest_page; 1922707e444SZhi Wang struct list_head oos_page_list_head; 1932707e444SZhi Wang struct list_head post_shadow_list_head; 1945c35258dSZhenyu Wang struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX]; 1952707e444SZhi Wang }; 1962707e444SZhi Wang 1972707e444SZhi Wang extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); 1982707e444SZhi Wang extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); 199d650ac06SPing Gao void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu); 2002707e444SZhi Wang 2012707e444SZhi Wang extern int intel_gvt_init_gtt(struct intel_gvt *gvt); 2024d3e67bbSChuanxiao Dong void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu); 2032707e444SZhi Wang extern void intel_gvt_clean_gtt(struct intel_gvt *gvt); 2042707e444SZhi Wang 2052707e444SZhi Wang extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, 2062707e444SZhi Wang int page_table_level, void *root_entry); 2072707e444SZhi Wang 2082707e444SZhi Wang struct intel_vgpu_oos_page; 2092707e444SZhi Wang 2105c35258dSZhenyu Wang struct intel_vgpu_shadow_page { 2115c35258dSZhenyu Wang void *vaddr; 2125c35258dSZhenyu Wang struct page *page; 2135c35258dSZhenyu Wang int type; 2145c35258dSZhenyu Wang struct hlist_node node; 2155c35258dSZhenyu Wang unsigned long mfn; 2165c35258dSZhenyu Wang }; 2175c35258dSZhenyu Wang 2187d1e5cdfSZhi Wang struct intel_vgpu_page_track { 2192707e444SZhi Wang struct hlist_node node; 2207d1e5cdfSZhi Wang bool tracked; 2212707e444SZhi Wang unsigned long gfn; 2222707e444SZhi Wang int (*handler)(void *, u64, void *, int); 2232707e444SZhi Wang void *data; 2247d1e5cdfSZhi Wang }; 2257d1e5cdfSZhi Wang 2267d1e5cdfSZhi Wang struct intel_vgpu_guest_page { 2277d1e5cdfSZhi Wang struct intel_vgpu_page_track track; 2282707e444SZhi Wang unsigned long write_cnt; 2292707e444SZhi Wang struct intel_vgpu_oos_page *oos_page; 2302707e444SZhi Wang }; 2312707e444SZhi Wang 2322707e444SZhi Wang struct intel_vgpu_oos_page { 2332707e444SZhi Wang struct intel_vgpu_guest_page *guest_page; 2342707e444SZhi Wang struct list_head list; 2352707e444SZhi Wang struct list_head vm_list; 2362707e444SZhi Wang int id; 2379556e118SZhi Wang unsigned char mem[I915_GTT_PAGE_SIZE]; 2382707e444SZhi Wang }; 2392707e444SZhi Wang 2402707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512 2412707e444SZhi Wang 2422707e444SZhi Wang struct intel_vgpu_ppgtt_spt { 2432707e444SZhi Wang struct intel_vgpu_shadow_page shadow_page; 2442707e444SZhi Wang struct intel_vgpu_guest_page guest_page; 2452707e444SZhi Wang int guest_page_type; 2462707e444SZhi Wang atomic_t refcount; 2472707e444SZhi Wang struct intel_vgpu *vgpu; 2482707e444SZhi Wang DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE); 2492707e444SZhi Wang struct list_head post_shadow_list; 2502707e444SZhi Wang }; 2512707e444SZhi Wang 2527d1e5cdfSZhi Wang int intel_vgpu_init_page_track(struct intel_vgpu *vgpu, 2537d1e5cdfSZhi Wang struct intel_vgpu_page_track *t, 2542707e444SZhi Wang unsigned long gfn, 2552707e444SZhi Wang int (*handler)(void *gp, u64, void *, int), 2562707e444SZhi Wang void *data); 2572707e444SZhi Wang 2587d1e5cdfSZhi Wang void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu, 2597d1e5cdfSZhi Wang struct intel_vgpu_page_track *t); 2602707e444SZhi Wang 2617d1e5cdfSZhi Wang struct intel_vgpu_page_track *intel_vgpu_find_tracked_page( 2622707e444SZhi Wang struct intel_vgpu *vgpu, unsigned long gfn); 2632707e444SZhi Wang 2642707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); 2652707e444SZhi Wang 2662707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); 2672707e444SZhi Wang 2682707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); 2692707e444SZhi Wang 2702707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); 2712707e444SZhi Wang 2722707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, 2732707e444SZhi Wang unsigned long gma); 2742707e444SZhi Wang 2752707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 276ede9d0cfSChangbin Du u64 pdps[]); 2772707e444SZhi Wang 2782707e444SZhi Wang int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, 279ede9d0cfSChangbin Du intel_gvt_gtt_type_t root_entry_type, u64 pdps[]); 2802707e444SZhi Wang 281ede9d0cfSChangbin Du int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]); 2822707e444SZhi Wang 283*a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu, 2842707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 2852707e444SZhi Wang 286*a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, 2872707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 2882707e444SZhi Wang 2894fafba2dSZhenyu Wang int intel_vgpu_write_protect_handler(struct intel_vgpu *vgpu, u64 pa, 2904fafba2dSZhenyu Wang void *p_data, unsigned int bytes); 2914fafba2dSZhenyu Wang 2922707e444SZhi Wang #endif /* _GVT_GTT_H_ */ 293