xref: /openbmc/linux/drivers/gpu/drm/i915/gvt/gtt.h (revision 655c64efe36f199bea16f9ba7388c479d5feed5f)
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);
65*655c64efSZhi 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;
872707e444SZhi Wang 	struct list_head mm_lru_list_head;
88d650ac06SPing Gao 
8922115cefSZhi Wang 	struct page *scratch_page;
9022115cefSZhi Wang 	unsigned long scratch_mfn;
912707e444SZhi Wang };
922707e444SZhi Wang 
932707e444SZhi Wang enum {
942707e444SZhi Wang 	INTEL_GVT_MM_GGTT = 0,
952707e444SZhi Wang 	INTEL_GVT_MM_PPGTT,
962707e444SZhi Wang };
972707e444SZhi Wang 
983b6411c2SPing Gao typedef enum {
993b6411c2SPing Gao 	GTT_TYPE_INVALID = -1,
1003b6411c2SPing Gao 
1013b6411c2SPing Gao 	GTT_TYPE_GGTT_PTE,
1023b6411c2SPing Gao 
1033b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_4K_ENTRY,
1043b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_2M_ENTRY,
1053b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_1G_ENTRY,
1063b6411c2SPing Gao 
1073b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_ENTRY,
1083b6411c2SPing Gao 
1093b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDE_ENTRY,
1103b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDP_ENTRY,
1113b6411c2SPing Gao 	GTT_TYPE_PPGTT_PML4_ENTRY,
1123b6411c2SPing Gao 
1133b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_ENTRY,
1143b6411c2SPing Gao 
1153b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
1163b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
1173b6411c2SPing Gao 
1183b6411c2SPing Gao 	GTT_TYPE_PPGTT_ENTRY,
1193b6411c2SPing Gao 
1203b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_PT,
1213b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDE_PT,
1223b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDP_PT,
1233b6411c2SPing Gao 	GTT_TYPE_PPGTT_PML4_PT,
1243b6411c2SPing Gao 
1253b6411c2SPing Gao 	GTT_TYPE_MAX,
1263b6411c2SPing Gao } intel_gvt_gtt_type_t;
1273b6411c2SPing Gao 
1282707e444SZhi Wang struct intel_vgpu_mm {
1292707e444SZhi Wang 	int type;
1302707e444SZhi Wang 	bool initialized;
1312707e444SZhi Wang 	bool shadowed;
1322707e444SZhi Wang 
1332707e444SZhi Wang 	int page_table_entry_type;
1342707e444SZhi Wang 	u32 page_table_entry_size;
1352707e444SZhi Wang 	u32 page_table_entry_cnt;
1362707e444SZhi Wang 	void *virtual_page_table;
1372707e444SZhi Wang 	void *shadow_page_table;
1382707e444SZhi Wang 
1392707e444SZhi Wang 	int page_table_level;
1402707e444SZhi Wang 	bool has_shadow_page_table;
1412707e444SZhi Wang 	u32 pde_base_index;
1422707e444SZhi Wang 
1432707e444SZhi Wang 	struct list_head list;
1442707e444SZhi Wang 	struct kref ref;
1452707e444SZhi Wang 	atomic_t pincount;
1462707e444SZhi Wang 	struct list_head lru_list;
1472707e444SZhi Wang 	struct intel_vgpu *vgpu;
1482707e444SZhi Wang };
1492707e444SZhi Wang 
1504b2dbbc2SChangbin Du extern int intel_vgpu_mm_get_entry(
1512707e444SZhi Wang 		struct intel_vgpu_mm *mm,
1522707e444SZhi Wang 		void *page_table, struct intel_gvt_gtt_entry *e,
1532707e444SZhi Wang 		unsigned long index);
1542707e444SZhi Wang 
1554b2dbbc2SChangbin Du extern int intel_vgpu_mm_set_entry(
1562707e444SZhi Wang 		struct intel_vgpu_mm *mm,
1572707e444SZhi Wang 		void *page_table, struct intel_gvt_gtt_entry *e,
1582707e444SZhi Wang 		unsigned long index);
1592707e444SZhi Wang 
1602707e444SZhi Wang #define ggtt_get_guest_entry(mm, e, index) \
1612707e444SZhi Wang 	intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
1622707e444SZhi Wang 
1632707e444SZhi Wang #define ggtt_set_guest_entry(mm, e, index) \
1642707e444SZhi Wang 	intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
1652707e444SZhi Wang 
1662707e444SZhi Wang #define ggtt_get_shadow_entry(mm, e, index) \
1672707e444SZhi Wang 	intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
1682707e444SZhi Wang 
1692707e444SZhi Wang #define ggtt_set_shadow_entry(mm, e, index) \
1702707e444SZhi Wang 	intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
1712707e444SZhi Wang 
1722707e444SZhi Wang #define ppgtt_get_guest_root_entry(mm, e, index) \
1732707e444SZhi Wang 	intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
1742707e444SZhi Wang 
1752707e444SZhi Wang #define ppgtt_set_guest_root_entry(mm, e, index) \
1762707e444SZhi Wang 	intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
1772707e444SZhi Wang 
1782707e444SZhi Wang #define ppgtt_get_shadow_root_entry(mm, e, index) \
1792707e444SZhi Wang 	intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
1802707e444SZhi Wang 
1812707e444SZhi Wang #define ppgtt_set_shadow_root_entry(mm, e, index) \
1822707e444SZhi Wang 	intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
1832707e444SZhi Wang 
1842707e444SZhi Wang extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
1852707e444SZhi Wang 		int mm_type, void *virtual_page_table, int page_table_level,
1862707e444SZhi Wang 		u32 pde_base_index);
1872707e444SZhi Wang extern void intel_vgpu_destroy_mm(struct kref *mm_ref);
1882707e444SZhi Wang 
1892707e444SZhi Wang struct intel_vgpu_guest_page;
1902707e444SZhi Wang 
1913b6411c2SPing Gao struct intel_vgpu_scratch_pt {
1923b6411c2SPing Gao 	struct page *page;
1933b6411c2SPing Gao 	unsigned long page_mfn;
1943b6411c2SPing Gao };
1953b6411c2SPing Gao 
1962707e444SZhi Wang struct intel_vgpu_gtt {
1972707e444SZhi Wang 	struct intel_vgpu_mm *ggtt_mm;
1982707e444SZhi Wang 	unsigned long active_ppgtt_mm_bitmap;
1992707e444SZhi Wang 	struct list_head mm_list_head;
2002707e444SZhi Wang 	DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
2017d1e5cdfSZhi Wang 	DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
2027d1e5cdfSZhi Wang 	atomic_t n_tracked_guest_page;
2032707e444SZhi Wang 	struct list_head oos_page_list_head;
2042707e444SZhi Wang 	struct list_head post_shadow_list_head;
2053b6411c2SPing Gao 	struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
2062707e444SZhi Wang };
2072707e444SZhi Wang 
2082707e444SZhi Wang extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
2092707e444SZhi Wang extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
210d650ac06SPing Gao void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
2112707e444SZhi Wang 
2122707e444SZhi Wang extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
2134d3e67bbSChuanxiao Dong void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu);
2142707e444SZhi Wang extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
2152707e444SZhi Wang 
2162707e444SZhi Wang extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
2172707e444SZhi Wang 		int page_table_level, void *root_entry);
2182707e444SZhi Wang 
2192707e444SZhi Wang struct intel_vgpu_oos_page;
2202707e444SZhi Wang 
2212707e444SZhi Wang struct intel_vgpu_shadow_page {
2222707e444SZhi Wang 	void *vaddr;
2232707e444SZhi Wang 	struct page *page;
2242707e444SZhi Wang 	int type;
2252707e444SZhi Wang 	struct hlist_node node;
2262707e444SZhi Wang 	unsigned long mfn;
2272707e444SZhi Wang };
2282707e444SZhi Wang 
2297d1e5cdfSZhi Wang struct intel_vgpu_page_track {
2302707e444SZhi Wang 	struct hlist_node node;
2317d1e5cdfSZhi Wang 	bool tracked;
2322707e444SZhi Wang 	unsigned long gfn;
2332707e444SZhi Wang 	int (*handler)(void *, u64, void *, int);
2342707e444SZhi Wang 	void *data;
2357d1e5cdfSZhi Wang };
2367d1e5cdfSZhi Wang 
2377d1e5cdfSZhi Wang struct intel_vgpu_guest_page {
2387d1e5cdfSZhi Wang 	struct intel_vgpu_page_track track;
2392707e444SZhi Wang 	unsigned long write_cnt;
2402707e444SZhi Wang 	struct intel_vgpu_oos_page *oos_page;
2412707e444SZhi Wang };
2422707e444SZhi Wang 
2432707e444SZhi Wang struct intel_vgpu_oos_page {
2442707e444SZhi Wang 	struct intel_vgpu_guest_page *guest_page;
2452707e444SZhi Wang 	struct list_head list;
2462707e444SZhi Wang 	struct list_head vm_list;
2472707e444SZhi Wang 	int id;
2489556e118SZhi Wang 	unsigned char mem[I915_GTT_PAGE_SIZE];
2492707e444SZhi Wang };
2502707e444SZhi Wang 
2512707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512
2522707e444SZhi Wang 
2532707e444SZhi Wang struct intel_vgpu_ppgtt_spt {
2542707e444SZhi Wang 	struct intel_vgpu_shadow_page shadow_page;
2552707e444SZhi Wang 	struct intel_vgpu_guest_page guest_page;
2562707e444SZhi Wang 	int guest_page_type;
2572707e444SZhi Wang 	atomic_t refcount;
2582707e444SZhi Wang 	struct intel_vgpu *vgpu;
2592707e444SZhi Wang 	DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
2602707e444SZhi Wang 	struct list_head post_shadow_list;
2612707e444SZhi Wang };
2622707e444SZhi Wang 
2637d1e5cdfSZhi Wang int intel_vgpu_init_page_track(struct intel_vgpu *vgpu,
2647d1e5cdfSZhi Wang 		struct intel_vgpu_page_track *t,
2652707e444SZhi Wang 		unsigned long gfn,
2662707e444SZhi Wang 		int (*handler)(void *gp, u64, void *, int),
2672707e444SZhi Wang 		void *data);
2682707e444SZhi Wang 
2697d1e5cdfSZhi Wang void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu,
2707d1e5cdfSZhi Wang 		struct intel_vgpu_page_track *t);
2712707e444SZhi Wang 
2727d1e5cdfSZhi Wang struct intel_vgpu_page_track *intel_vgpu_find_tracked_page(
2732707e444SZhi Wang 		struct intel_vgpu *vgpu, unsigned long gfn);
2742707e444SZhi Wang 
2752707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
2762707e444SZhi Wang 
2772707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu);
2782707e444SZhi Wang 
2792707e444SZhi Wang static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm)
2802707e444SZhi Wang {
2812707e444SZhi Wang 	kref_get(&mm->ref);
2822707e444SZhi Wang }
2832707e444SZhi Wang 
2842707e444SZhi Wang static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm)
2852707e444SZhi Wang {
2862707e444SZhi Wang 	kref_put(&mm->ref, intel_vgpu_destroy_mm);
2872707e444SZhi Wang }
2882707e444SZhi Wang 
2892707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm);
2902707e444SZhi Wang 
2912707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm);
2922707e444SZhi Wang 
2932707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
2942707e444SZhi Wang 		unsigned long gma);
2952707e444SZhi Wang 
2962707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
2972707e444SZhi Wang 		int page_table_level, void *root_entry);
2982707e444SZhi Wang 
2992707e444SZhi Wang int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
3002707e444SZhi Wang 		int page_table_level);
3012707e444SZhi Wang 
3022707e444SZhi Wang int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
3032707e444SZhi Wang 		int page_table_level);
3042707e444SZhi Wang 
3052707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
3062707e444SZhi Wang 	unsigned int off, void *p_data, unsigned int bytes);
3072707e444SZhi Wang 
3082707e444SZhi Wang int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu,
3092707e444SZhi Wang 	unsigned int off, void *p_data, unsigned int bytes);
3102707e444SZhi Wang 
3112707e444SZhi Wang #endif /* _GVT_GTT_H_ */
312