Commit | Line | Data |
---|---|---|
56283174 LB |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* | |
02f3effd | 3 | * pasid.h - PASID idr, table and entry header |
56283174 LB |
4 | * |
5 | * Copyright (C) 2018 Intel Corporation | |
6 | * | |
7 | * Author: Lu Baolu <baolu.lu@linux.intel.com> | |
8 | */ | |
9 | ||
10 | #ifndef __INTEL_PASID_H | |
11 | #define __INTEL_PASID_H | |
12 | ||
ef848b7e | 13 | #define PASID_RID2PASID 0x0 |
56283174 | 14 | #define PASID_MIN 0x1 |
0bbeb01a LB |
15 | #define PASID_MAX 0x100000 |
16 | #define PASID_PTE_MASK 0x3F | |
17 | #define PASID_PTE_PRESENT 1 | |
37e91bd4 | 18 | #define PASID_PTE_FPD 2 |
0bbeb01a LB |
19 | #define PDE_PFN_MASK PAGE_MASK |
20 | #define PASID_PDE_SHIFT 6 | |
7373a8cc | 21 | #define MAX_NR_PASID_BITS 20 |
cdd3a249 SPP |
22 | #define PASID_TBL_ENTRIES BIT(PASID_PDE_SHIFT) |
23 | ||
24 | #define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1) | |
25 | #define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7)) | |
56283174 | 26 | |
24f27d32 LB |
27 | /* Virtual command interface for enlightened pasid management. */ |
28 | #define VCMD_CMD_ALLOC 0x1 | |
29 | #define VCMD_CMD_FREE 0x2 | |
30 | #define VCMD_VRSP_IP 0x1 | |
4d99efb2 | 31 | #define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1) |
24f27d32 | 32 | #define VCMD_VRSP_SC_SUCCESS 0 |
4d99efb2 LB |
33 | #define VCMD_VRSP_SC_NO_PASID_AVAIL 16 |
34 | #define VCMD_VRSP_SC_INVALID_PASID 16 | |
35 | #define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff) | |
36 | #define VCMD_CMD_OPERAND(e) ((e) << 16) | |
3b33d4ab LB |
37 | /* |
38 | * Domain ID reserved for pasid entries programmed for first-level | |
39 | * only and pass-through transfer modes. | |
40 | */ | |
41 | #define FLPT_DEFAULT_DID 1 | |
42 | ||
437f35e1 LB |
43 | /* |
44 | * The SUPERVISOR_MODE flag indicates a first level translation which | |
45 | * can be used for access to kernel addresses. It is valid only for | |
46 | * access to the kernel's static 1:1 mapping of physical memory — not | |
47 | * to vmalloc or even module mappings. | |
48 | */ | |
49 | #define PASID_FLAG_SUPERVISOR_MODE BIT(0) | |
b0d1f874 | 50 | #define PASID_FLAG_NESTED BIT(1) |
6c00612d | 51 | #define PASID_FLAG_PAGE_SNOOP BIT(2) |
437f35e1 | 52 | |
87208f22 LB |
53 | /* |
54 | * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first- | |
55 | * level translation, otherwise, 4-level paging will be used. | |
56 | */ | |
57 | #define PASID_FLAG_FL5LP BIT(1) | |
58 | ||
0bbeb01a | 59 | struct pasid_dir_entry { |
cc580e41 LB |
60 | u64 val; |
61 | }; | |
62 | ||
0bbeb01a LB |
63 | struct pasid_entry { |
64 | u64 val[8]; | |
65 | }; | |
66 | ||
b0d1f874 JP |
67 | #define PASID_ENTRY_PGTT_FL_ONLY (1) |
68 | #define PASID_ENTRY_PGTT_SL_ONLY (2) | |
69 | #define PASID_ENTRY_PGTT_NESTED (3) | |
70 | #define PASID_ENTRY_PGTT_PT (4) | |
71 | ||
cc580e41 LB |
72 | /* The representative of a PASID table */ |
73 | struct pasid_table { | |
74 | void *table; /* pasid table pointer */ | |
75 | int order; /* page order of pasid table */ | |
c7b6bac9 | 76 | u32 max_pasid; /* max pasid */ |
cc580e41 LB |
77 | }; |
78 | ||
cdd3a249 SPP |
79 | /* Get PRESENT bit of a PASID directory entry. */ |
80 | static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde) | |
81 | { | |
82 | return READ_ONCE(pde->val) & PASID_PTE_PRESENT; | |
83 | } | |
84 | ||
85 | /* Get PASID table from a PASID directory entry. */ | |
86 | static inline struct pasid_entry * | |
87 | get_pasid_table_from_pde(struct pasid_dir_entry *pde) | |
88 | { | |
89 | if (!pasid_pde_is_present(pde)) | |
90 | return NULL; | |
91 | ||
92 | return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK); | |
93 | } | |
94 | ||
95 | /* Get PRESENT bit of a PASID table entry. */ | |
96 | static inline bool pasid_pte_is_present(struct pasid_entry *pte) | |
97 | { | |
98 | return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT; | |
99 | } | |
100 | ||
8798d364 LY |
101 | /* Get PGTT field of a PASID table entry */ |
102 | static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte) | |
103 | { | |
104 | return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7); | |
105 | } | |
106 | ||
c7b6bac9 | 107 | extern unsigned int intel_pasid_max_id; |
cc580e41 LB |
108 | int intel_pasid_alloc_table(struct device *dev); |
109 | void intel_pasid_free_table(struct device *dev); | |
110 | struct pasid_table *intel_pasid_get_table(struct device *dev); | |
437f35e1 LB |
111 | int intel_pasid_setup_first_level(struct intel_iommu *iommu, |
112 | struct device *dev, pgd_t *pgd, | |
c7b6bac9 | 113 | u32 pasid, u16 did, int flags); |
6f7db75e LB |
114 | int intel_pasid_setup_second_level(struct intel_iommu *iommu, |
115 | struct dmar_domain *domain, | |
c7b6bac9 | 116 | struct device *dev, u32 pasid); |
6f7db75e LB |
117 | int intel_pasid_setup_pass_through(struct intel_iommu *iommu, |
118 | struct dmar_domain *domain, | |
c7b6bac9 | 119 | struct device *dev, u32 pasid); |
6f7db75e | 120 | void intel_pasid_tear_down_entry(struct intel_iommu *iommu, |
c7b6bac9 | 121 | struct device *dev, u32 pasid, |
37e91bd4 | 122 | bool fault_ignore); |
c7b6bac9 FY |
123 | int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid); |
124 | void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid); | |
fc0051cb LB |
125 | void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, |
126 | struct device *dev, u32 pasid); | |
56283174 | 127 | #endif /* __INTEL_PASID_H */ |