1 /*
2  * Copyright (c) 2006, Intel Corporation.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Copyright (C) Ashok Raj <ashok.raj@intel.com>
17  * Copyright (C) Shaohua Li <shaohua.li@intel.com>
18  */
19 
20 #ifndef _DMAR_H_
21 #define _DMAR_H_
22 
23 #include <xen/list.h>
24 #include <xen/iommu.h>
25 #include <xen/kexec.h>
26 
27 /* This one is for interrupt remapping */
28 struct acpi_ioapic_unit {
29     struct list_head list;
30     int apic_id;
31     union {
32         u16 info;
33         struct {
34             u16 func: 3,
35                 dev:  5,
36                 bus:  8;
37         }bdf;
38     }ioapic;
39 };
40 
41 struct acpi_hpet_unit {
42     struct list_head list;
43     unsigned int id;
44     union {
45         u16 bdf;
46         struct {
47             u16 func: 3,
48                 dev:  5,
49                 bus:  8;
50         };
51     };
52 };
53 
54 struct dmar_scope {
55     DECLARE_BITMAP(buses, 256);         /* buses owned by this unit */
56     u16    *devices;                    /* devices owned by this unit */
57     int    devices_cnt;
58 };
59 
60 struct acpi_drhd_unit {
61     struct dmar_scope scope;
62     struct list_head list;
63     u64    address;                     /* register base address of the unit */
64     u16    segment;
65     u8     include_all:1;
66     struct iommu *iommu;
67     struct list_head ioapic_list;
68     struct list_head hpet_list;
69 };
70 
71 struct acpi_rmrr_unit {
72     struct dmar_scope scope;
73     struct list_head list;
74     u64    base_address;
75     u64    end_address;
76     u16    segment;
77     u8     allow_all:1;
78 };
79 
80 struct acpi_atsr_unit {
81     struct dmar_scope scope;
82     struct list_head list;
83     u16    segment;
84     u8     all_ports:1;
85 };
86 
87 struct acpi_rhsa_unit {
88     struct list_head list;
89     u64    address;
90     u32    proximity_domain;
91 };
92 
93 #define for_each_drhd_unit(drhd) \
94     list_for_each_entry(drhd, &acpi_drhd_units, list)
95 
96 #define for_each_rmrr_device(rmrr, bdf, idx)            \
97     list_for_each_entry(rmrr, &acpi_rmrr_units, list)   \
98         /* assume there never is a bdf == 0 */          \
99         for (idx = 0; (bdf = rmrr->scope.devices[idx]) && \
100                  idx < rmrr->scope.devices_cnt; idx++)
101 
102 struct acpi_drhd_unit *acpi_find_matched_drhd_unit(const struct pci_dev *);
103 struct acpi_atsr_unit *acpi_find_matched_atsr_unit(const struct pci_dev *);
104 
105 #define DMAR_TYPE 1
106 #define RMRR_TYPE 2
107 #define ATSR_TYPE 3
108 
109 #define DMAR_OPERATION_TIMEOUT MILLISECS(1000)
110 
111 #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
112 do {                                                \
113     s_time_t start_time = NOW();                    \
114     while (1) {                                     \
115         sts = op(iommu->reg, offset);               \
116         if ( cond )                                 \
117             break;                                  \
118         if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT ) {    \
119             if ( !kexecing )                                    \
120                 panic("%s:%d:%s: DMAR hardware is malfunctional",\
121                       __FILE__, __LINE__, __func__);            \
122             else                                                \
123                 break;                                          \
124         }                                                       \
125         cpu_relax();                                            \
126     }                                                           \
127 } while (0)
128 
129 int vtd_hw_check(void);
130 void disable_pmr(struct iommu *iommu);
131 int is_igd_drhd(struct acpi_drhd_unit *drhd);
132 
133 #endif /* _DMAR_H_ */
134