Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * pasid.h - PASID idr, table and entry header
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
13#define PASID_MAX 0x100000
14#define PASID_PTE_MASK 0x3F
15#define PASID_PTE_PRESENT 1
16#define PASID_PTE_FPD 2
17#define PDE_PFN_MASK PAGE_MASK
18#define PASID_PDE_SHIFT 6
19#define MAX_NR_PASID_BITS 20
20#define PASID_TBL_ENTRIES BIT(PASID_PDE_SHIFT)
21
22#define is_pasid_enabled(entry) (((entry)->lo >> 3) & 0x1)
23#define get_pasid_dir_size(entry) (1 << ((((entry)->lo >> 9) & 0x7) + 7))
24
25/* Virtual command interface for enlightened pasid management. */
26#define VCMD_CMD_ALLOC 0x1
27#define VCMD_CMD_FREE 0x2
28#define VCMD_VRSP_IP 0x1
29#define VCMD_VRSP_SC(e) (((e) & 0xff) >> 1)
30#define VCMD_VRSP_SC_SUCCESS 0
31#define VCMD_VRSP_SC_NO_PASID_AVAIL 16
32#define VCMD_VRSP_SC_INVALID_PASID 16
33#define VCMD_VRSP_RESULT_PASID(e) (((e) >> 16) & 0xfffff)
34#define VCMD_CMD_OPERAND(e) ((e) << 16)
35/*
36 * Domain ID reserved for pasid entries programmed for first-level
37 * only and pass-through transfer modes.
38 */
39#define FLPT_DEFAULT_DID 1
40#define NUM_RESERVED_DID 2
41
42#define PASID_FLAG_NESTED BIT(1)
43#define PASID_FLAG_PAGE_SNOOP BIT(2)
44
45/*
46 * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
47 * level translation, otherwise, 4-level paging will be used.
48 */
49#define PASID_FLAG_FL5LP BIT(1)
50
51struct pasid_dir_entry {
52 u64 val;
53};
54
55struct pasid_entry {
56 u64 val[8];
57};
58
59#define PASID_ENTRY_PGTT_FL_ONLY (1)
60#define PASID_ENTRY_PGTT_SL_ONLY (2)
61#define PASID_ENTRY_PGTT_NESTED (3)
62#define PASID_ENTRY_PGTT_PT (4)
63
64/* The representative of a PASID table */
65struct pasid_table {
66 void *table; /* pasid table pointer */
67 int order; /* page order of pasid table */
68 u32 max_pasid; /* max pasid */
69};
70
71/* Get PRESENT bit of a PASID directory entry. */
72static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde)
73{
74 return READ_ONCE(pde->val) & PASID_PTE_PRESENT;
75}
76
77/* Get PASID table from a PASID directory entry. */
78static inline struct pasid_entry *
79get_pasid_table_from_pde(struct pasid_dir_entry *pde)
80{
81 if (!pasid_pde_is_present(pde))
82 return NULL;
83
84 return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK);
85}
86
87/* Get PRESENT bit of a PASID table entry. */
88static inline bool pasid_pte_is_present(struct pasid_entry *pte)
89{
90 return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
91}
92
93/* Get PGTT field of a PASID table entry */
94static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
95{
96 return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
97}
98
99extern unsigned int intel_pasid_max_id;
100int intel_pasid_alloc_table(struct device *dev);
101void intel_pasid_free_table(struct device *dev);
102struct pasid_table *intel_pasid_get_table(struct device *dev);
103int intel_pasid_setup_first_level(struct intel_iommu *iommu,
104 struct device *dev, pgd_t *pgd,
105 u32 pasid, u16 did, int flags);
106int intel_pasid_setup_second_level(struct intel_iommu *iommu,
107 struct dmar_domain *domain,
108 struct device *dev, u32 pasid);
109int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu,
110 struct dmar_domain *domain,
111 struct device *dev, u32 pasid,
112 bool enabled);
113int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
114 struct dmar_domain *domain,
115 struct device *dev, u32 pasid);
116int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
117 u32 pasid, struct dmar_domain *domain);
118void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
119 struct device *dev, u32 pasid,
120 bool fault_ignore);
121int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid);
122void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid);
123void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
124 struct device *dev, u32 pasid);
125#endif /* __INTEL_PASID_H */