1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms and conditions of the GNU General Public License,
4  * version 2, as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope it will be useful, but WITHOUT
7  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
9  * more details.
10  *
11  * You should have received a copy of the GNU General Public License along with
12  * this program; If not, see <http://www.gnu.org/licenses/>.
13 */
14 #ifndef __ARCH_X86_IOMMU_H__
15 #define __ARCH_X86_IOMMU_H__
16 
17 #include <xen/errno.h>
18 #include <xen/list.h>
19 #include <xen/spinlock.h>
20 #include <asm/apicdef.h>
21 #include <asm/processor.h>
22 #include <asm/hvm/vmx/vmcs.h>
23 
24 #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
25 #define MAX_IOMMUS 32
26 
27 struct g2m_ioport {
28     struct list_head list;
29     unsigned int gport;
30     unsigned int mport;
31     unsigned int np;
32 };
33 
34 #define IOMMU_PAGE_SHIFT 12
35 #define IOMMU_PAGE_SIZE  (1 << IOMMU_PAGE_SHIFT)
36 #define IOMMU_PAGE_MASK  (~(IOMMU_PAGE_SIZE - 1))
37 
38 typedef uint64_t daddr_t;
39 
40 #define __dfn_to_daddr(dfn) ((daddr_t)(dfn) << IOMMU_PAGE_SHIFT)
41 #define __daddr_to_dfn(daddr) ((daddr) >> IOMMU_PAGE_SHIFT)
42 
43 #define dfn_to_daddr(dfn) __dfn_to_daddr(dfn_x(dfn))
44 #define daddr_to_dfn(daddr) _dfn(__daddr_to_dfn(daddr))
45 
46 struct arch_iommu
47 {
48     u64 pgd_maddr;                 /* io page directory machine address */
49     spinlock_t mapping_lock;            /* io page table lock */
50     int agaw;     /* adjusted guest address width, 0 is level 2 30-bit */
51     u64 iommu_bitmap;              /* bitmap of iommu(s) that the domain uses */
52     struct list_head mapped_rmrrs;
53 
54     /* amd iommu support */
55     int paging_mode;
56     struct page_info *root_table;
57     struct guest_iommu *g_iommu;
58 };
59 
60 extern struct iommu_ops iommu_ops;
61 
62 #ifdef NDEBUG
63 # include <asm/alternative.h>
64 # define iommu_call(ops, fn, args...) ({      \
65     (void)(ops);                              \
66     alternative_call(iommu_ops.fn, ## args);  \
67 })
68 
69 # define iommu_vcall(ops, fn, args...) ({     \
70     (void)(ops);                              \
71     alternative_vcall(iommu_ops.fn, ## args); \
72 })
73 #endif
74 
iommu_get_ops(void)75 static inline const struct iommu_ops *iommu_get_ops(void)
76 {
77     BUG_ON(!iommu_ops.init);
78     return &iommu_ops;
79 }
80 
81 struct iommu_init_ops {
82     const struct iommu_ops *ops;
83     int (*setup)(void);
84     bool (*supports_x2apic)(void);
85 };
86 
87 extern const struct iommu_init_ops *iommu_init_ops;
88 
89 void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned int value);
90 unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg);
91 int iommu_setup_hpet_msi(struct msi_desc *);
92 
iommu_adjust_irq_affinities(void)93 static inline int iommu_adjust_irq_affinities(void)
94 {
95     return iommu_ops.adjust_irq_affinities
96            ? iommu_ops.adjust_irq_affinities()
97            : 0;
98 }
99 
iommu_supports_x2apic(void)100 static inline bool iommu_supports_x2apic(void)
101 {
102     return iommu_init_ops && iommu_init_ops->supports_x2apic
103            ? iommu_init_ops->supports_x2apic()
104            : false;
105 }
106 
107 int iommu_enable_x2apic(void);
108 
iommu_disable_x2apic(void)109 static inline void iommu_disable_x2apic(void)
110 {
111     if ( x2apic_enabled && iommu_ops.disable_x2apic )
112         iommu_ops.disable_x2apic();
113 }
114 
115 extern bool untrusted_msi;
116 
117 int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
118                    const uint8_t gvec);
119 
120 #define iommu_sync_cache(addr, size) ({                 \
121     const struct iommu_ops *ops = iommu_get_ops();      \
122                                                         \
123     if ( ops->sync_cache )                              \
124         iommu_vcall(ops, sync_cache, addr, size);       \
125 })
126 
127 #endif /* !__ARCH_X86_IOMMU_H__ */
128 /*
129  * Local variables:
130  * mode: C
131  * c-file-style: "BSD"
132  * c-basic-offset: 4
133  * indent-tabs-mode: nil
134  * End:
135  */
136