xref: /openbmc/linux/drivers/iommu/intel/pasid.h (revision 42987801)
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_MAX			0x100000
1402f3effdSLu Baolu #define PASID_PTE_MASK			0x3F
1502f3effdSLu Baolu #define PASID_PTE_PRESENT		1
1602f3effdSLu Baolu #define PASID_PTE_FPD			2
1702f3effdSLu Baolu #define PDE_PFN_MASK			PAGE_MASK
1802f3effdSLu Baolu #define PASID_PDE_SHIFT			6
1902f3effdSLu Baolu #define MAX_NR_PASID_BITS		20
2002f3effdSLu Baolu #define PASID_TBL_ENTRIES		BIT(PASID_PDE_SHIFT)
2102f3effdSLu Baolu 
2202f3effdSLu Baolu #define is_pasid_enabled(entry)		(((entry)->lo >> 3) & 0x1)
2302f3effdSLu Baolu #define get_pasid_dir_size(entry)	(1 << ((((entry)->lo >> 9) & 0x7) + 7))
2402f3effdSLu Baolu 
2502f3effdSLu Baolu /* Virtual command interface for enlightened pasid management. */
2602f3effdSLu Baolu #define VCMD_CMD_ALLOC			0x1
2702f3effdSLu Baolu #define VCMD_CMD_FREE			0x2
2802f3effdSLu Baolu #define VCMD_VRSP_IP			0x1
294d99efb2SLu Baolu #define VCMD_VRSP_SC(e)			(((e) & 0xff) >> 1)
3002f3effdSLu Baolu #define VCMD_VRSP_SC_SUCCESS		0
314d99efb2SLu Baolu #define VCMD_VRSP_SC_NO_PASID_AVAIL	16
324d99efb2SLu Baolu #define VCMD_VRSP_SC_INVALID_PASID	16
334d99efb2SLu Baolu #define VCMD_VRSP_RESULT_PASID(e)	(((e) >> 16) & 0xfffff)
344d99efb2SLu Baolu #define VCMD_CMD_OPERAND(e)		((e) << 16)
3502f3effdSLu Baolu /*
3602f3effdSLu Baolu  * Domain ID reserved for pasid entries programmed for first-level
3702f3effdSLu Baolu  * only and pass-through transfer modes.
3802f3effdSLu Baolu  */
3902f3effdSLu Baolu #define FLPT_DEFAULT_DID		1
40*98f7b0dbSLu Baolu #define NUM_RESERVED_DID		2
4102f3effdSLu Baolu 
4202f3effdSLu Baolu #define PASID_FLAG_NESTED		BIT(1)
436c00612dSLu Baolu #define PASID_FLAG_PAGE_SNOOP		BIT(2)
4402f3effdSLu Baolu 
4502f3effdSLu Baolu /*
4602f3effdSLu Baolu  * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
4702f3effdSLu Baolu  * level translation, otherwise, 4-level paging will be used.
4802f3effdSLu Baolu  */
4902f3effdSLu Baolu #define PASID_FLAG_FL5LP		BIT(1)
5002f3effdSLu Baolu 
5102f3effdSLu Baolu struct pasid_dir_entry {
5202f3effdSLu Baolu 	u64 val;
5302f3effdSLu Baolu };
5402f3effdSLu Baolu 
5502f3effdSLu Baolu struct pasid_entry {
5602f3effdSLu Baolu 	u64 val[8];
5702f3effdSLu Baolu };
5802f3effdSLu Baolu 
5902f3effdSLu Baolu #define PASID_ENTRY_PGTT_FL_ONLY	(1)
6002f3effdSLu Baolu #define PASID_ENTRY_PGTT_SL_ONLY	(2)
6102f3effdSLu Baolu #define PASID_ENTRY_PGTT_NESTED		(3)
6202f3effdSLu Baolu #define PASID_ENTRY_PGTT_PT		(4)
6302f3effdSLu Baolu 
6402f3effdSLu Baolu /* The representative of a PASID table */
6502f3effdSLu Baolu struct pasid_table {
6602f3effdSLu Baolu 	void			*table;		/* pasid table pointer */
6702f3effdSLu Baolu 	int			order;		/* page order of pasid table */
68c7b6bac9SFenghua Yu 	u32			max_pasid;	/* max pasid */
6902f3effdSLu Baolu };
7002f3effdSLu Baolu 
7102f3effdSLu Baolu /* Get PRESENT bit of a PASID directory entry. */
pasid_pde_is_present(struct pasid_dir_entry * pde)7202f3effdSLu Baolu static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde)
7302f3effdSLu Baolu {
7402f3effdSLu Baolu 	return READ_ONCE(pde->val) & PASID_PTE_PRESENT;
7502f3effdSLu Baolu }
7602f3effdSLu Baolu 
7702f3effdSLu Baolu /* Get PASID table from a PASID directory entry. */
7802f3effdSLu Baolu static inline struct pasid_entry *
get_pasid_table_from_pde(struct pasid_dir_entry * pde)7902f3effdSLu Baolu get_pasid_table_from_pde(struct pasid_dir_entry *pde)
8002f3effdSLu Baolu {
8102f3effdSLu Baolu 	if (!pasid_pde_is_present(pde))
8202f3effdSLu Baolu 		return NULL;
8302f3effdSLu Baolu 
8402f3effdSLu Baolu 	return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK);
8502f3effdSLu Baolu }
8602f3effdSLu Baolu 
8702f3effdSLu Baolu /* Get PRESENT bit of a PASID table entry. */
pasid_pte_is_present(struct pasid_entry * pte)8802f3effdSLu Baolu static inline bool pasid_pte_is_present(struct pasid_entry *pte)
8902f3effdSLu Baolu {
9002f3effdSLu Baolu 	return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
9102f3effdSLu Baolu }
9202f3effdSLu Baolu 
938798d364SLiu Yi L /* Get PGTT field of a PASID table entry */
pasid_pte_get_pgtt(struct pasid_entry * pte)948798d364SLiu Yi L static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
958798d364SLiu Yi L {
968798d364SLiu Yi L 	return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
978798d364SLiu Yi L }
988798d364SLiu Yi L 
99c7b6bac9SFenghua Yu extern unsigned int intel_pasid_max_id;
10002f3effdSLu Baolu int intel_pasid_alloc_table(struct device *dev);
10102f3effdSLu Baolu void intel_pasid_free_table(struct device *dev);
10202f3effdSLu Baolu struct pasid_table *intel_pasid_get_table(struct device *dev);
10302f3effdSLu Baolu int intel_pasid_setup_first_level(struct intel_iommu *iommu,
10402f3effdSLu Baolu 				  struct device *dev, pgd_t *pgd,
105c7b6bac9SFenghua Yu 				  u32 pasid, u16 did, int flags);
10602f3effdSLu Baolu int intel_pasid_setup_second_level(struct intel_iommu *iommu,
10702f3effdSLu Baolu 				   struct dmar_domain *domain,
108c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
10902f3effdSLu Baolu int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
11002f3effdSLu Baolu 				   struct dmar_domain *domain,
111c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
11202f3effdSLu Baolu void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
113c7b6bac9SFenghua Yu 				 struct device *dev, u32 pasid,
11402f3effdSLu Baolu 				 bool fault_ignore);
115c7b6bac9SFenghua Yu int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid);
116c7b6bac9SFenghua Yu void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid);
117fc0051cbSLu Baolu void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
118fc0051cbSLu Baolu 					  struct device *dev, u32 pasid);
11902f3effdSLu Baolu #endif /* __INTEL_PASID_H */
120