xref: /openbmc/linux/drivers/gpu/drm/i915/gvt/gtt.h (revision bc0686ff5fad7a842cc88377439e78be87fedc80)
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_INVALID_ADDR (~0UL)
432707e444SZhi Wang 
442707e444SZhi Wang struct intel_gvt_gtt_entry {
452707e444SZhi Wang 	u64 val64;
462707e444SZhi Wang 	int type;
472707e444SZhi Wang };
482707e444SZhi Wang 
492707e444SZhi Wang struct intel_gvt_gtt_pte_ops {
504b2dbbc2SChangbin Du 	int (*get_entry)(void *pt,
512707e444SZhi Wang 			 struct intel_gvt_gtt_entry *e,
524b2dbbc2SChangbin Du 			 unsigned long index,
534b2dbbc2SChangbin Du 			 bool hypervisor_access,
544b2dbbc2SChangbin Du 			 unsigned long gpa,
552707e444SZhi Wang 			 struct intel_vgpu *vgpu);
564b2dbbc2SChangbin Du 	int (*set_entry)(void *pt,
572707e444SZhi Wang 			 struct intel_gvt_gtt_entry *e,
584b2dbbc2SChangbin Du 			 unsigned long index,
594b2dbbc2SChangbin Du 			 bool hypervisor_access,
604b2dbbc2SChangbin Du 			 unsigned long gpa,
612707e444SZhi Wang 			 struct intel_vgpu *vgpu);
622707e444SZhi Wang 	bool (*test_present)(struct intel_gvt_gtt_entry *e);
632707e444SZhi Wang 	void (*clear_present)(struct intel_gvt_gtt_entry *e);
64655c64efSZhi Wang 	void (*set_present)(struct intel_gvt_gtt_entry *e);
652707e444SZhi Wang 	bool (*test_pse)(struct intel_gvt_gtt_entry *e);
66c3e69763SChangbin Du 	void (*clear_pse)(struct intel_gvt_gtt_entry *e);
676fd79378SChangbin Du 	bool (*test_ips)(struct intel_gvt_gtt_entry *e);
686fd79378SChangbin Du 	void (*clear_ips)(struct intel_gvt_gtt_entry *e);
6971634848SChangbin Du 	bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
7071634848SChangbin Du 	void (*clear_64k_splited)(struct intel_gvt_gtt_entry *e);
7171634848SChangbin Du 	void (*set_64k_splited)(struct intel_gvt_gtt_entry *e);
722707e444SZhi Wang 	void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
732707e444SZhi Wang 	unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
742707e444SZhi Wang };
752707e444SZhi Wang 
762707e444SZhi Wang struct intel_gvt_gtt_gma_ops {
772707e444SZhi Wang 	unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma);
782707e444SZhi Wang 	unsigned long (*gma_to_pte_index)(unsigned long gma);
792707e444SZhi Wang 	unsigned long (*gma_to_pde_index)(unsigned long gma);
802707e444SZhi Wang 	unsigned long (*gma_to_l3_pdp_index)(unsigned long gma);
812707e444SZhi Wang 	unsigned long (*gma_to_l4_pdp_index)(unsigned long gma);
822707e444SZhi Wang 	unsigned long (*gma_to_pml4_index)(unsigned long gma);
832707e444SZhi Wang };
842707e444SZhi Wang 
852707e444SZhi Wang struct intel_gvt_gtt {
862707e444SZhi Wang 	struct intel_gvt_gtt_pte_ops *pte_ops;
872707e444SZhi Wang 	struct intel_gvt_gtt_gma_ops *gma_ops;
882707e444SZhi Wang 	int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm);
892707e444SZhi Wang 	void (*mm_free_page_table)(struct intel_vgpu_mm *mm);
902707e444SZhi Wang 	struct list_head oos_page_use_list_head;
912707e444SZhi Wang 	struct list_head oos_page_free_list_head;
92ede9d0cfSChangbin Du 	struct list_head ppgtt_mm_lru_list_head;
93d650ac06SPing Gao 
9422115cefSZhi Wang 	struct page *scratch_page;
9522115cefSZhi Wang 	unsigned long scratch_mfn;
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,
104b294657dSChangbin Du 	GTT_TYPE_PPGTT_PTE_64K_ENTRY,
1053b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_2M_ENTRY,
1063b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_1G_ENTRY,
1073b6411c2SPing Gao 
1083b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_ENTRY,
1093b6411c2SPing Gao 
1103b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDE_ENTRY,
1113b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDP_ENTRY,
1123b6411c2SPing Gao 	GTT_TYPE_PPGTT_PML4_ENTRY,
1133b6411c2SPing Gao 
1143b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_ENTRY,
1153b6411c2SPing Gao 
1163b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
1173b6411c2SPing Gao 	GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
1183b6411c2SPing Gao 
1193b6411c2SPing Gao 	GTT_TYPE_PPGTT_ENTRY,
1203b6411c2SPing Gao 
1213b6411c2SPing Gao 	GTT_TYPE_PPGTT_PTE_PT,
1223b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDE_PT,
1233b6411c2SPing Gao 	GTT_TYPE_PPGTT_PDP_PT,
1243b6411c2SPing Gao 	GTT_TYPE_PPGTT_PML4_PT,
1253b6411c2SPing Gao 
1263b6411c2SPing Gao 	GTT_TYPE_MAX,
1273b6411c2SPing Gao } intel_gvt_gtt_type_t;
1283b6411c2SPing Gao 
129ede9d0cfSChangbin Du enum intel_gvt_mm_type {
130ede9d0cfSChangbin Du 	INTEL_GVT_MM_GGTT,
131ede9d0cfSChangbin Du 	INTEL_GVT_MM_PPGTT,
132ede9d0cfSChangbin Du };
133ede9d0cfSChangbin Du 
134ede9d0cfSChangbin Du #define GVT_RING_CTX_NR_PDPS	GEN8_3LVL_PDPES
135ede9d0cfSChangbin Du 
136*bc0686ffSHang Yuan struct intel_gvt_partial_pte {
137*bc0686ffSHang Yuan 	unsigned long offset;
138*bc0686ffSHang Yuan 	u64 data;
139*bc0686ffSHang Yuan 	struct list_head list;
140*bc0686ffSHang Yuan };
141*bc0686ffSHang Yuan 
1422707e444SZhi Wang struct intel_vgpu_mm {
143ede9d0cfSChangbin Du 	enum intel_gvt_mm_type type;
144ede9d0cfSChangbin Du 	struct intel_vgpu *vgpu;
1452707e444SZhi Wang 
1462707e444SZhi Wang 	struct kref ref;
1472707e444SZhi Wang 	atomic_t pincount;
148ede9d0cfSChangbin Du 
149ede9d0cfSChangbin Du 	union {
150ede9d0cfSChangbin Du 		struct {
151ede9d0cfSChangbin Du 			intel_gvt_gtt_type_t root_entry_type;
152ede9d0cfSChangbin Du 			/*
153ede9d0cfSChangbin Du 			 * The 4 PDPs in ring context. For 48bit addressing,
154ede9d0cfSChangbin Du 			 * only PDP0 is valid and point to PML4. For 32it
155ede9d0cfSChangbin Du 			 * addressing, all 4 are used as true PDPs.
156ede9d0cfSChangbin Du 			 */
157ede9d0cfSChangbin Du 			u64 guest_pdps[GVT_RING_CTX_NR_PDPS];
158ede9d0cfSChangbin Du 			u64 shadow_pdps[GVT_RING_CTX_NR_PDPS];
159ede9d0cfSChangbin Du 			bool shadowed;
160ede9d0cfSChangbin Du 
161ede9d0cfSChangbin Du 			struct list_head list;
1622707e444SZhi Wang 			struct list_head lru_list;
163ede9d0cfSChangbin Du 		} ppgtt_mm;
164ede9d0cfSChangbin Du 		struct {
165ede9d0cfSChangbin Du 			void *virtual_ggtt;
166*bc0686ffSHang Yuan 			struct list_head partial_pte_list;
167ede9d0cfSChangbin Du 		} ggtt_mm;
168ede9d0cfSChangbin Du 	};
1692707e444SZhi Wang };
1702707e444SZhi Wang 
171ede9d0cfSChangbin Du struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
172ede9d0cfSChangbin Du 		intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
1731bc25851SChangbin Du 
1741bc25851SChangbin Du static inline void intel_vgpu_mm_get(struct intel_vgpu_mm *mm)
1751bc25851SChangbin Du {
1761bc25851SChangbin Du 	kref_get(&mm->ref);
1771bc25851SChangbin Du }
1781bc25851SChangbin Du 
1791bc25851SChangbin Du void _intel_vgpu_mm_release(struct kref *mm_ref);
1801bc25851SChangbin Du 
1811bc25851SChangbin Du static inline void intel_vgpu_mm_put(struct intel_vgpu_mm *mm)
1821bc25851SChangbin Du {
1831bc25851SChangbin Du 	kref_put(&mm->ref, _intel_vgpu_mm_release);
1841bc25851SChangbin Du }
1851bc25851SChangbin Du 
1861bc25851SChangbin Du static inline void intel_vgpu_destroy_mm(struct intel_vgpu_mm *mm)
1871bc25851SChangbin Du {
1881bc25851SChangbin Du 	intel_vgpu_mm_put(mm);
1891bc25851SChangbin Du }
1902707e444SZhi Wang 
1912707e444SZhi Wang struct intel_vgpu_guest_page;
1922707e444SZhi Wang 
1935c35258dSZhenyu Wang struct intel_vgpu_scratch_pt {
1943b6411c2SPing Gao 	struct page *page;
1955c35258dSZhenyu Wang 	unsigned long page_mfn;
1963b6411c2SPing Gao };
1973b6411c2SPing Gao 
1982707e444SZhi Wang struct intel_vgpu_gtt {
1992707e444SZhi Wang 	struct intel_vgpu_mm *ggtt_mm;
2002707e444SZhi Wang 	unsigned long active_ppgtt_mm_bitmap;
201ede9d0cfSChangbin Du 	struct list_head ppgtt_mm_list_head;
202b6c126a3SChangbin Du 	struct radix_tree_root spt_tree;
2032707e444SZhi Wang 	struct list_head oos_page_list_head;
2042707e444SZhi Wang 	struct list_head post_shadow_list_head;
2055c35258dSZhenyu Wang 	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);
210f4c43db3SChangbin Du void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old);
211730c8eadSZhi Wang void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu);
2122707e444SZhi Wang 
2132707e444SZhi Wang extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
2144d3e67bbSChuanxiao Dong void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu);
2152707e444SZhi Wang extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
2162707e444SZhi Wang 
2172707e444SZhi Wang extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
2182707e444SZhi Wang 		int page_table_level, void *root_entry);
2192707e444SZhi Wang 
2202707e444SZhi Wang struct intel_vgpu_oos_page {
22144b46733SChangbin Du 	struct intel_vgpu_ppgtt_spt *spt;
2222707e444SZhi Wang 	struct list_head list;
2232707e444SZhi Wang 	struct list_head vm_list;
2242707e444SZhi Wang 	int id;
2259556e118SZhi Wang 	unsigned char mem[I915_GTT_PAGE_SIZE];
2262707e444SZhi Wang };
2272707e444SZhi Wang 
2282707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512
2292707e444SZhi Wang 
23044b46733SChangbin Du /* Represent a vgpu shadow page table. */
2312707e444SZhi Wang struct intel_vgpu_ppgtt_spt {
2322707e444SZhi Wang 	atomic_t refcount;
2332707e444SZhi Wang 	struct intel_vgpu *vgpu;
23444b46733SChangbin Du 
23544b46733SChangbin Du 	struct {
23644b46733SChangbin Du 		intel_gvt_gtt_type_t type;
23740b27176SChangbin Du 		bool pde_ips; /* for 64KB PTEs */
23844b46733SChangbin Du 		void *vaddr;
23944b46733SChangbin Du 		struct page *page;
24044b46733SChangbin Du 		unsigned long mfn;
24144b46733SChangbin Du 	} shadow_page;
24244b46733SChangbin Du 
24344b46733SChangbin Du 	struct {
24444b46733SChangbin Du 		intel_gvt_gtt_type_t type;
24540b27176SChangbin Du 		bool pde_ips; /* for 64KB PTEs */
24644b46733SChangbin Du 		unsigned long gfn;
24744b46733SChangbin Du 		unsigned long write_cnt;
24844b46733SChangbin Du 		struct intel_vgpu_oos_page *oos_page;
24944b46733SChangbin Du 	} guest_page;
25044b46733SChangbin Du 
2512707e444SZhi Wang 	DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
2522707e444SZhi Wang 	struct list_head post_shadow_list;
2532707e444SZhi Wang };
2542707e444SZhi Wang 
2552707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
2562707e444SZhi Wang 
2572707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu);
2582707e444SZhi Wang 
2592707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm);
2602707e444SZhi Wang 
2612707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm);
2622707e444SZhi Wang 
2632707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
2642707e444SZhi Wang 		unsigned long gma);
2652707e444SZhi Wang 
2662707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
267ede9d0cfSChangbin Du 		u64 pdps[]);
2682707e444SZhi Wang 
269e6e9c46fSChangbin Du struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu,
270ede9d0cfSChangbin Du 		intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
2712707e444SZhi Wang 
272e6e9c46fSChangbin Du int intel_vgpu_put_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]);
2732707e444SZhi Wang 
274a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu,
2752707e444SZhi Wang 	unsigned int off, void *p_data, unsigned int bytes);
2762707e444SZhi Wang 
277a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
2782707e444SZhi Wang 	unsigned int off, void *p_data, unsigned int bytes);
2792707e444SZhi Wang 
2802707e444SZhi Wang #endif /* _GVT_GTT_H_ */
281