xref: /linux/drivers/iommu/intel/pasid.h (revision 6c00612d0cba10f7d0917cf1f73c945003ed4cd7)
102f3effdSLu Baolu /* SPDX-License-Identifier: GPL-2.0 */
202f3effdSLu Baolu /*
302f3effdSLu Baolu  * pasid.h - PASID idr, table and entry header
402f3effdSLu Baolu  *
502f3effdSLu Baolu  * Copyright (C) 2018 Intel Corporation
602f3effdSLu Baolu  *
702f3effdSLu Baolu  * Author: Lu Baolu <baolu.lu@linux.intel.com>
802f3effdSLu Baolu  */
902f3effdSLu Baolu 
1002f3effdSLu Baolu #ifndef __INTEL_PASID_H
1102f3effdSLu Baolu #define __INTEL_PASID_H
1202f3effdSLu Baolu 
1302f3effdSLu Baolu #define PASID_RID2PASID			0x0
1402f3effdSLu Baolu #define PASID_MIN			0x1
1502f3effdSLu Baolu #define PASID_MAX			0x100000
1602f3effdSLu Baolu #define PASID_PTE_MASK			0x3F
1702f3effdSLu Baolu #define PASID_PTE_PRESENT		1
1802f3effdSLu Baolu #define PASID_PTE_FPD			2
1902f3effdSLu Baolu #define PDE_PFN_MASK			PAGE_MASK
2002f3effdSLu Baolu #define PASID_PDE_SHIFT			6
2102f3effdSLu Baolu #define MAX_NR_PASID_BITS		20
2202f3effdSLu Baolu #define PASID_TBL_ENTRIES		BIT(PASID_PDE_SHIFT)
2302f3effdSLu Baolu 
2402f3effdSLu Baolu #define is_pasid_enabled(entry)		(((entry)->lo >> 3) & 0x1)
2502f3effdSLu Baolu #define get_pasid_dir_size(entry)	(1 << ((((entry)->lo >> 9) & 0x7) + 7))
2602f3effdSLu Baolu 
2702f3effdSLu Baolu /* Virtual command interface for enlightened pasid management. */
2802f3effdSLu Baolu #define VCMD_CMD_ALLOC			0x1
2902f3effdSLu Baolu #define VCMD_CMD_FREE			0x2
3002f3effdSLu Baolu #define VCMD_VRSP_IP			0x1
3102f3effdSLu Baolu #define VCMD_VRSP_SC(e)			(((e) >> 1) & 0x3)
3202f3effdSLu Baolu #define VCMD_VRSP_SC_SUCCESS		0
33444d66a2SZenghui Yu #define VCMD_VRSP_SC_NO_PASID_AVAIL	2
34444d66a2SZenghui Yu #define VCMD_VRSP_SC_INVALID_PASID	2
3502f3effdSLu Baolu #define VCMD_VRSP_RESULT_PASID(e)	(((e) >> 8) & 0xfffff)
3602f3effdSLu Baolu #define VCMD_CMD_OPERAND(e)		((e) << 8)
3702f3effdSLu Baolu /*
3802f3effdSLu Baolu  * Domain ID reserved for pasid entries programmed for first-level
3902f3effdSLu Baolu  * only and pass-through transfer modes.
4002f3effdSLu Baolu  */
4102f3effdSLu Baolu #define FLPT_DEFAULT_DID		1
4202f3effdSLu Baolu 
4302f3effdSLu Baolu /*
4402f3effdSLu Baolu  * The SUPERVISOR_MODE flag indicates a first level translation which
4502f3effdSLu Baolu  * can be used for access to kernel addresses. It is valid only for
4602f3effdSLu Baolu  * access to the kernel's static 1:1 mapping of physical memory — not
4702f3effdSLu Baolu  * to vmalloc or even module mappings.
4802f3effdSLu Baolu  */
4902f3effdSLu Baolu #define PASID_FLAG_SUPERVISOR_MODE	BIT(0)
5002f3effdSLu Baolu #define PASID_FLAG_NESTED		BIT(1)
51*6c00612dSLu Baolu #define PASID_FLAG_PAGE_SNOOP		BIT(2)
5202f3effdSLu Baolu 
5302f3effdSLu Baolu /*
5402f3effdSLu Baolu  * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
5502f3effdSLu Baolu  * level translation, otherwise, 4-level paging will be used.
5602f3effdSLu Baolu  */
5702f3effdSLu Baolu #define PASID_FLAG_FL5LP		BIT(1)
5802f3effdSLu Baolu 
5902f3effdSLu Baolu struct pasid_dir_entry {
6002f3effdSLu Baolu 	u64 val;
6102f3effdSLu Baolu };
6202f3effdSLu Baolu 
6302f3effdSLu Baolu struct pasid_entry {
6402f3effdSLu Baolu 	u64 val[8];
6502f3effdSLu Baolu };
6602f3effdSLu Baolu 
6702f3effdSLu Baolu #define PASID_ENTRY_PGTT_FL_ONLY	(1)
6802f3effdSLu Baolu #define PASID_ENTRY_PGTT_SL_ONLY	(2)
6902f3effdSLu Baolu #define PASID_ENTRY_PGTT_NESTED		(3)
7002f3effdSLu Baolu #define PASID_ENTRY_PGTT_PT		(4)
7102f3effdSLu Baolu 
7202f3effdSLu Baolu /* The representative of a PASID table */
7302f3effdSLu Baolu struct pasid_table {
7402f3effdSLu Baolu 	void			*table;		/* pasid table pointer */
7502f3effdSLu Baolu 	int			order;		/* page order of pasid table */
76c7b6bac9SFenghua Yu 	u32			max_pasid;	/* max pasid */
7702f3effdSLu Baolu 	struct list_head	dev;		/* device list */
7802f3effdSLu Baolu };
7902f3effdSLu Baolu 
8002f3effdSLu Baolu /* Get PRESENT bit of a PASID directory entry. */
8102f3effdSLu Baolu static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde)
8202f3effdSLu Baolu {
8302f3effdSLu Baolu 	return READ_ONCE(pde->val) & PASID_PTE_PRESENT;
8402f3effdSLu Baolu }
8502f3effdSLu Baolu 
8602f3effdSLu Baolu /* Get PASID table from a PASID directory entry. */
8702f3effdSLu Baolu static inline struct pasid_entry *
8802f3effdSLu Baolu get_pasid_table_from_pde(struct pasid_dir_entry *pde)
8902f3effdSLu Baolu {
9002f3effdSLu Baolu 	if (!pasid_pde_is_present(pde))
9102f3effdSLu Baolu 		return NULL;
9202f3effdSLu Baolu 
9302f3effdSLu Baolu 	return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK);
9402f3effdSLu Baolu }
9502f3effdSLu Baolu 
9602f3effdSLu Baolu /* Get PRESENT bit of a PASID table entry. */
9702f3effdSLu Baolu static inline bool pasid_pte_is_present(struct pasid_entry *pte)
9802f3effdSLu Baolu {
9902f3effdSLu Baolu 	return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
10002f3effdSLu Baolu }
10102f3effdSLu Baolu 
102c7b6bac9SFenghua Yu extern unsigned int intel_pasid_max_id;
10302f3effdSLu Baolu int intel_pasid_alloc_table(struct device *dev);
10402f3effdSLu Baolu void intel_pasid_free_table(struct device *dev);
10502f3effdSLu Baolu struct pasid_table *intel_pasid_get_table(struct device *dev);
10602f3effdSLu Baolu int intel_pasid_setup_first_level(struct intel_iommu *iommu,
10702f3effdSLu Baolu 				  struct device *dev, pgd_t *pgd,
108c7b6bac9SFenghua Yu 				  u32 pasid, u16 did, int flags);
10902f3effdSLu Baolu int intel_pasid_setup_second_level(struct intel_iommu *iommu,
11002f3effdSLu Baolu 				   struct dmar_domain *domain,
111c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
11202f3effdSLu Baolu int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
11302f3effdSLu Baolu 				   struct dmar_domain *domain,
114c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
11502f3effdSLu Baolu int intel_pasid_setup_nested(struct intel_iommu *iommu,
116c7b6bac9SFenghua Yu 			     struct device *dev, pgd_t *pgd, u32 pasid,
11702f3effdSLu Baolu 			     struct iommu_gpasid_bind_data_vtd *pasid_data,
11802f3effdSLu Baolu 			     struct dmar_domain *domain, int addr_width);
11902f3effdSLu Baolu void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
120c7b6bac9SFenghua Yu 				 struct device *dev, u32 pasid,
12102f3effdSLu Baolu 				 bool fault_ignore);
122c7b6bac9SFenghua Yu int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid);
123c7b6bac9SFenghua Yu void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid);
12402f3effdSLu Baolu #endif /* __INTEL_PASID_H */
125