1*2707e444SZhi Wang /* 2*2707e444SZhi Wang * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 3*2707e444SZhi Wang * 4*2707e444SZhi Wang * Permission is hereby granted, free of charge, to any person obtaining a 5*2707e444SZhi Wang * copy of this software and associated documentation files (the "Software"), 6*2707e444SZhi Wang * to deal in the Software without restriction, including without limitation 7*2707e444SZhi Wang * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*2707e444SZhi Wang * and/or sell copies of the Software, and to permit persons to whom the 9*2707e444SZhi Wang * Software is furnished to do so, subject to the following conditions: 10*2707e444SZhi Wang * 11*2707e444SZhi Wang * The above copyright notice and this permission notice (including the next 12*2707e444SZhi Wang * paragraph) shall be included in all copies or substantial portions of the 13*2707e444SZhi Wang * Software. 14*2707e444SZhi Wang * 15*2707e444SZhi Wang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*2707e444SZhi Wang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*2707e444SZhi Wang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*2707e444SZhi Wang * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*2707e444SZhi Wang * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20*2707e444SZhi Wang * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21*2707e444SZhi Wang * SOFTWARE. 22*2707e444SZhi Wang * 23*2707e444SZhi Wang * Authors: 24*2707e444SZhi Wang * Zhi Wang <zhi.a.wang@intel.com> 25*2707e444SZhi Wang * Zhenyu Wang <zhenyuw@linux.intel.com> 26*2707e444SZhi Wang * Xiao Zheng <xiao.zheng@intel.com> 27*2707e444SZhi Wang * 28*2707e444SZhi Wang * Contributors: 29*2707e444SZhi Wang * Min He <min.he@intel.com> 30*2707e444SZhi Wang * Bing Niu <bing.niu@intel.com> 31*2707e444SZhi Wang * 32*2707e444SZhi Wang */ 33*2707e444SZhi Wang 34*2707e444SZhi Wang #ifndef _GVT_GTT_H_ 35*2707e444SZhi Wang #define _GVT_GTT_H_ 36*2707e444SZhi Wang 37*2707e444SZhi Wang #define GTT_PAGE_SHIFT 12 38*2707e444SZhi Wang #define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT) 39*2707e444SZhi Wang #define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1)) 40*2707e444SZhi Wang 41*2707e444SZhi Wang struct intel_vgpu_mm; 42*2707e444SZhi Wang 43*2707e444SZhi Wang #define INTEL_GVT_GTT_HASH_BITS 8 44*2707e444SZhi Wang #define INTEL_GVT_INVALID_ADDR (~0UL) 45*2707e444SZhi Wang 46*2707e444SZhi Wang struct intel_gvt_gtt_entry { 47*2707e444SZhi Wang u64 val64; 48*2707e444SZhi Wang int type; 49*2707e444SZhi Wang }; 50*2707e444SZhi Wang 51*2707e444SZhi Wang struct intel_gvt_gtt_pte_ops { 52*2707e444SZhi Wang struct intel_gvt_gtt_entry *(*get_entry)(void *pt, 53*2707e444SZhi Wang struct intel_gvt_gtt_entry *e, 54*2707e444SZhi Wang unsigned long index, bool hypervisor_access, unsigned long gpa, 55*2707e444SZhi Wang struct intel_vgpu *vgpu); 56*2707e444SZhi Wang struct intel_gvt_gtt_entry *(*set_entry)(void *pt, 57*2707e444SZhi Wang struct intel_gvt_gtt_entry *e, 58*2707e444SZhi Wang unsigned long index, bool hypervisor_access, unsigned long gpa, 59*2707e444SZhi Wang struct intel_vgpu *vgpu); 60*2707e444SZhi Wang bool (*test_present)(struct intel_gvt_gtt_entry *e); 61*2707e444SZhi Wang void (*clear_present)(struct intel_gvt_gtt_entry *e); 62*2707e444SZhi Wang bool (*test_pse)(struct intel_gvt_gtt_entry *e); 63*2707e444SZhi Wang void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); 64*2707e444SZhi Wang unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); 65*2707e444SZhi Wang }; 66*2707e444SZhi Wang 67*2707e444SZhi Wang struct intel_gvt_gtt_gma_ops { 68*2707e444SZhi Wang unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); 69*2707e444SZhi Wang unsigned long (*gma_to_pte_index)(unsigned long gma); 70*2707e444SZhi Wang unsigned long (*gma_to_pde_index)(unsigned long gma); 71*2707e444SZhi Wang unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); 72*2707e444SZhi Wang unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); 73*2707e444SZhi Wang unsigned long (*gma_to_pml4_index)(unsigned long gma); 74*2707e444SZhi Wang }; 75*2707e444SZhi Wang 76*2707e444SZhi Wang struct intel_gvt_gtt { 77*2707e444SZhi Wang struct intel_gvt_gtt_pte_ops *pte_ops; 78*2707e444SZhi Wang struct intel_gvt_gtt_gma_ops *gma_ops; 79*2707e444SZhi Wang int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); 80*2707e444SZhi Wang void (*mm_free_page_table)(struct intel_vgpu_mm *mm); 81*2707e444SZhi Wang struct list_head oos_page_use_list_head; 82*2707e444SZhi Wang struct list_head oos_page_free_list_head; 83*2707e444SZhi Wang struct list_head mm_lru_list_head; 84*2707e444SZhi Wang }; 85*2707e444SZhi Wang 86*2707e444SZhi Wang enum { 87*2707e444SZhi Wang INTEL_GVT_MM_GGTT = 0, 88*2707e444SZhi Wang INTEL_GVT_MM_PPGTT, 89*2707e444SZhi Wang }; 90*2707e444SZhi Wang 91*2707e444SZhi Wang struct intel_vgpu_mm { 92*2707e444SZhi Wang int type; 93*2707e444SZhi Wang bool initialized; 94*2707e444SZhi Wang bool shadowed; 95*2707e444SZhi Wang 96*2707e444SZhi Wang int page_table_entry_type; 97*2707e444SZhi Wang u32 page_table_entry_size; 98*2707e444SZhi Wang u32 page_table_entry_cnt; 99*2707e444SZhi Wang void *virtual_page_table; 100*2707e444SZhi Wang void *shadow_page_table; 101*2707e444SZhi Wang 102*2707e444SZhi Wang int page_table_level; 103*2707e444SZhi Wang bool has_shadow_page_table; 104*2707e444SZhi Wang u32 pde_base_index; 105*2707e444SZhi Wang 106*2707e444SZhi Wang struct list_head list; 107*2707e444SZhi Wang struct kref ref; 108*2707e444SZhi Wang atomic_t pincount; 109*2707e444SZhi Wang struct list_head lru_list; 110*2707e444SZhi Wang struct intel_vgpu *vgpu; 111*2707e444SZhi Wang }; 112*2707e444SZhi Wang 113*2707e444SZhi Wang extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry( 114*2707e444SZhi Wang struct intel_vgpu_mm *mm, 115*2707e444SZhi Wang void *page_table, struct intel_gvt_gtt_entry *e, 116*2707e444SZhi Wang unsigned long index); 117*2707e444SZhi Wang 118*2707e444SZhi Wang extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry( 119*2707e444SZhi Wang struct intel_vgpu_mm *mm, 120*2707e444SZhi Wang void *page_table, struct intel_gvt_gtt_entry *e, 121*2707e444SZhi Wang unsigned long index); 122*2707e444SZhi Wang 123*2707e444SZhi Wang #define ggtt_get_guest_entry(mm, e, index) \ 124*2707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 125*2707e444SZhi Wang 126*2707e444SZhi Wang #define ggtt_set_guest_entry(mm, e, index) \ 127*2707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 128*2707e444SZhi Wang 129*2707e444SZhi Wang #define ggtt_get_shadow_entry(mm, e, index) \ 130*2707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 131*2707e444SZhi Wang 132*2707e444SZhi Wang #define ggtt_set_shadow_entry(mm, e, index) \ 133*2707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 134*2707e444SZhi Wang 135*2707e444SZhi Wang #define ppgtt_get_guest_root_entry(mm, e, index) \ 136*2707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 137*2707e444SZhi Wang 138*2707e444SZhi Wang #define ppgtt_set_guest_root_entry(mm, e, index) \ 139*2707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 140*2707e444SZhi Wang 141*2707e444SZhi Wang #define ppgtt_get_shadow_root_entry(mm, e, index) \ 142*2707e444SZhi Wang intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 143*2707e444SZhi Wang 144*2707e444SZhi Wang #define ppgtt_set_shadow_root_entry(mm, e, index) \ 145*2707e444SZhi Wang intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 146*2707e444SZhi Wang 147*2707e444SZhi Wang extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, 148*2707e444SZhi Wang int mm_type, void *virtual_page_table, int page_table_level, 149*2707e444SZhi Wang u32 pde_base_index); 150*2707e444SZhi Wang extern void intel_vgpu_destroy_mm(struct kref *mm_ref); 151*2707e444SZhi Wang 152*2707e444SZhi Wang struct intel_vgpu_guest_page; 153*2707e444SZhi Wang 154*2707e444SZhi Wang struct intel_vgpu_gtt { 155*2707e444SZhi Wang struct intel_vgpu_mm *ggtt_mm; 156*2707e444SZhi Wang unsigned long active_ppgtt_mm_bitmap; 157*2707e444SZhi Wang struct list_head mm_list_head; 158*2707e444SZhi Wang DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 159*2707e444SZhi Wang DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 160*2707e444SZhi Wang atomic_t n_write_protected_guest_page; 161*2707e444SZhi Wang struct list_head oos_page_list_head; 162*2707e444SZhi Wang struct list_head post_shadow_list_head; 163*2707e444SZhi Wang struct page *scratch_page; 164*2707e444SZhi Wang unsigned long scratch_page_mfn; 165*2707e444SZhi Wang }; 166*2707e444SZhi Wang 167*2707e444SZhi Wang extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); 168*2707e444SZhi Wang extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); 169*2707e444SZhi Wang 170*2707e444SZhi Wang extern int intel_gvt_init_gtt(struct intel_gvt *gvt); 171*2707e444SZhi Wang extern void intel_gvt_clean_gtt(struct intel_gvt *gvt); 172*2707e444SZhi Wang 173*2707e444SZhi Wang extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, 174*2707e444SZhi Wang int page_table_level, void *root_entry); 175*2707e444SZhi Wang 176*2707e444SZhi Wang struct intel_vgpu_oos_page; 177*2707e444SZhi Wang 178*2707e444SZhi Wang struct intel_vgpu_shadow_page { 179*2707e444SZhi Wang void *vaddr; 180*2707e444SZhi Wang struct page *page; 181*2707e444SZhi Wang int type; 182*2707e444SZhi Wang struct hlist_node node; 183*2707e444SZhi Wang unsigned long mfn; 184*2707e444SZhi Wang }; 185*2707e444SZhi Wang 186*2707e444SZhi Wang struct intel_vgpu_guest_page { 187*2707e444SZhi Wang struct hlist_node node; 188*2707e444SZhi Wang bool writeprotection; 189*2707e444SZhi Wang unsigned long gfn; 190*2707e444SZhi Wang int (*handler)(void *, u64, void *, int); 191*2707e444SZhi Wang void *data; 192*2707e444SZhi Wang unsigned long write_cnt; 193*2707e444SZhi Wang struct intel_vgpu_oos_page *oos_page; 194*2707e444SZhi Wang }; 195*2707e444SZhi Wang 196*2707e444SZhi Wang struct intel_vgpu_oos_page { 197*2707e444SZhi Wang struct intel_vgpu_guest_page *guest_page; 198*2707e444SZhi Wang struct list_head list; 199*2707e444SZhi Wang struct list_head vm_list; 200*2707e444SZhi Wang int id; 201*2707e444SZhi Wang unsigned char mem[GTT_PAGE_SIZE]; 202*2707e444SZhi Wang }; 203*2707e444SZhi Wang 204*2707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512 205*2707e444SZhi Wang 206*2707e444SZhi Wang struct intel_vgpu_ppgtt_spt { 207*2707e444SZhi Wang struct intel_vgpu_shadow_page shadow_page; 208*2707e444SZhi Wang struct intel_vgpu_guest_page guest_page; 209*2707e444SZhi Wang int guest_page_type; 210*2707e444SZhi Wang atomic_t refcount; 211*2707e444SZhi Wang struct intel_vgpu *vgpu; 212*2707e444SZhi Wang DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE); 213*2707e444SZhi Wang struct list_head post_shadow_list; 214*2707e444SZhi Wang }; 215*2707e444SZhi Wang 216*2707e444SZhi Wang int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, 217*2707e444SZhi Wang struct intel_vgpu_guest_page *guest_page, 218*2707e444SZhi Wang unsigned long gfn, 219*2707e444SZhi Wang int (*handler)(void *gp, u64, void *, int), 220*2707e444SZhi Wang void *data); 221*2707e444SZhi Wang 222*2707e444SZhi Wang void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, 223*2707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 224*2707e444SZhi Wang 225*2707e444SZhi Wang int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, 226*2707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 227*2707e444SZhi Wang 228*2707e444SZhi Wang void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu, 229*2707e444SZhi Wang struct intel_vgpu_guest_page *guest_page); 230*2707e444SZhi Wang 231*2707e444SZhi Wang struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( 232*2707e444SZhi Wang struct intel_vgpu *vgpu, unsigned long gfn); 233*2707e444SZhi Wang 234*2707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); 235*2707e444SZhi Wang 236*2707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); 237*2707e444SZhi Wang 238*2707e444SZhi Wang static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm) 239*2707e444SZhi Wang { 240*2707e444SZhi Wang kref_get(&mm->ref); 241*2707e444SZhi Wang } 242*2707e444SZhi Wang 243*2707e444SZhi Wang static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm) 244*2707e444SZhi Wang { 245*2707e444SZhi Wang kref_put(&mm->ref, intel_vgpu_destroy_mm); 246*2707e444SZhi Wang } 247*2707e444SZhi Wang 248*2707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); 249*2707e444SZhi Wang 250*2707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); 251*2707e444SZhi Wang 252*2707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, 253*2707e444SZhi Wang unsigned long gma); 254*2707e444SZhi Wang 255*2707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 256*2707e444SZhi Wang int page_table_level, void *root_entry); 257*2707e444SZhi Wang 258*2707e444SZhi Wang int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, 259*2707e444SZhi Wang int page_table_level); 260*2707e444SZhi Wang 261*2707e444SZhi Wang int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, 262*2707e444SZhi Wang int page_table_level); 263*2707e444SZhi Wang 264*2707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, 265*2707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 266*2707e444SZhi Wang 267*2707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, 268*2707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes); 269*2707e444SZhi Wang 270*2707e444SZhi Wang #endif /* _GVT_GTT_H_ */ 271