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 372707e444SZhi Wang #define GTT_PAGE_SHIFT 12 382707e444SZhi Wang #define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT) 392707e444SZhi Wang #define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1)) 402707e444SZhi Wang 412707e444SZhi Wang struct intel_vgpu_mm; 422707e444SZhi Wang 432707e444SZhi Wang #define INTEL_GVT_GTT_HASH_BITS 8 442707e444SZhi Wang #define INTEL_GVT_INVALID_ADDR (~0UL) 452707e444SZhi Wang 462707e444SZhi Wang struct intel_gvt_gtt_entry { 472707e444SZhi Wang u64 val64; 482707e444SZhi Wang int type; 492707e444SZhi Wang }; 502707e444SZhi Wang 512707e444SZhi Wang struct intel_gvt_gtt_pte_ops { 522707e444SZhi Wang struct intel_gvt_gtt_entry *(*get_entry)(void *pt, 532707e444SZhi Wang struct intel_gvt_gtt_entry *e, 542707e444SZhi Wang unsigned long index, bool hypervisor_access, unsigned long gpa, 552707e444SZhi Wang struct intel_vgpu *vgpu); 562707e444SZhi Wang struct intel_gvt_gtt_entry *(*set_entry)(void *pt, 572707e444SZhi Wang struct intel_gvt_gtt_entry *e, 582707e444SZhi Wang unsigned long index, bool hypervisor_access, unsigned long gpa, 592707e444SZhi Wang struct intel_vgpu *vgpu); 602707e444SZhi Wang bool (*test_present)(struct intel_gvt_gtt_entry *e); 612707e444SZhi Wang void (*clear_present)(struct intel_gvt_gtt_entry *e); 622707e444SZhi Wang bool (*test_pse)(struct intel_gvt_gtt_entry *e); 632707e444SZhi Wang void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); 642707e444SZhi Wang unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); 652707e444SZhi Wang }; 662707e444SZhi Wang 672707e444SZhi Wang struct intel_gvt_gtt_gma_ops { 682707e444SZhi Wang unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); 692707e444SZhi Wang unsigned long (*gma_to_pte_index)(unsigned long gma); 702707e444SZhi Wang unsigned long (*gma_to_pde_index)(unsigned long gma); 712707e444SZhi Wang unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); 722707e444SZhi Wang unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); 732707e444SZhi Wang unsigned long (*gma_to_pml4_index)(unsigned long gma); 742707e444SZhi Wang }; 752707e444SZhi Wang 762707e444SZhi Wang struct intel_gvt_gtt { 772707e444SZhi Wang struct intel_gvt_gtt_pte_ops *pte_ops; 782707e444SZhi Wang struct intel_gvt_gtt_gma_ops *gma_ops; 792707e444SZhi Wang int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); 802707e444SZhi Wang void (*mm_free_page_table)(struct intel_vgpu_mm *mm); 812707e444SZhi Wang struct list_head oos_page_use_list_head; 822707e444SZhi Wang struct list_head oos_page_free_list_head; 832707e444SZhi Wang struct list_head mm_lru_list_head; 842707e444SZhi Wang }; 852707e444SZhi Wang 862707e444SZhi Wang enum { 872707e444SZhi Wang INTEL_GVT_MM_GGTT = 0, 882707e444SZhi Wang INTEL_GVT_MM_PPGTT, 892707e444SZhi Wang }; 902707e444SZhi Wang 91*3b6411c2SPing Gao typedef enum { 92*3b6411c2SPing Gao GTT_TYPE_INVALID = -1, 93*3b6411c2SPing Gao 94*3b6411c2SPing Gao GTT_TYPE_GGTT_PTE, 95*3b6411c2SPing Gao 96*3b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_4K_ENTRY, 97*3b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_2M_ENTRY, 98*3b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_1G_ENTRY, 99*3b6411c2SPing Gao 100*3b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_ENTRY, 101*3b6411c2SPing Gao 102*3b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_ENTRY, 103*3b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_ENTRY, 104*3b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_ENTRY, 105*3b6411c2SPing Gao 106*3b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_ENTRY, 107*3b6411c2SPing Gao 108*3b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L3_ENTRY, 109*3b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L4_ENTRY, 110*3b6411c2SPing Gao 111*3b6411c2SPing Gao GTT_TYPE_PPGTT_ENTRY, 112*3b6411c2SPing Gao 113*3b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_PT, 114*3b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_PT, 115*3b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_PT, 116*3b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_PT, 117*3b6411c2SPing Gao 118*3b6411c2SPing Gao GTT_TYPE_MAX, 119*3b6411c2SPing Gao } intel_gvt_gtt_type_t; 120*3b6411c2SPing Gao 1212707e444SZhi Wang struct intel_vgpu_mm { 1222707e444SZhi Wang int type; 1232707e444SZhi Wang bool initialized; 1242707e444SZhi Wang bool shadowed; 1252707e444SZhi Wang 1262707e444SZhi Wang int page_table_entry_type; 1272707e444SZhi Wang u32 page_table_entry_size; 1282707e444SZhi Wang u32 page_table_entry_cnt; 1292707e444SZhi Wang void *virtual_page_table; 1302707e444SZhi Wang void *shadow_page_table; 1312707e444SZhi Wang 1322707e444SZhi Wang int page_table_level; 1332707e444SZhi Wang bool has_shadow_page_table; 1342707e444SZhi Wang u32 pde_base_index; 1352707e444SZhi Wang 1362707e444SZhi Wang struct list_head list; 1372707e444SZhi Wang struct kref ref; 1382707e444SZhi Wang atomic_t pincount; 1392707e444SZhi Wang struct list_head lru_list; 1402707e444SZhi Wang struct intel_vgpu *vgpu; 1412707e444SZhi Wang }; 1422707e444SZhi Wang 1432707e444SZhi Wang extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry( 1442707e444SZhi Wang struct intel_vgpu_mm *mm, 1452707e444SZhi Wang void *page_table, struct intel_gvt_gtt_entry *e, 1462707e444SZhi Wang unsigned long index); 1472707e444SZhi Wang 1482707e444SZhi Wang extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry( 1492707e444SZhi Wang struct intel_vgpu_mm *mm, 1502707e444SZhi Wang void *page_table, struct intel_gvt_gtt_entry *e, 1512707e444SZhi Wang unsigned long index); 1522707e444SZhi Wang 1532707e444SZhi Wang #define ggtt_get_guest_entry(mm, e, index) \ 1542707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 1552707e444SZhi Wang 1562707e444SZhi Wang #define ggtt_set_guest_entry(mm, e, index) \ 1572707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 1582707e444SZhi Wang 1592707e444SZhi Wang #define ggtt_get_shadow_entry(mm, e, index) \ 1602707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 1612707e444SZhi Wang 1622707e444SZhi Wang #define ggtt_set_shadow_entry(mm, e, index) \ 1632707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 1642707e444SZhi Wang 1652707e444SZhi Wang #define ppgtt_get_guest_root_entry(mm, e, index) \ 1662707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 1672707e444SZhi Wang 1682707e444SZhi Wang #define ppgtt_set_guest_root_entry(mm, e, index) \ 1692707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 1702707e444SZhi Wang 1712707e444SZhi Wang #define ppgtt_get_shadow_root_entry(mm, e, index) \ 1722707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 1732707e444SZhi Wang 1742707e444SZhi Wang #define ppgtt_set_shadow_root_entry(mm, e, index) \ 1752707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 1762707e444SZhi Wang 1772707e444SZhi Wang extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, 1782707e444SZhi Wang int mm_type, void *virtual_page_table, int page_table_level, 1792707e444SZhi Wang u32 pde_base_index); 1802707e444SZhi Wang extern void intel_vgpu_destroy_mm(struct kref *mm_ref); 1812707e444SZhi Wang 1822707e444SZhi Wang struct intel_vgpu_guest_page; 1832707e444SZhi Wang 184*3b6411c2SPing Gao struct intel_vgpu_scratch_pt { 185*3b6411c2SPing Gao struct page *page; 186*3b6411c2SPing Gao unsigned long page_mfn; 187*3b6411c2SPing Gao }; 188*3b6411c2SPing Gao 189*3b6411c2SPing Gao 1902707e444SZhi Wang struct intel_vgpu_gtt { 1912707e444SZhi Wang struct intel_vgpu_mm *ggtt_mm; 1922707e444SZhi Wang unsigned long active_ppgtt_mm_bitmap; 1932707e444SZhi Wang struct list_head mm_list_head; 1942707e444SZhi Wang DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 1952707e444SZhi Wang DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 1962707e444SZhi Wang atomic_t n_write_protected_guest_page; 1972707e444SZhi Wang struct list_head oos_page_list_head; 1982707e444SZhi Wang struct list_head post_shadow_list_head; 199*3b6411c2SPing Gao struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX]; 200*3b6411c2SPing Gao 2012707e444SZhi Wang }; 2022707e444SZhi Wang 2032707e444SZhi Wang extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); 2042707e444SZhi Wang extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); 2052707e444SZhi Wang 2062707e444SZhi Wang extern int intel_gvt_init_gtt(struct intel_gvt *gvt); 2072707e444SZhi Wang extern void intel_gvt_clean_gtt(struct intel_gvt *gvt); 2082707e444SZhi Wang 2092707e444SZhi Wang extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, 2102707e444SZhi Wang int page_table_level, void *root_entry); 2112707e444SZhi Wang 2122707e444SZhi Wang struct intel_vgpu_oos_page; 2132707e444SZhi Wang 2142707e444SZhi Wang struct intel_vgpu_shadow_page { 2152707e444SZhi Wang void *vaddr; 2162707e444SZhi Wang struct page *page; 2172707e444SZhi Wang int type; 2182707e444SZhi Wang struct hlist_node node; 2192707e444SZhi Wang unsigned long mfn; 2202707e444SZhi Wang }; 2212707e444SZhi Wang 2222707e444SZhi Wang struct intel_vgpu_guest_page { 2232707e444SZhi Wang struct hlist_node node; 2242707e444SZhi Wang bool writeprotection; 2252707e444SZhi Wang unsigned long gfn; 2262707e444SZhi Wang int (*handler)(void *, u64, void *, int); 2272707e444SZhi Wang void *data; 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; 2372707e444SZhi Wang unsigned char mem[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 2522707e444SZhi Wang int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, 2532707e444SZhi Wang struct intel_vgpu_guest_page *guest_page, 2542707e444SZhi Wang unsigned long gfn, 2552707e444SZhi Wang int (*handler)(void *gp, u64, void *, int), 2562707e444SZhi Wang void *data); 2572707e444SZhi Wang 2582707e444SZhi Wang void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, 2592707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 2602707e444SZhi Wang 2612707e444SZhi Wang int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, 2622707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 2632707e444SZhi Wang 2642707e444SZhi Wang void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu, 2652707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 2662707e444SZhi Wang 2672707e444SZhi Wang struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( 2682707e444SZhi Wang struct intel_vgpu *vgpu, unsigned long gfn); 2692707e444SZhi Wang 2702707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); 2712707e444SZhi Wang 2722707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); 2732707e444SZhi Wang 2742707e444SZhi Wang static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm) 2752707e444SZhi Wang { 2762707e444SZhi Wang kref_get(&mm->ref); 2772707e444SZhi Wang } 2782707e444SZhi Wang 2792707e444SZhi Wang static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm) 2802707e444SZhi Wang { 2812707e444SZhi Wang kref_put(&mm->ref, intel_vgpu_destroy_mm); 2822707e444SZhi Wang } 2832707e444SZhi Wang 2842707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); 2852707e444SZhi Wang 2862707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); 2872707e444SZhi Wang 2882707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, 2892707e444SZhi Wang unsigned long gma); 2902707e444SZhi Wang 2912707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 2922707e444SZhi Wang int page_table_level, void *root_entry); 2932707e444SZhi Wang 2942707e444SZhi Wang int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, 2952707e444SZhi Wang int page_table_level); 2962707e444SZhi Wang 2972707e444SZhi Wang int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, 2982707e444SZhi Wang int page_table_level); 2992707e444SZhi Wang 3002707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, 3012707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 3022707e444SZhi Wang 3032707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, 3042707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 3052707e444SZhi Wang 3062707e444SZhi Wang #endif /* _GVT_GTT_H_ */ 307