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
3733a357daSJani Nikula #include <linux/kernel.h>
3833a357daSJani Nikula #include <linux/kref.h>
3933a357daSJani Nikula #include <linux/mutex.h>
4033a357daSJani Nikula #include <linux/radix-tree.h>
412707e444SZhi Wang
4233a357daSJani Nikula #include "gt/intel_gtt.h"
4333a357daSJani Nikula
4433a357daSJani Nikula struct intel_gvt;
4533a357daSJani Nikula struct intel_vgpu;
462707e444SZhi Wang struct intel_vgpu_mm;
472707e444SZhi Wang
4833a357daSJani Nikula #define I915_GTT_PAGE_SHIFT 12
4933a357daSJani Nikula
502707e444SZhi Wang #define INTEL_GVT_INVALID_ADDR (~0UL)
512707e444SZhi Wang
522707e444SZhi Wang struct intel_gvt_gtt_entry {
532707e444SZhi Wang u64 val64;
542707e444SZhi Wang int type;
552707e444SZhi Wang };
562707e444SZhi Wang
572707e444SZhi Wang struct intel_gvt_gtt_pte_ops {
584b2dbbc2SChangbin Du int (*get_entry)(void *pt,
592707e444SZhi Wang struct intel_gvt_gtt_entry *e,
604b2dbbc2SChangbin Du unsigned long index,
614b2dbbc2SChangbin Du bool hypervisor_access,
624b2dbbc2SChangbin Du unsigned long gpa,
632707e444SZhi Wang struct intel_vgpu *vgpu);
644b2dbbc2SChangbin Du int (*set_entry)(void *pt,
652707e444SZhi Wang struct intel_gvt_gtt_entry *e,
664b2dbbc2SChangbin Du unsigned long index,
674b2dbbc2SChangbin Du bool hypervisor_access,
684b2dbbc2SChangbin Du unsigned long gpa,
692707e444SZhi Wang struct intel_vgpu *vgpu);
702707e444SZhi Wang bool (*test_present)(struct intel_gvt_gtt_entry *e);
712707e444SZhi Wang void (*clear_present)(struct intel_gvt_gtt_entry *e);
72655c64efSZhi Wang void (*set_present)(struct intel_gvt_gtt_entry *e);
732707e444SZhi Wang bool (*test_pse)(struct intel_gvt_gtt_entry *e);
74c3e69763SChangbin Du void (*clear_pse)(struct intel_gvt_gtt_entry *e);
756fd79378SChangbin Du bool (*test_ips)(struct intel_gvt_gtt_entry *e);
766fd79378SChangbin Du void (*clear_ips)(struct intel_gvt_gtt_entry *e);
7771634848SChangbin Du bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
7871634848SChangbin Du void (*clear_64k_splited)(struct intel_gvt_gtt_entry *e);
7971634848SChangbin Du void (*set_64k_splited)(struct intel_gvt_gtt_entry *e);
802707e444SZhi Wang void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
812707e444SZhi Wang unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
822707e444SZhi Wang };
832707e444SZhi Wang
842707e444SZhi Wang struct intel_gvt_gtt_gma_ops {
852707e444SZhi Wang unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma);
862707e444SZhi Wang unsigned long (*gma_to_pte_index)(unsigned long gma);
872707e444SZhi Wang unsigned long (*gma_to_pde_index)(unsigned long gma);
882707e444SZhi Wang unsigned long (*gma_to_l3_pdp_index)(unsigned long gma);
892707e444SZhi Wang unsigned long (*gma_to_l4_pdp_index)(unsigned long gma);
902707e444SZhi Wang unsigned long (*gma_to_pml4_index)(unsigned long gma);
912707e444SZhi Wang };
922707e444SZhi Wang
932707e444SZhi Wang struct intel_gvt_gtt {
94*5512445cSRikard Falkeborn const struct intel_gvt_gtt_pte_ops *pte_ops;
95c41aadd2SRikard Falkeborn const struct intel_gvt_gtt_gma_ops *gma_ops;
962707e444SZhi Wang int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm);
972707e444SZhi Wang void (*mm_free_page_table)(struct intel_vgpu_mm *mm);
982707e444SZhi Wang struct list_head oos_page_use_list_head;
992707e444SZhi Wang struct list_head oos_page_free_list_head;
10072aabfb8SZhenyu Wang struct mutex ppgtt_mm_lock;
101ede9d0cfSChangbin Du struct list_head ppgtt_mm_lru_list_head;
102d650ac06SPing Gao
10322115cefSZhi Wang struct page *scratch_page;
10422115cefSZhi Wang unsigned long scratch_mfn;
1052707e444SZhi Wang };
1062707e444SZhi Wang
1070cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type {
1080cf8f58dSAleksei Gimbitskii GTT_TYPE_INVALID = 0,
1093b6411c2SPing Gao
1103b6411c2SPing Gao GTT_TYPE_GGTT_PTE,
1113b6411c2SPing Gao
1123b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_4K_ENTRY,
113b294657dSChangbin Du GTT_TYPE_PPGTT_PTE_64K_ENTRY,
1143b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_2M_ENTRY,
1153b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_1G_ENTRY,
1163b6411c2SPing Gao
1173b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_ENTRY,
1183b6411c2SPing Gao
1193b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_ENTRY,
1203b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_ENTRY,
1213b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_ENTRY,
1223b6411c2SPing Gao
1233b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_ENTRY,
1243b6411c2SPing Gao
1253b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
1263b6411c2SPing Gao GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
1273b6411c2SPing Gao
1283b6411c2SPing Gao GTT_TYPE_PPGTT_ENTRY,
1293b6411c2SPing Gao
1303b6411c2SPing Gao GTT_TYPE_PPGTT_PTE_PT,
1313b6411c2SPing Gao GTT_TYPE_PPGTT_PDE_PT,
1323b6411c2SPing Gao GTT_TYPE_PPGTT_PDP_PT,
1333b6411c2SPing Gao GTT_TYPE_PPGTT_PML4_PT,
1343b6411c2SPing Gao
1353b6411c2SPing Gao GTT_TYPE_MAX,
1360cf8f58dSAleksei Gimbitskii };
1373b6411c2SPing Gao
138ede9d0cfSChangbin Du enum intel_gvt_mm_type {
139ede9d0cfSChangbin Du INTEL_GVT_MM_GGTT,
140ede9d0cfSChangbin Du INTEL_GVT_MM_PPGTT,
141ede9d0cfSChangbin Du };
142ede9d0cfSChangbin Du
143ede9d0cfSChangbin Du #define GVT_RING_CTX_NR_PDPS GEN8_3LVL_PDPES
144ede9d0cfSChangbin Du
145bc0686ffSHang Yuan struct intel_gvt_partial_pte {
146bc0686ffSHang Yuan unsigned long offset;
147bc0686ffSHang Yuan u64 data;
148bc0686ffSHang Yuan struct list_head list;
149bc0686ffSHang Yuan };
150bc0686ffSHang Yuan
1512707e444SZhi Wang struct intel_vgpu_mm {
152ede9d0cfSChangbin Du enum intel_gvt_mm_type type;
153ede9d0cfSChangbin Du struct intel_vgpu *vgpu;
1542707e444SZhi Wang
1552707e444SZhi Wang struct kref ref;
1562707e444SZhi Wang atomic_t pincount;
157ede9d0cfSChangbin Du
158ede9d0cfSChangbin Du union {
159ede9d0cfSChangbin Du struct {
1600cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type;
161ede9d0cfSChangbin Du /*
162ede9d0cfSChangbin Du * The 4 PDPs in ring context. For 48bit addressing,
163ede9d0cfSChangbin Du * only PDP0 is valid and point to PML4. For 32it
164ede9d0cfSChangbin Du * addressing, all 4 are used as true PDPs.
165ede9d0cfSChangbin Du */
166ede9d0cfSChangbin Du u64 guest_pdps[GVT_RING_CTX_NR_PDPS];
167ede9d0cfSChangbin Du u64 shadow_pdps[GVT_RING_CTX_NR_PDPS];
168ede9d0cfSChangbin Du bool shadowed;
169ede9d0cfSChangbin Du
170ede9d0cfSChangbin Du struct list_head list;
1712707e444SZhi Wang struct list_head lru_list;
172bec3df93SZhenyu Wang struct list_head link; /* possible LRI shadow mm list */
173ede9d0cfSChangbin Du } ppgtt_mm;
174ede9d0cfSChangbin Du struct {
175ede9d0cfSChangbin Du void *virtual_ggtt;
1765f60b12eSColin Xu /* Save/restore for PM */
1775f60b12eSColin Xu u64 *host_ggtt_aperture;
1785f60b12eSColin Xu u64 *host_ggtt_hidden;
179bc0686ffSHang Yuan struct list_head partial_pte_list;
180ede9d0cfSChangbin Du } ggtt_mm;
181ede9d0cfSChangbin Du };
1822707e444SZhi Wang };
1832707e444SZhi Wang
184ede9d0cfSChangbin Du struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
1850cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type, u64 pdps[]);
1861bc25851SChangbin Du
intel_vgpu_mm_get(struct intel_vgpu_mm * mm)1871bc25851SChangbin Du static inline void intel_vgpu_mm_get(struct intel_vgpu_mm *mm)
1881bc25851SChangbin Du {
1891bc25851SChangbin Du kref_get(&mm->ref);
1901bc25851SChangbin Du }
1911bc25851SChangbin Du
1921bc25851SChangbin Du void _intel_vgpu_mm_release(struct kref *mm_ref);
1931bc25851SChangbin Du
intel_vgpu_mm_put(struct intel_vgpu_mm * mm)1941bc25851SChangbin Du static inline void intel_vgpu_mm_put(struct intel_vgpu_mm *mm)
1951bc25851SChangbin Du {
1961bc25851SChangbin Du kref_put(&mm->ref, _intel_vgpu_mm_release);
1971bc25851SChangbin Du }
1981bc25851SChangbin Du
intel_vgpu_destroy_mm(struct intel_vgpu_mm * mm)1991bc25851SChangbin Du static inline void intel_vgpu_destroy_mm(struct intel_vgpu_mm *mm)
2001bc25851SChangbin Du {
2011bc25851SChangbin Du intel_vgpu_mm_put(mm);
2021bc25851SChangbin Du }
2032707e444SZhi Wang
2042707e444SZhi Wang struct intel_vgpu_guest_page;
2052707e444SZhi Wang
2065c35258dSZhenyu Wang struct intel_vgpu_scratch_pt {
2073b6411c2SPing Gao struct page *page;
2085c35258dSZhenyu Wang unsigned long page_mfn;
2093b6411c2SPing Gao };
2103b6411c2SPing Gao
2112707e444SZhi Wang struct intel_vgpu_gtt {
2122707e444SZhi Wang struct intel_vgpu_mm *ggtt_mm;
2132707e444SZhi Wang unsigned long active_ppgtt_mm_bitmap;
214ede9d0cfSChangbin Du struct list_head ppgtt_mm_list_head;
215b6c126a3SChangbin Du struct radix_tree_root spt_tree;
2162707e444SZhi Wang struct list_head oos_page_list_head;
2172707e444SZhi Wang struct list_head post_shadow_list_head;
2185c35258dSZhenyu Wang struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
2192707e444SZhi Wang };
2202707e444SZhi Wang
221b5893ffcSJanusz Krzysztofik int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
222b5893ffcSJanusz Krzysztofik void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
223f4c43db3SChangbin Du void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old);
224730c8eadSZhi Wang void intel_vgpu_invalidate_ppgtt(struct intel_vgpu *vgpu);
2252707e444SZhi Wang
226b5893ffcSJanusz Krzysztofik int intel_gvt_init_gtt(struct intel_gvt *gvt);
227b5893ffcSJanusz Krzysztofik void intel_gvt_clean_gtt(struct intel_gvt *gvt);
2282707e444SZhi Wang
229b5893ffcSJanusz Krzysztofik struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
230b5893ffcSJanusz Krzysztofik int page_table_level,
231b5893ffcSJanusz Krzysztofik void *root_entry);
2322707e444SZhi Wang
2332707e444SZhi Wang struct intel_vgpu_oos_page {
23444b46733SChangbin Du struct intel_vgpu_ppgtt_spt *spt;
2352707e444SZhi Wang struct list_head list;
2362707e444SZhi Wang struct list_head vm_list;
2372707e444SZhi Wang int id;
238ed47c5cbSZhao Yakui void *mem;
2392707e444SZhi Wang };
2402707e444SZhi Wang
2412707e444SZhi Wang #define GTT_ENTRY_NUM_IN_ONE_PAGE 512
2422707e444SZhi Wang
24344b46733SChangbin Du /* Represent a vgpu shadow page table. */
2442707e444SZhi Wang struct intel_vgpu_ppgtt_spt {
2452707e444SZhi Wang atomic_t refcount;
2462707e444SZhi Wang struct intel_vgpu *vgpu;
24744b46733SChangbin Du
24844b46733SChangbin Du struct {
2490cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type type;
25040b27176SChangbin Du bool pde_ips; /* for 64KB PTEs */
25144b46733SChangbin Du void *vaddr;
25244b46733SChangbin Du struct page *page;
25344b46733SChangbin Du unsigned long mfn;
25444b46733SChangbin Du } shadow_page;
25544b46733SChangbin Du
25644b46733SChangbin Du struct {
2570cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type type;
25840b27176SChangbin Du bool pde_ips; /* for 64KB PTEs */
25944b46733SChangbin Du unsigned long gfn;
26044b46733SChangbin Du unsigned long write_cnt;
26144b46733SChangbin Du struct intel_vgpu_oos_page *oos_page;
26244b46733SChangbin Du } guest_page;
26344b46733SChangbin Du
2642707e444SZhi Wang DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
2652707e444SZhi Wang struct list_head post_shadow_list;
2662707e444SZhi Wang };
2672707e444SZhi Wang
2682707e444SZhi Wang int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
2692707e444SZhi Wang
2702707e444SZhi Wang int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu);
2712707e444SZhi Wang
2722707e444SZhi Wang int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm);
2732707e444SZhi Wang
2742707e444SZhi Wang void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm);
2752707e444SZhi Wang
2762707e444SZhi Wang unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
2772707e444SZhi Wang unsigned long gma);
2782707e444SZhi Wang
2792707e444SZhi Wang struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
280ede9d0cfSChangbin Du u64 pdps[]);
2812707e444SZhi Wang
282e6e9c46fSChangbin Du struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu,
2830cf8f58dSAleksei Gimbitskii enum intel_gvt_gtt_type root_entry_type, u64 pdps[]);
2842707e444SZhi Wang
285e6e9c46fSChangbin Du int intel_vgpu_put_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]);
2862707e444SZhi Wang
287a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu,
2882707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes);
2892707e444SZhi Wang
290a143cef7SChangbin Du int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
2912707e444SZhi Wang unsigned int off, void *p_data, unsigned int bytes);
2922707e444SZhi Wang
293ba25d977SColin Xu void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu);
2945f60b12eSColin Xu void intel_gvt_restore_ggtt(struct intel_gvt *gvt);
295ba25d977SColin Xu
2962707e444SZhi Wang #endif /* _GVT_GTT_H_ */
297