1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef __ARCH_X86_IOMMU_H__
3 #define __ARCH_X86_IOMMU_H__
4 
5 #include <xen/errno.h>
6 #include <xen/list.h>
7 #include <xen/mem_access.h>
8 #include <xen/spinlock.h>
9 #include <asm/apicdef.h>
10 #include <asm/cache.h>
11 #include <asm/processor.h>
12 
13 #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
14 
15 struct g2m_ioport {
16     struct list_head list;
17     unsigned int gport;
18     unsigned int mport;
19     unsigned int np;
20 };
21 
22 #define IOMMU_PAGE_SHIFT 12
23 #define IOMMU_PAGE_SIZE  (1 << IOMMU_PAGE_SHIFT)
24 #define IOMMU_PAGE_MASK  (~(IOMMU_PAGE_SIZE - 1))
25 
26 typedef uint64_t daddr_t;
27 
28 #define __dfn_to_daddr(dfn) ((daddr_t)(dfn) << IOMMU_PAGE_SHIFT)
29 #define __daddr_to_dfn(daddr) ((daddr) >> IOMMU_PAGE_SHIFT)
30 
31 #define dfn_to_daddr(dfn) __dfn_to_daddr(dfn_x(dfn))
32 #define daddr_to_dfn(daddr) _dfn(__daddr_to_dfn(daddr))
33 
34 struct arch_iommu
35 {
36     spinlock_t mapping_lock; /* io page table lock */
37     struct {
38         struct page_list_head list;
39         spinlock_t lock;
40     } pgtables;
41 
42     struct list_head identity_maps;
43 
44     union {
45         /* Intel VT-d */
46         struct {
47             uint64_t pgd_maddr; /* io page directory machine address */
48             unsigned int agaw; /* adjusted guest address width, 0 is level 2 30-bit */
49             unsigned long *iommu_bitmap; /* bitmap of iommu(s) that the domain uses */
50         } vtd;
51         /* AMD IOMMU */
52         struct {
53             unsigned int paging_mode;
54             struct page_info *root_table;
55         } amd;
56     };
57 };
58 
59 extern struct iommu_ops iommu_ops;
60 
61 # include <asm/alternative.h>
62 # define iommu_call(ops, fn, args...) ({      \
63     ASSERT((ops) == &iommu_ops);              \
64     alternative_call(iommu_ops.fn, ## args);  \
65 })
66 
67 # define iommu_vcall(ops, fn, args...) ({     \
68     ASSERT((ops) == &iommu_ops);              \
69     alternative_vcall(iommu_ops.fn, ## args); \
70 })
71 
iommu_get_ops(void)72 static inline const struct iommu_ops *iommu_get_ops(void)
73 {
74     BUG_ON(!iommu_ops.init);
75     return &iommu_ops;
76 }
77 
78 struct iommu_init_ops {
79     const struct iommu_ops *ops;
80     int (*setup)(void);
81     bool (*supports_x2apic)(void);
82 };
83 
84 extern const struct iommu_init_ops *iommu_init_ops;
85 
86 void iommu_update_ire_from_apic(unsigned int apic, unsigned int pin,
87                                 uint64_t rte);
88 unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg);
89 int iommu_setup_hpet_msi(struct msi_desc *msi);
90 
iommu_adjust_irq_affinities(void)91 static inline void iommu_adjust_irq_affinities(void)
92 {
93     if ( iommu_enabled && iommu_ops.adjust_irq_affinities )
94         iommu_vcall(&iommu_ops, adjust_irq_affinities);
95 }
96 
iommu_supports_x2apic(void)97 static inline bool iommu_supports_x2apic(void)
98 {
99     return iommu_init_ops && iommu_init_ops->supports_x2apic
100            ? iommu_init_ops->supports_x2apic()
101            : false;
102 }
103 
104 int iommu_enable_x2apic(void);
105 
iommu_disable_x2apic(void)106 static inline void iommu_disable_x2apic(void)
107 {
108     if ( x2apic_enabled && iommu_ops.disable_x2apic )
109         iommu_vcall(&iommu_ops, disable_x2apic);
110 }
111 
112 int iommu_identity_mapping(struct domain *d, p2m_access_t p2ma,
113                            paddr_t base, paddr_t end,
114                            unsigned int flag);
115 void iommu_identity_map_teardown(struct domain *d);
116 
117 extern bool untrusted_msi;
118 
119 extern bool iommu_non_coherent, iommu_superpages;
120 
iommu_sync_cache(const void * addr,unsigned int size)121 static inline void iommu_sync_cache(const void *addr, unsigned int size)
122 {
123     if ( iommu_non_coherent )
124         cache_writeback(addr, size);
125 }
126 
127 unsigned long *iommu_init_domid(domid_t reserve);
128 domid_t iommu_alloc_domid(unsigned long *map);
129 void iommu_free_domid(domid_t domid, unsigned long *map);
130 
131 int __must_check iommu_free_pgtables(struct domain *d);
132 struct domain_iommu;
133 struct page_info *__must_check iommu_alloc_pgtable(struct domain_iommu *hd,
134                                                    uint64_t contig_mask);
135 void iommu_queue_free_pgtable(struct domain_iommu *hd, struct page_info *pg);
136 
137 /* Check [start, end] unity map range for correctness. */
138 bool iommu_unity_region_ok(const char *prefix, mfn_t start, mfn_t end);
139 
140 #endif /* !__ARCH_X86_IOMMU_H__ */
141 /*
142  * Local variables:
143  * mode: C
144  * c-file-style: "BSD"
145  * c-basic-offset: 4
146  * indent-tabs-mode: nil
147  * End:
148  */
149