xref: /linux-6.15/include/linux/dmar.h (revision 95e2eaf5)
13b20eb23SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
210e5247fSKeshavamurthy, Anil S /*
310e5247fSKeshavamurthy, Anil S  * Copyright (c) 2006, Intel Corporation.
410e5247fSKeshavamurthy, Anil S  *
510e5247fSKeshavamurthy, Anil S  * Copyright (C) Ashok Raj <[email protected]>
610e5247fSKeshavamurthy, Anil S  * Copyright (C) Shaohua Li <[email protected]>
710e5247fSKeshavamurthy, Anil S  */
810e5247fSKeshavamurthy, Anil S 
910e5247fSKeshavamurthy, Anil S #ifndef __DMAR_H__
1010e5247fSKeshavamurthy, Anil S #define __DMAR_H__
1110e5247fSKeshavamurthy, Anil S 
1210e5247fSKeshavamurthy, Anil S #include <linux/acpi.h>
1310e5247fSKeshavamurthy, Anil S #include <linux/types.h>
14ba395927SKeshavamurthy, Anil S #include <linux/msi.h>
151531a6a6SSuresh Siddha #include <linux/irqreturn.h>
163a5670e8SJiang Liu #include <linux/rwsem.h>
17b2d09103SIngo Molnar #include <linux/rculist.h>
1810e5247fSKeshavamurthy, Anil S 
196eea69ddSAndrew Morton struct acpi_dmar_header;
206eea69ddSAndrew Morton 
2125357900SLu Baolu #define DMAR_UNITS_SUPPORTED	1024
2278d8e704SJiang Liu 
2341750d31SSuresh Siddha /* DMAR Flags */
2441750d31SSuresh Siddha #define DMAR_INTR_REMAP		0x1
2541750d31SSuresh Siddha #define DMAR_X2APIC_OPT_OUT	0x2
2689a6079dSLu Baolu #define DMAR_PLATFORM_OPT_IN	0x4
2741750d31SSuresh Siddha 
28ba395927SKeshavamurthy, Anil S struct intel_iommu;
29694835dcSJiang Liu 
30832bd858SDavid Woodhouse struct dmar_dev_scope {
31832bd858SDavid Woodhouse 	struct device __rcu *dev;
32832bd858SDavid Woodhouse 	u8 bus;
33832bd858SDavid Woodhouse 	u8 devfn;
34832bd858SDavid Woodhouse };
35832bd858SDavid Woodhouse 
36d3f13810SSuresh Siddha #ifdef CONFIG_DMAR_TABLE
3741750d31SSuresh Siddha extern struct acpi_table_header *dmar_tbl;
3810e5247fSKeshavamurthy, Anil S struct dmar_drhd_unit {
3910e5247fSKeshavamurthy, Anil S 	struct list_head list;		/* list of drhd units	*/
401886e8a9SSuresh Siddha 	struct  acpi_dmar_header *hdr;	/* ACPI header		*/
4110e5247fSKeshavamurthy, Anil S 	u64	reg_base_addr;		/* register base address*/
424db96bfeSKan Liang 	unsigned long reg_size;		/* size of register set */
43832bd858SDavid Woodhouse 	struct	dmar_dev_scope *devices;/* target device array	*/
4410e5247fSKeshavamurthy, Anil S 	int	devices_cnt;		/* target device count	*/
45276dbf99SDavid Woodhouse 	u16	segment;		/* PCI domain		*/
4610e5247fSKeshavamurthy, Anil S 	u8	ignored:1; 		/* ignore drhd		*/
4710e5247fSKeshavamurthy, Anil S 	u8	include_all:1;
48b1012ca8SLu Baolu 	u8	gfx_dedicated:1;	/* graphic dedicated	*/
4910e5247fSKeshavamurthy, Anil S 	struct intel_iommu *iommu;
5010e5247fSKeshavamurthy, Anil S };
5110e5247fSKeshavamurthy, Anil S 
5257384592SJoerg Roedel struct dmar_pci_path {
5357384592SJoerg Roedel 	u8 bus;
5457384592SJoerg Roedel 	u8 device;
5557384592SJoerg Roedel 	u8 function;
5657384592SJoerg Roedel };
5757384592SJoerg Roedel 
5859ce0515SJiang Liu struct dmar_pci_notify_info {
5959ce0515SJiang Liu 	struct pci_dev			*dev;
6059ce0515SJiang Liu 	unsigned long			event;
6159ce0515SJiang Liu 	int				bus;
6259ce0515SJiang Liu 	u16				seg;
6359ce0515SJiang Liu 	u16				level;
6457384592SJoerg Roedel 	struct dmar_pci_path		path[];
6559ce0515SJiang Liu }  __attribute__((packed));
6659ce0515SJiang Liu 
673a5670e8SJiang Liu extern struct rw_semaphore dmar_global_lock;
682ae21010SSuresh Siddha extern struct list_head dmar_drhd_units;
692ae21010SSuresh Siddha 
702ae21010SSuresh Siddha #define for_each_drhd_unit(drhd)					\
7102d715b4SAmol Grover 	list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,		\
7202d715b4SAmol Grover 				dmar_rcu_check())
732ae21010SSuresh Siddha 
747c919779SJiang Liu #define for_each_active_drhd_unit(drhd)					\
75f5152416SQian Cai 	list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,		\
76f5152416SQian Cai 				dmar_rcu_check())			\
777c919779SJiang Liu 		if (drhd->ignored) {} else
787c919779SJiang Liu 
798f912ba4SDavid Woodhouse #define for_each_active_iommu(i, drhd)					\
80f5152416SQian Cai 	list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,		\
81f5152416SQian Cai 				dmar_rcu_check())			\
828f912ba4SDavid Woodhouse 		if (i=drhd->iommu, drhd->ignored) {} else
838f912ba4SDavid Woodhouse 
848f912ba4SDavid Woodhouse #define for_each_iommu(i, drhd)						\
8502d715b4SAmol Grover 	list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,		\
8602d715b4SAmol Grover 				dmar_rcu_check())			\
878f912ba4SDavid Woodhouse 		if (i=drhd->iommu, 0) {} else
888f912ba4SDavid Woodhouse 
dmar_rcu_check(void)890e242612SJiang Liu static inline bool dmar_rcu_check(void)
900e242612SJiang Liu {
910e242612SJiang Liu 	return rwsem_is_locked(&dmar_global_lock) ||
927ebb5f8eSLu Baolu 	       system_state == SYSTEM_BOOTING;
930e242612SJiang Liu }
940e242612SJiang Liu 
950e242612SJiang Liu #define	dmar_rcu_dereference(p)	rcu_dereference_check((p), dmar_rcu_check())
960e242612SJiang Liu 
97a760f8a6SQian Cai #define for_each_dev_scope(devs, cnt, i, tmp)				\
98a760f8a6SQian Cai 	for ((i) = 0; ((tmp) = (i) < (cnt) ?				\
99a760f8a6SQian Cai 	    dmar_rcu_dereference((devs)[(i)].dev) : NULL, (i) < (cnt)); \
100a760f8a6SQian Cai 	    (i)++)
101b683b230SJiang Liu 
102a760f8a6SQian Cai #define for_each_active_dev_scope(devs, cnt, i, tmp)			\
103a760f8a6SQian Cai 	for_each_dev_scope((devs), (cnt), (i), (tmp))			\
104a760f8a6SQian Cai 		if (!(tmp)) { continue; } else
105b683b230SJiang Liu 
1062ae21010SSuresh Siddha extern int dmar_table_init(void);
1072ae21010SSuresh Siddha extern int dmar_dev_scope_init(void);
108ec154bf5SJoerg Roedel extern void dmar_register_bus_notifier(void);
109bb3a6b78SJiang Liu extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
110832bd858SDavid Woodhouse extern void dmar_free_dev_scope(struct dmar_dev_scope **devices, int *cnt);
11159ce0515SJiang Liu extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
11259ce0515SJiang Liu 				 void *start, void*end, u16 segment,
113832bd858SDavid Woodhouse 				 struct dmar_dev_scope *devices,
11459ce0515SJiang Liu 				 int devices_cnt);
11559ce0515SJiang Liu extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
116832bd858SDavid Woodhouse 				 u16 segment, struct dmar_dev_scope *devices,
11759ce0515SJiang Liu 				 int count);
1182ae21010SSuresh Siddha /* Intel IOMMU detection */
11978013eaaSChristoph Hellwig void detect_intel_iommu(void);
120*d74169ceSDimitri Sivanich extern int enable_drhd_fault_handling(unsigned int cpu);
1216b197249SJiang Liu extern int dmar_device_add(acpi_handle handle);
1226b197249SJiang Liu extern int dmar_device_remove(acpi_handle handle);
1232ae21010SSuresh Siddha 
dmar_res_noop(struct acpi_dmar_header * hdr,void * arg)124c2a0b538SJiang Liu static inline int dmar_res_noop(struct acpi_dmar_header *hdr, void *arg)
125c2a0b538SJiang Liu {
126c2a0b538SJiang Liu 	return 0;
127c2a0b538SJiang Liu }
128c2a0b538SJiang Liu 
129914ff771SKyung Min Park #ifdef CONFIG_DMAR_DEBUG
130914ff771SKyung Min Park void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
131914ff771SKyung Min Park 			  unsigned long long addr, u32 pasid);
132914ff771SKyung Min Park #else
dmar_fault_dump_ptes(struct intel_iommu * iommu,u16 source_id,unsigned long long addr,u32 pasid)133914ff771SKyung Min Park static inline void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
134914ff771SKyung Min Park 					unsigned long long addr, u32 pasid) {}
135914ff771SKyung Min Park #endif
136914ff771SKyung Min Park 
1378594d832SJiang Liu #ifdef CONFIG_INTEL_IOMMU
1388594d832SJiang Liu extern int iommu_detected, no_iommu;
1398594d832SJiang Liu extern int intel_iommu_init(void);
1406c3a44edSDeepa Dinamani extern void intel_iommu_shutdown(void);
141c2a0b538SJiang Liu extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg);
142c2a0b538SJiang Liu extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
1436b197249SJiang Liu extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
14431a75cbbSYian Chen extern int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg);
1456b197249SJiang Liu extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
1466b197249SJiang Liu extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
1478594d832SJiang Liu extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
1488594d832SJiang Liu #else /* !CONFIG_INTEL_IOMMU: */
intel_iommu_init(void)1498594d832SJiang Liu static inline int intel_iommu_init(void) { return -ENODEV; }
intel_iommu_shutdown(void)1506c3a44edSDeepa Dinamani static inline void intel_iommu_shutdown(void) { }
1516b197249SJiang Liu 
152c2a0b538SJiang Liu #define	dmar_parse_one_rmrr		dmar_res_noop
153c2a0b538SJiang Liu #define	dmar_parse_one_atsr		dmar_res_noop
1546b197249SJiang Liu #define	dmar_check_one_atsr		dmar_res_noop
1556b197249SJiang Liu #define	dmar_release_one_atsr		dmar_res_noop
15631a75cbbSYian Chen #define	dmar_parse_one_satc		dmar_res_noop
1576b197249SJiang Liu 
dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info * info)1588594d832SJiang Liu static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
1598594d832SJiang Liu {
1608594d832SJiang Liu 	return 0;
1618594d832SJiang Liu }
1626b197249SJiang Liu 
dmar_iommu_hotplug(struct dmar_drhd_unit * dmaru,bool insert)1636b197249SJiang Liu static inline int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
1646b197249SJiang Liu {
1656b197249SJiang Liu 	return 0;
1666b197249SJiang Liu }
1678594d832SJiang Liu #endif /* CONFIG_INTEL_IOMMU */
1688594d832SJiang Liu 
1696b197249SJiang Liu #ifdef CONFIG_IRQ_REMAP
1706b197249SJiang Liu extern int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
1716b197249SJiang Liu #else  /* CONFIG_IRQ_REMAP */
dmar_ir_hotplug(struct dmar_drhd_unit * dmaru,bool insert)1726b197249SJiang Liu static inline int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
1736b197249SJiang Liu { return 0; }
1746b197249SJiang Liu #endif /* CONFIG_IRQ_REMAP */
1756b197249SJiang Liu 
17689a6079dSLu Baolu extern bool dmar_platform_optin(void);
17789a6079dSLu Baolu 
1786b197249SJiang Liu #else /* CONFIG_DMAR_TABLE */
1796b197249SJiang Liu 
dmar_device_add(void * handle)1806b197249SJiang Liu static inline int dmar_device_add(void *handle)
1816b197249SJiang Liu {
1826b197249SJiang Liu 	return 0;
1836b197249SJiang Liu }
1846b197249SJiang Liu 
dmar_device_remove(void * handle)1856b197249SJiang Liu static inline int dmar_device_remove(void *handle)
1866b197249SJiang Liu {
1876b197249SJiang Liu 	return 0;
1886b197249SJiang Liu }
1896b197249SJiang Liu 
dmar_platform_optin(void)19089a6079dSLu Baolu static inline bool dmar_platform_optin(void)
19189a6079dSLu Baolu {
19289a6079dSLu Baolu 	return false;
19389a6079dSLu Baolu }
19489a6079dSLu Baolu 
detect_intel_iommu(void)19578013eaaSChristoph Hellwig static inline void detect_intel_iommu(void)
19678013eaaSChristoph Hellwig {
19778013eaaSChristoph Hellwig }
19878013eaaSChristoph Hellwig 
1998594d832SJiang Liu #endif /* CONFIG_DMAR_TABLE */
2002ae21010SSuresh Siddha 
2012ae21010SSuresh Siddha struct irte {
2022ae21010SSuresh Siddha 	union {
203b1fe7f2cSPeter Zijlstra 		struct {
204b1fe7f2cSPeter Zijlstra 			union {
2053bf17472SThomas Gleixner 				/* Shared between remapped and posted mode*/
2062ae21010SSuresh Siddha 				struct {
2073bf17472SThomas Gleixner 					__u64	present		: 1,  /*  0      */
2083bf17472SThomas Gleixner 						fpd		: 1,  /*  1      */
2093bf17472SThomas Gleixner 						__res0		: 6,  /*  2 -  6 */
2103bf17472SThomas Gleixner 						avail		: 4,  /*  8 - 11 */
2113bf17472SThomas Gleixner 						__res1		: 3,  /* 12 - 14 */
2123bf17472SThomas Gleixner 						pst		: 1,  /* 15      */
2133bf17472SThomas Gleixner 						vector		: 8,  /* 16 - 23 */
2143bf17472SThomas Gleixner 						__res2		: 40; /* 24 - 63 */
2153bf17472SThomas Gleixner 				};
2163bf17472SThomas Gleixner 
2173bf17472SThomas Gleixner 				/* Remapped mode */
2183bf17472SThomas Gleixner 				struct {
2193bf17472SThomas Gleixner 					__u64	r_present	: 1,  /*  0      */
2203bf17472SThomas Gleixner 						r_fpd		: 1,  /*  1      */
2213bf17472SThomas Gleixner 						dst_mode	: 1,  /*  2      */
2223bf17472SThomas Gleixner 						redir_hint	: 1,  /*  3      */
2233bf17472SThomas Gleixner 						trigger_mode	: 1,  /*  4      */
2243bf17472SThomas Gleixner 						dlvry_mode	: 3,  /*  5 -  7 */
2253bf17472SThomas Gleixner 						r_avail		: 4,  /*  8 - 11 */
2263bf17472SThomas Gleixner 						r_res0		: 4,  /* 12 - 15 */
2273bf17472SThomas Gleixner 						r_vector	: 8,  /* 16 - 23 */
2283bf17472SThomas Gleixner 						r_res1		: 8,  /* 24 - 31 */
2293bf17472SThomas Gleixner 						dest_id		: 32; /* 32 - 63 */
2303bf17472SThomas Gleixner 				};
2313bf17472SThomas Gleixner 
2323bf17472SThomas Gleixner 				/* Posted mode */
2333bf17472SThomas Gleixner 				struct {
2343bf17472SThomas Gleixner 					__u64	p_present	: 1,  /*  0      */
2353bf17472SThomas Gleixner 						p_fpd		: 1,  /*  1      */
2363bf17472SThomas Gleixner 						p_res0		: 6,  /*  2 -  7 */
2373bf17472SThomas Gleixner 						p_avail		: 4,  /*  8 - 11 */
2383bf17472SThomas Gleixner 						p_res1		: 2,  /* 12 - 13 */
2393bf17472SThomas Gleixner 						p_urgent	: 1,  /* 14      */
2403bf17472SThomas Gleixner 						p_pst		: 1,  /* 15      */
2413bf17472SThomas Gleixner 						p_vector	: 8,  /* 16 - 23 */
2423bf17472SThomas Gleixner 						p_res2		: 14, /* 24 - 37 */
2433bf17472SThomas Gleixner 						pda_l		: 26; /* 38 - 63 */
2442ae21010SSuresh Siddha 				};
2452ae21010SSuresh Siddha 				__u64 low;
2462ae21010SSuresh Siddha 			};
2472ae21010SSuresh Siddha 
2482ae21010SSuresh Siddha 			union {
2493bf17472SThomas Gleixner 				/* Shared between remapped and posted mode*/
2502ae21010SSuresh Siddha 				struct {
2513bf17472SThomas Gleixner 					__u64	sid		: 16,  /* 64 - 79  */
2523bf17472SThomas Gleixner 						sq		: 2,   /* 80 - 81  */
2533bf17472SThomas Gleixner 						svt		: 2,   /* 82 - 83  */
2543bf17472SThomas Gleixner 						__res3		: 44;  /* 84 - 127 */
2553bf17472SThomas Gleixner 				};
2563bf17472SThomas Gleixner 
2573bf17472SThomas Gleixner 				/* Posted mode*/
2583bf17472SThomas Gleixner 				struct {
2593bf17472SThomas Gleixner 					__u64	p_sid		: 16,  /* 64 - 79  */
2603bf17472SThomas Gleixner 						p_sq		: 2,   /* 80 - 81  */
2613bf17472SThomas Gleixner 						p_svt		: 2,   /* 82 - 83  */
2623bf17472SThomas Gleixner 						p_res3		: 12,  /* 84 - 95  */
2633bf17472SThomas Gleixner 						pda_h		: 32;  /* 96 - 127 */
2642ae21010SSuresh Siddha 				};
2652ae21010SSuresh Siddha 				__u64 high;
2662ae21010SSuresh Siddha 			};
2672ae21010SSuresh Siddha 		};
268b1fe7f2cSPeter Zijlstra #ifdef CONFIG_IRQ_REMAP
269b1fe7f2cSPeter Zijlstra 		__u128 irte;
270b1fe7f2cSPeter Zijlstra #endif
271b1fe7f2cSPeter Zijlstra 	};
272b1fe7f2cSPeter Zijlstra };
273423f0859SThomas Gleixner 
dmar_copy_shared_irte(struct irte * dst,struct irte * src)274bf56027fSThomas Gleixner static inline void dmar_copy_shared_irte(struct irte *dst, struct irte *src)
275bf56027fSThomas Gleixner {
276bf56027fSThomas Gleixner 	dst->present	= src->present;
277bf56027fSThomas Gleixner 	dst->fpd	= src->fpd;
278bf56027fSThomas Gleixner 	dst->avail	= src->avail;
279bf56027fSThomas Gleixner 	dst->pst	= src->pst;
280bf56027fSThomas Gleixner 	dst->vector	= src->vector;
281bf56027fSThomas Gleixner 	dst->sid	= src->sid;
282bf56027fSThomas Gleixner 	dst->sq		= src->sq;
283bf56027fSThomas Gleixner 	dst->svt	= src->svt;
284bf56027fSThomas Gleixner }
285bf56027fSThomas Gleixner 
2863bf17472SThomas Gleixner #define PDA_LOW_BIT    26
2873bf17472SThomas Gleixner #define PDA_HIGH_BIT   32
2883bf17472SThomas Gleixner 
2892ae21010SSuresh Siddha /* Can't use the common MSI interrupt functions
2902ae21010SSuresh Siddha  * since DMAR is not a pci device
2912ae21010SSuresh Siddha  */
2925c2837fbSThomas Gleixner struct irq_data;
2935c2837fbSThomas Gleixner extern void dmar_msi_unmask(struct irq_data *data);
2945c2837fbSThomas Gleixner extern void dmar_msi_mask(struct irq_data *data);
2952ae21010SSuresh Siddha extern void dmar_msi_write(int irq, struct msi_msg *msg);
2962ae21010SSuresh Siddha extern int dmar_set_interrupt(struct intel_iommu *iommu);
2971531a6a6SSuresh Siddha extern irqreturn_t dmar_fault(int irq, void *dev_id);
29834742db8SJiang Liu extern int dmar_alloc_hwirq(int id, int node, void *arg);
29934742db8SJiang Liu extern void dmar_free_hwirq(int irq);
3002ae21010SSuresh Siddha 
30110e5247fSKeshavamurthy, Anil S #endif /* __DMAR_H__ */
302