xref: /linux/drivers/iommu/intel/pasid.h (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 /*
2602f3effdSLu Baolu  * Domain ID reserved for pasid entries programmed for first-level
2702f3effdSLu Baolu  * only and pass-through transfer modes.
2802f3effdSLu Baolu  */
2902f3effdSLu Baolu #define FLPT_DEFAULT_DID		1
3098f7b0dbSLu Baolu #define NUM_RESERVED_DID		2
3102f3effdSLu Baolu 
3202f3effdSLu Baolu #define PASID_FLAG_NESTED		BIT(1)
336c00612dSLu Baolu #define PASID_FLAG_PAGE_SNOOP		BIT(2)
3402f3effdSLu Baolu 
3502f3effdSLu Baolu /*
3602f3effdSLu Baolu  * The PASID_FLAG_FL5LP flag Indicates using 5-level paging for first-
3702f3effdSLu Baolu  * level translation, otherwise, 4-level paging will be used.
3802f3effdSLu Baolu  */
3902f3effdSLu Baolu #define PASID_FLAG_FL5LP		BIT(1)
4002f3effdSLu Baolu 
4102f3effdSLu Baolu struct pasid_dir_entry {
4202f3effdSLu Baolu 	u64 val;
4302f3effdSLu Baolu };
4402f3effdSLu Baolu 
4502f3effdSLu Baolu struct pasid_entry {
4602f3effdSLu Baolu 	u64 val[8];
4702f3effdSLu Baolu };
4802f3effdSLu Baolu 
4902f3effdSLu Baolu #define PASID_ENTRY_PGTT_FL_ONLY	(1)
5002f3effdSLu Baolu #define PASID_ENTRY_PGTT_SL_ONLY	(2)
5102f3effdSLu Baolu #define PASID_ENTRY_PGTT_NESTED		(3)
5202f3effdSLu Baolu #define PASID_ENTRY_PGTT_PT		(4)
5302f3effdSLu Baolu 
5402f3effdSLu Baolu /* The representative of a PASID table */
5502f3effdSLu Baolu struct pasid_table {
5602f3effdSLu Baolu 	void			*table;		/* pasid table pointer */
5702f3effdSLu Baolu 	int			order;		/* page order of pasid table */
58c7b6bac9SFenghua Yu 	u32			max_pasid;	/* max pasid */
5902f3effdSLu Baolu };
6002f3effdSLu Baolu 
6102f3effdSLu Baolu /* Get PRESENT bit of a PASID directory entry. */
pasid_pde_is_present(struct pasid_dir_entry * pde)6202f3effdSLu Baolu static inline bool pasid_pde_is_present(struct pasid_dir_entry *pde)
6302f3effdSLu Baolu {
6402f3effdSLu Baolu 	return READ_ONCE(pde->val) & PASID_PTE_PRESENT;
6502f3effdSLu Baolu }
6602f3effdSLu Baolu 
6702f3effdSLu Baolu /* Get PASID table from a PASID directory entry. */
6802f3effdSLu Baolu static inline struct pasid_entry *
get_pasid_table_from_pde(struct pasid_dir_entry * pde)6902f3effdSLu Baolu get_pasid_table_from_pde(struct pasid_dir_entry *pde)
7002f3effdSLu Baolu {
7102f3effdSLu Baolu 	if (!pasid_pde_is_present(pde))
7202f3effdSLu Baolu 		return NULL;
7302f3effdSLu Baolu 
7402f3effdSLu Baolu 	return phys_to_virt(READ_ONCE(pde->val) & PDE_PFN_MASK);
7502f3effdSLu Baolu }
7602f3effdSLu Baolu 
7702f3effdSLu Baolu /* Get PRESENT bit of a PASID table entry. */
pasid_pte_is_present(struct pasid_entry * pte)7802f3effdSLu Baolu static inline bool pasid_pte_is_present(struct pasid_entry *pte)
7902f3effdSLu Baolu {
8002f3effdSLu Baolu 	return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
8102f3effdSLu Baolu }
8202f3effdSLu Baolu 
838798d364SLiu Yi L /* Get PGTT field of a PASID table entry */
pasid_pte_get_pgtt(struct pasid_entry * pte)848798d364SLiu Yi L static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
858798d364SLiu Yi L {
868798d364SLiu Yi L 	return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
878798d364SLiu Yi L }
888798d364SLiu Yi L 
pasid_clear_entry(struct pasid_entry * pe)8980b79e14SLu Baolu static inline void pasid_clear_entry(struct pasid_entry *pe)
9080b79e14SLu Baolu {
9180b79e14SLu Baolu 	WRITE_ONCE(pe->val[0], 0);
9280b79e14SLu Baolu 	WRITE_ONCE(pe->val[1], 0);
9380b79e14SLu Baolu 	WRITE_ONCE(pe->val[2], 0);
9480b79e14SLu Baolu 	WRITE_ONCE(pe->val[3], 0);
9580b79e14SLu Baolu 	WRITE_ONCE(pe->val[4], 0);
9680b79e14SLu Baolu 	WRITE_ONCE(pe->val[5], 0);
9780b79e14SLu Baolu 	WRITE_ONCE(pe->val[6], 0);
9880b79e14SLu Baolu 	WRITE_ONCE(pe->val[7], 0);
9980b79e14SLu Baolu }
10080b79e14SLu Baolu 
pasid_clear_entry_with_fpd(struct pasid_entry * pe)10180b79e14SLu Baolu static inline void pasid_clear_entry_with_fpd(struct pasid_entry *pe)
10280b79e14SLu Baolu {
10380b79e14SLu Baolu 	WRITE_ONCE(pe->val[0], PASID_PTE_FPD);
10480b79e14SLu Baolu 	WRITE_ONCE(pe->val[1], 0);
10580b79e14SLu Baolu 	WRITE_ONCE(pe->val[2], 0);
10680b79e14SLu Baolu 	WRITE_ONCE(pe->val[3], 0);
10780b79e14SLu Baolu 	WRITE_ONCE(pe->val[4], 0);
10880b79e14SLu Baolu 	WRITE_ONCE(pe->val[5], 0);
10980b79e14SLu Baolu 	WRITE_ONCE(pe->val[6], 0);
11080b79e14SLu Baolu 	WRITE_ONCE(pe->val[7], 0);
11180b79e14SLu Baolu }
11280b79e14SLu Baolu 
pasid_set_bits(u64 * ptr,u64 mask,u64 bits)11380b79e14SLu Baolu static inline void pasid_set_bits(u64 *ptr, u64 mask, u64 bits)
11480b79e14SLu Baolu {
11580b79e14SLu Baolu 	u64 old;
11680b79e14SLu Baolu 
11780b79e14SLu Baolu 	old = READ_ONCE(*ptr);
11880b79e14SLu Baolu 	WRITE_ONCE(*ptr, (old & ~mask) | bits);
11980b79e14SLu Baolu }
12080b79e14SLu Baolu 
pasid_get_bits(u64 * ptr)12180b79e14SLu Baolu static inline u64 pasid_get_bits(u64 *ptr)
12280b79e14SLu Baolu {
12380b79e14SLu Baolu 	return READ_ONCE(*ptr);
12480b79e14SLu Baolu }
12580b79e14SLu Baolu 
12680b79e14SLu Baolu /*
12780b79e14SLu Baolu  * Setup the DID(Domain Identifier) field (Bit 64~79) of scalable mode
12880b79e14SLu Baolu  * PASID entry.
12980b79e14SLu Baolu  */
13080b79e14SLu Baolu static inline void
pasid_set_domain_id(struct pasid_entry * pe,u64 value)13180b79e14SLu Baolu pasid_set_domain_id(struct pasid_entry *pe, u64 value)
13280b79e14SLu Baolu {
13380b79e14SLu Baolu 	pasid_set_bits(&pe->val[1], GENMASK_ULL(15, 0), value);
13480b79e14SLu Baolu }
13580b79e14SLu Baolu 
13680b79e14SLu Baolu /*
13780b79e14SLu Baolu  * Get domain ID value of a scalable mode PASID entry.
13880b79e14SLu Baolu  */
13980b79e14SLu Baolu static inline u16
pasid_get_domain_id(struct pasid_entry * pe)14080b79e14SLu Baolu pasid_get_domain_id(struct pasid_entry *pe)
14180b79e14SLu Baolu {
14280b79e14SLu Baolu 	return (u16)(READ_ONCE(pe->val[1]) & GENMASK_ULL(15, 0));
14380b79e14SLu Baolu }
14480b79e14SLu Baolu 
14580b79e14SLu Baolu /*
14680b79e14SLu Baolu  * Setup the SLPTPTR(Second Level Page Table Pointer) field (Bit 12~63)
14780b79e14SLu Baolu  * of a scalable mode PASID entry.
14880b79e14SLu Baolu  */
14980b79e14SLu Baolu static inline void
pasid_set_slptr(struct pasid_entry * pe,u64 value)15080b79e14SLu Baolu pasid_set_slptr(struct pasid_entry *pe, u64 value)
15180b79e14SLu Baolu {
15280b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], VTD_PAGE_MASK, value);
15380b79e14SLu Baolu }
15480b79e14SLu Baolu 
15580b79e14SLu Baolu /*
15680b79e14SLu Baolu  * Setup the AW(Address Width) field (Bit 2~4) of a scalable mode PASID
15780b79e14SLu Baolu  * entry.
15880b79e14SLu Baolu  */
15980b79e14SLu Baolu static inline void
pasid_set_address_width(struct pasid_entry * pe,u64 value)16080b79e14SLu Baolu pasid_set_address_width(struct pasid_entry *pe, u64 value)
16180b79e14SLu Baolu {
16280b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], GENMASK_ULL(4, 2), value << 2);
16380b79e14SLu Baolu }
16480b79e14SLu Baolu 
16580b79e14SLu Baolu /*
16680b79e14SLu Baolu  * Setup the PGTT(PASID Granular Translation Type) field (Bit 6~8)
16780b79e14SLu Baolu  * of a scalable mode PASID entry.
16880b79e14SLu Baolu  */
16980b79e14SLu Baolu static inline void
pasid_set_translation_type(struct pasid_entry * pe,u64 value)17080b79e14SLu Baolu pasid_set_translation_type(struct pasid_entry *pe, u64 value)
17180b79e14SLu Baolu {
17280b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], GENMASK_ULL(8, 6), value << 6);
17380b79e14SLu Baolu }
17480b79e14SLu Baolu 
17580b79e14SLu Baolu /*
17680b79e14SLu Baolu  * Enable fault processing by clearing the FPD(Fault Processing
17780b79e14SLu Baolu  * Disable) field (Bit 1) of a scalable mode PASID entry.
17880b79e14SLu Baolu  */
pasid_set_fault_enable(struct pasid_entry * pe)17980b79e14SLu Baolu static inline void pasid_set_fault_enable(struct pasid_entry *pe)
18080b79e14SLu Baolu {
18180b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], 1 << 1, 0);
18280b79e14SLu Baolu }
18380b79e14SLu Baolu 
18480b79e14SLu Baolu /*
18580b79e14SLu Baolu  * Enable second level A/D bits by setting the SLADE (Second Level
18680b79e14SLu Baolu  * Access Dirty Enable) field (Bit 9) of a scalable mode PASID
18780b79e14SLu Baolu  * entry.
18880b79e14SLu Baolu  */
pasid_set_ssade(struct pasid_entry * pe)18980b79e14SLu Baolu static inline void pasid_set_ssade(struct pasid_entry *pe)
19080b79e14SLu Baolu {
19180b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], 1 << 9, 1 << 9);
19280b79e14SLu Baolu }
19380b79e14SLu Baolu 
19480b79e14SLu Baolu /*
19580b79e14SLu Baolu  * Disable second level A/D bits by clearing the SLADE (Second Level
19680b79e14SLu Baolu  * Access Dirty Enable) field (Bit 9) of a scalable mode PASID
19780b79e14SLu Baolu  * entry.
19880b79e14SLu Baolu  */
pasid_clear_ssade(struct pasid_entry * pe)19980b79e14SLu Baolu static inline void pasid_clear_ssade(struct pasid_entry *pe)
20080b79e14SLu Baolu {
20180b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], 1 << 9, 0);
20280b79e14SLu Baolu }
20380b79e14SLu Baolu 
20480b79e14SLu Baolu /*
20580b79e14SLu Baolu  * Checks if second level A/D bits specifically the SLADE (Second Level
20680b79e14SLu Baolu  * Access Dirty Enable) field (Bit 9) of a scalable mode PASID
20780b79e14SLu Baolu  * entry is set.
20880b79e14SLu Baolu  */
pasid_get_ssade(struct pasid_entry * pe)20980b79e14SLu Baolu static inline bool pasid_get_ssade(struct pasid_entry *pe)
21080b79e14SLu Baolu {
21180b79e14SLu Baolu 	return pasid_get_bits(&pe->val[0]) & (1 << 9);
21280b79e14SLu Baolu }
21380b79e14SLu Baolu 
21480b79e14SLu Baolu /*
21580b79e14SLu Baolu  * Setup the SRE(Supervisor Request Enable) field (Bit 128) of a
21680b79e14SLu Baolu  * scalable mode PASID entry.
21780b79e14SLu Baolu  */
pasid_set_sre(struct pasid_entry * pe)21880b79e14SLu Baolu static inline void pasid_set_sre(struct pasid_entry *pe)
21980b79e14SLu Baolu {
22080b79e14SLu Baolu 	pasid_set_bits(&pe->val[2], 1 << 0, 1);
22180b79e14SLu Baolu }
22280b79e14SLu Baolu 
22380b79e14SLu Baolu /*
22480b79e14SLu Baolu  * Setup the WPE(Write Protect Enable) field (Bit 132) of a
22580b79e14SLu Baolu  * scalable mode PASID entry.
22680b79e14SLu Baolu  */
pasid_set_wpe(struct pasid_entry * pe)22780b79e14SLu Baolu static inline void pasid_set_wpe(struct pasid_entry *pe)
22880b79e14SLu Baolu {
22980b79e14SLu Baolu 	pasid_set_bits(&pe->val[2], 1 << 4, 1 << 4);
23080b79e14SLu Baolu }
23180b79e14SLu Baolu 
23280b79e14SLu Baolu /*
23380b79e14SLu Baolu  * Setup the P(Present) field (Bit 0) of a scalable mode PASID
23480b79e14SLu Baolu  * entry.
23580b79e14SLu Baolu  */
pasid_set_present(struct pasid_entry * pe)23680b79e14SLu Baolu static inline void pasid_set_present(struct pasid_entry *pe)
23780b79e14SLu Baolu {
23880b79e14SLu Baolu 	pasid_set_bits(&pe->val[0], 1 << 0, 1);
23980b79e14SLu Baolu }
24080b79e14SLu Baolu 
24180b79e14SLu Baolu /*
24280b79e14SLu Baolu  * Setup Page Walk Snoop bit (Bit 87) of a scalable mode PASID
24380b79e14SLu Baolu  * entry.
24480b79e14SLu Baolu  */
pasid_set_page_snoop(struct pasid_entry * pe,bool value)24580b79e14SLu Baolu static inline void pasid_set_page_snoop(struct pasid_entry *pe, bool value)
24680b79e14SLu Baolu {
24780b79e14SLu Baolu 	pasid_set_bits(&pe->val[1], 1 << 23, value << 23);
24880b79e14SLu Baolu }
24980b79e14SLu Baolu 
25080b79e14SLu Baolu /*
25180b79e14SLu Baolu  * Setup the Page Snoop (PGSNP) field (Bit 88) of a scalable mode
25280b79e14SLu Baolu  * PASID entry.
25380b79e14SLu Baolu  */
25480b79e14SLu Baolu static inline void
pasid_set_pgsnp(struct pasid_entry * pe)25580b79e14SLu Baolu pasid_set_pgsnp(struct pasid_entry *pe)
25680b79e14SLu Baolu {
25780b79e14SLu Baolu 	pasid_set_bits(&pe->val[1], 1ULL << 24, 1ULL << 24);
25880b79e14SLu Baolu }
25980b79e14SLu Baolu 
26080b79e14SLu Baolu /*
26180b79e14SLu Baolu  * Setup the First Level Page table Pointer field (Bit 140~191)
26280b79e14SLu Baolu  * of a scalable mode PASID entry.
26380b79e14SLu Baolu  */
26480b79e14SLu Baolu static inline void
pasid_set_flptr(struct pasid_entry * pe,u64 value)26580b79e14SLu Baolu pasid_set_flptr(struct pasid_entry *pe, u64 value)
26680b79e14SLu Baolu {
26780b79e14SLu Baolu 	pasid_set_bits(&pe->val[2], VTD_PAGE_MASK, value);
26880b79e14SLu Baolu }
26980b79e14SLu Baolu 
27080b79e14SLu Baolu /*
27180b79e14SLu Baolu  * Setup the First Level Paging Mode field (Bit 130~131) of a
27280b79e14SLu Baolu  * scalable mode PASID entry.
27380b79e14SLu Baolu  */
27480b79e14SLu Baolu static inline void
pasid_set_flpm(struct pasid_entry * pe,u64 value)27580b79e14SLu Baolu pasid_set_flpm(struct pasid_entry *pe, u64 value)
27680b79e14SLu Baolu {
27780b79e14SLu Baolu 	pasid_set_bits(&pe->val[2], GENMASK_ULL(3, 2), value << 2);
27880b79e14SLu Baolu }
27980b79e14SLu Baolu 
28080b79e14SLu Baolu /*
28180b79e14SLu Baolu  * Setup the Extended Access Flag Enable (EAFE) field (Bit 135)
28280b79e14SLu Baolu  * of a scalable mode PASID entry.
28380b79e14SLu Baolu  */
pasid_set_eafe(struct pasid_entry * pe)28480b79e14SLu Baolu static inline void pasid_set_eafe(struct pasid_entry *pe)
28580b79e14SLu Baolu {
28680b79e14SLu Baolu 	pasid_set_bits(&pe->val[2], 1 << 7, 1 << 7);
28780b79e14SLu Baolu }
28880b79e14SLu Baolu 
289c7b6bac9SFenghua Yu extern unsigned int intel_pasid_max_id;
29002f3effdSLu Baolu int intel_pasid_alloc_table(struct device *dev);
29102f3effdSLu Baolu void intel_pasid_free_table(struct device *dev);
29202f3effdSLu Baolu struct pasid_table *intel_pasid_get_table(struct device *dev);
29302f3effdSLu Baolu int intel_pasid_setup_first_level(struct intel_iommu *iommu,
29402f3effdSLu Baolu 				  struct device *dev, pgd_t *pgd,
295c7b6bac9SFenghua Yu 				  u32 pasid, u16 did, int flags);
29602f3effdSLu Baolu int intel_pasid_setup_second_level(struct intel_iommu *iommu,
29702f3effdSLu Baolu 				   struct dmar_domain *domain,
298c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
299f35f22ccSJoao Martins int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu,
300f35f22ccSJoao Martins 				     struct device *dev, u32 pasid,
301f35f22ccSJoao Martins 				     bool enabled);
30202f3effdSLu Baolu int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
303c7b6bac9SFenghua Yu 				   struct device *dev, u32 pasid);
304111bf85cSLu Baolu int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
305111bf85cSLu Baolu 			     u32 pasid, struct dmar_domain *domain);
30602f3effdSLu Baolu void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
307c7b6bac9SFenghua Yu 				 struct device *dev, u32 pasid,
30802f3effdSLu Baolu 				 bool fault_ignore);
309fc0051cbSLu Baolu void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
310fc0051cbSLu Baolu 					  struct device *dev, u32 pasid);
311*301f1a80SLu Baolu int intel_pasid_setup_sm_context(struct device *dev);
31281e921fdSLu Baolu void intel_pasid_teardown_sm_context(struct device *dev);
31302f3effdSLu Baolu #endif /* __INTEL_PASID_H */
314