Commit 6ec5ff4bc3a90b7716eadc4c8a686e904131f03a
Committed by
Ingo Molnar
1 parent
1d487624fc
Exists in
master
and in
7 other branches
x86: Eliminate various 'set but not used' warnings
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Cc: Joerg Roedel <joerg.roedel@amd.com> (supporter:AMD IOMMU (AMD-VI)) Cc: iommu@lists.linux-foundation.org (open list:AMD IOMMU (AMD-VI)) Link: http://lkml.kernel.org/r/1305918786-7239-3-git-send-email-padovan@profusion.mobi Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 3 changed files with 5 additions and 16 deletions Inline Diff
arch/x86/kernel/amd_iommu.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2010 Advanced Micro Devices, Inc. | 2 | * Copyright (C) 2007-2010 Advanced Micro Devices, Inc. |
3 | * Author: Joerg Roedel <joerg.roedel@amd.com> | 3 | * Author: Joerg Roedel <joerg.roedel@amd.com> |
4 | * Leo Duran <leo.duran@amd.com> | 4 | * Leo Duran <leo.duran@amd.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
8 | * by the Free Software Foundation. | 8 | * by the Free Software Foundation. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/pci-ats.h> | 21 | #include <linux/pci-ats.h> |
22 | #include <linux/bitmap.h> | 22 | #include <linux/bitmap.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/iommu-helper.h> | 27 | #include <linux/iommu-helper.h> |
28 | #include <linux/iommu.h> | 28 | #include <linux/iommu.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <asm/proto.h> | 30 | #include <asm/proto.h> |
31 | #include <asm/iommu.h> | 31 | #include <asm/iommu.h> |
32 | #include <asm/gart.h> | 32 | #include <asm/gart.h> |
33 | #include <asm/amd_iommu_proto.h> | 33 | #include <asm/amd_iommu_proto.h> |
34 | #include <asm/amd_iommu_types.h> | 34 | #include <asm/amd_iommu_types.h> |
35 | #include <asm/amd_iommu.h> | 35 | #include <asm/amd_iommu.h> |
36 | 36 | ||
37 | #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) | 37 | #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28)) |
38 | 38 | ||
39 | #define LOOP_TIMEOUT 100000 | 39 | #define LOOP_TIMEOUT 100000 |
40 | 40 | ||
41 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); | 41 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); |
42 | 42 | ||
43 | /* A list of preallocated protection domains */ | 43 | /* A list of preallocated protection domains */ |
44 | static LIST_HEAD(iommu_pd_list); | 44 | static LIST_HEAD(iommu_pd_list); |
45 | static DEFINE_SPINLOCK(iommu_pd_list_lock); | 45 | static DEFINE_SPINLOCK(iommu_pd_list_lock); |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Domain for untranslated devices - only allocated | 48 | * Domain for untranslated devices - only allocated |
49 | * if iommu=pt passed on kernel cmd line. | 49 | * if iommu=pt passed on kernel cmd line. |
50 | */ | 50 | */ |
51 | static struct protection_domain *pt_domain; | 51 | static struct protection_domain *pt_domain; |
52 | 52 | ||
53 | static struct iommu_ops amd_iommu_ops; | 53 | static struct iommu_ops amd_iommu_ops; |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * general struct to manage commands send to an IOMMU | 56 | * general struct to manage commands send to an IOMMU |
57 | */ | 57 | */ |
58 | struct iommu_cmd { | 58 | struct iommu_cmd { |
59 | u32 data[4]; | 59 | u32 data[4]; |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static void update_domain(struct protection_domain *domain); | 62 | static void update_domain(struct protection_domain *domain); |
63 | 63 | ||
64 | /**************************************************************************** | 64 | /**************************************************************************** |
65 | * | 65 | * |
66 | * Helper functions | 66 | * Helper functions |
67 | * | 67 | * |
68 | ****************************************************************************/ | 68 | ****************************************************************************/ |
69 | 69 | ||
70 | static inline u16 get_device_id(struct device *dev) | 70 | static inline u16 get_device_id(struct device *dev) |
71 | { | 71 | { |
72 | struct pci_dev *pdev = to_pci_dev(dev); | 72 | struct pci_dev *pdev = to_pci_dev(dev); |
73 | 73 | ||
74 | return calc_devid(pdev->bus->number, pdev->devfn); | 74 | return calc_devid(pdev->bus->number, pdev->devfn); |
75 | } | 75 | } |
76 | 76 | ||
77 | static struct iommu_dev_data *get_dev_data(struct device *dev) | 77 | static struct iommu_dev_data *get_dev_data(struct device *dev) |
78 | { | 78 | { |
79 | return dev->archdata.iommu; | 79 | return dev->archdata.iommu; |
80 | } | 80 | } |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * In this function the list of preallocated protection domains is traversed to | 83 | * In this function the list of preallocated protection domains is traversed to |
84 | * find the domain for a specific device | 84 | * find the domain for a specific device |
85 | */ | 85 | */ |
86 | static struct dma_ops_domain *find_protection_domain(u16 devid) | 86 | static struct dma_ops_domain *find_protection_domain(u16 devid) |
87 | { | 87 | { |
88 | struct dma_ops_domain *entry, *ret = NULL; | 88 | struct dma_ops_domain *entry, *ret = NULL; |
89 | unsigned long flags; | 89 | unsigned long flags; |
90 | u16 alias = amd_iommu_alias_table[devid]; | 90 | u16 alias = amd_iommu_alias_table[devid]; |
91 | 91 | ||
92 | if (list_empty(&iommu_pd_list)) | 92 | if (list_empty(&iommu_pd_list)) |
93 | return NULL; | 93 | return NULL; |
94 | 94 | ||
95 | spin_lock_irqsave(&iommu_pd_list_lock, flags); | 95 | spin_lock_irqsave(&iommu_pd_list_lock, flags); |
96 | 96 | ||
97 | list_for_each_entry(entry, &iommu_pd_list, list) { | 97 | list_for_each_entry(entry, &iommu_pd_list, list) { |
98 | if (entry->target_dev == devid || | 98 | if (entry->target_dev == devid || |
99 | entry->target_dev == alias) { | 99 | entry->target_dev == alias) { |
100 | ret = entry; | 100 | ret = entry; |
101 | break; | 101 | break; |
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); | 105 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); |
106 | 106 | ||
107 | return ret; | 107 | return ret; |
108 | } | 108 | } |
109 | 109 | ||
110 | /* | 110 | /* |
111 | * This function checks if the driver got a valid device from the caller to | 111 | * This function checks if the driver got a valid device from the caller to |
112 | * avoid dereferencing invalid pointers. | 112 | * avoid dereferencing invalid pointers. |
113 | */ | 113 | */ |
114 | static bool check_device(struct device *dev) | 114 | static bool check_device(struct device *dev) |
115 | { | 115 | { |
116 | u16 devid; | 116 | u16 devid; |
117 | 117 | ||
118 | if (!dev || !dev->dma_mask) | 118 | if (!dev || !dev->dma_mask) |
119 | return false; | 119 | return false; |
120 | 120 | ||
121 | /* No device or no PCI device */ | 121 | /* No device or no PCI device */ |
122 | if (dev->bus != &pci_bus_type) | 122 | if (dev->bus != &pci_bus_type) |
123 | return false; | 123 | return false; |
124 | 124 | ||
125 | devid = get_device_id(dev); | 125 | devid = get_device_id(dev); |
126 | 126 | ||
127 | /* Out of our scope? */ | 127 | /* Out of our scope? */ |
128 | if (devid > amd_iommu_last_bdf) | 128 | if (devid > amd_iommu_last_bdf) |
129 | return false; | 129 | return false; |
130 | 130 | ||
131 | if (amd_iommu_rlookup_table[devid] == NULL) | 131 | if (amd_iommu_rlookup_table[devid] == NULL) |
132 | return false; | 132 | return false; |
133 | 133 | ||
134 | return true; | 134 | return true; |
135 | } | 135 | } |
136 | 136 | ||
137 | static int iommu_init_device(struct device *dev) | 137 | static int iommu_init_device(struct device *dev) |
138 | { | 138 | { |
139 | struct iommu_dev_data *dev_data; | 139 | struct iommu_dev_data *dev_data; |
140 | struct pci_dev *pdev; | 140 | struct pci_dev *pdev; |
141 | u16 devid, alias; | 141 | u16 devid, alias; |
142 | 142 | ||
143 | if (dev->archdata.iommu) | 143 | if (dev->archdata.iommu) |
144 | return 0; | 144 | return 0; |
145 | 145 | ||
146 | dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); | 146 | dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); |
147 | if (!dev_data) | 147 | if (!dev_data) |
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | 149 | ||
150 | dev_data->dev = dev; | 150 | dev_data->dev = dev; |
151 | 151 | ||
152 | devid = get_device_id(dev); | 152 | devid = get_device_id(dev); |
153 | alias = amd_iommu_alias_table[devid]; | 153 | alias = amd_iommu_alias_table[devid]; |
154 | pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); | 154 | pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); |
155 | if (pdev) | 155 | if (pdev) |
156 | dev_data->alias = &pdev->dev; | 156 | dev_data->alias = &pdev->dev; |
157 | 157 | ||
158 | atomic_set(&dev_data->bind, 0); | 158 | atomic_set(&dev_data->bind, 0); |
159 | 159 | ||
160 | dev->archdata.iommu = dev_data; | 160 | dev->archdata.iommu = dev_data; |
161 | 161 | ||
162 | 162 | ||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | static void iommu_uninit_device(struct device *dev) | 166 | static void iommu_uninit_device(struct device *dev) |
167 | { | 167 | { |
168 | kfree(dev->archdata.iommu); | 168 | kfree(dev->archdata.iommu); |
169 | } | 169 | } |
170 | 170 | ||
171 | void __init amd_iommu_uninit_devices(void) | 171 | void __init amd_iommu_uninit_devices(void) |
172 | { | 172 | { |
173 | struct pci_dev *pdev = NULL; | 173 | struct pci_dev *pdev = NULL; |
174 | 174 | ||
175 | for_each_pci_dev(pdev) { | 175 | for_each_pci_dev(pdev) { |
176 | 176 | ||
177 | if (!check_device(&pdev->dev)) | 177 | if (!check_device(&pdev->dev)) |
178 | continue; | 178 | continue; |
179 | 179 | ||
180 | iommu_uninit_device(&pdev->dev); | 180 | iommu_uninit_device(&pdev->dev); |
181 | } | 181 | } |
182 | } | 182 | } |
183 | 183 | ||
184 | int __init amd_iommu_init_devices(void) | 184 | int __init amd_iommu_init_devices(void) |
185 | { | 185 | { |
186 | struct pci_dev *pdev = NULL; | 186 | struct pci_dev *pdev = NULL; |
187 | int ret = 0; | 187 | int ret = 0; |
188 | 188 | ||
189 | for_each_pci_dev(pdev) { | 189 | for_each_pci_dev(pdev) { |
190 | 190 | ||
191 | if (!check_device(&pdev->dev)) | 191 | if (!check_device(&pdev->dev)) |
192 | continue; | 192 | continue; |
193 | 193 | ||
194 | ret = iommu_init_device(&pdev->dev); | 194 | ret = iommu_init_device(&pdev->dev); |
195 | if (ret) | 195 | if (ret) |
196 | goto out_free; | 196 | goto out_free; |
197 | } | 197 | } |
198 | 198 | ||
199 | return 0; | 199 | return 0; |
200 | 200 | ||
201 | out_free: | 201 | out_free: |
202 | 202 | ||
203 | amd_iommu_uninit_devices(); | 203 | amd_iommu_uninit_devices(); |
204 | 204 | ||
205 | return ret; | 205 | return ret; |
206 | } | 206 | } |
207 | #ifdef CONFIG_AMD_IOMMU_STATS | 207 | #ifdef CONFIG_AMD_IOMMU_STATS |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * Initialization code for statistics collection | 210 | * Initialization code for statistics collection |
211 | */ | 211 | */ |
212 | 212 | ||
213 | DECLARE_STATS_COUNTER(compl_wait); | 213 | DECLARE_STATS_COUNTER(compl_wait); |
214 | DECLARE_STATS_COUNTER(cnt_map_single); | 214 | DECLARE_STATS_COUNTER(cnt_map_single); |
215 | DECLARE_STATS_COUNTER(cnt_unmap_single); | 215 | DECLARE_STATS_COUNTER(cnt_unmap_single); |
216 | DECLARE_STATS_COUNTER(cnt_map_sg); | 216 | DECLARE_STATS_COUNTER(cnt_map_sg); |
217 | DECLARE_STATS_COUNTER(cnt_unmap_sg); | 217 | DECLARE_STATS_COUNTER(cnt_unmap_sg); |
218 | DECLARE_STATS_COUNTER(cnt_alloc_coherent); | 218 | DECLARE_STATS_COUNTER(cnt_alloc_coherent); |
219 | DECLARE_STATS_COUNTER(cnt_free_coherent); | 219 | DECLARE_STATS_COUNTER(cnt_free_coherent); |
220 | DECLARE_STATS_COUNTER(cross_page); | 220 | DECLARE_STATS_COUNTER(cross_page); |
221 | DECLARE_STATS_COUNTER(domain_flush_single); | 221 | DECLARE_STATS_COUNTER(domain_flush_single); |
222 | DECLARE_STATS_COUNTER(domain_flush_all); | 222 | DECLARE_STATS_COUNTER(domain_flush_all); |
223 | DECLARE_STATS_COUNTER(alloced_io_mem); | 223 | DECLARE_STATS_COUNTER(alloced_io_mem); |
224 | DECLARE_STATS_COUNTER(total_map_requests); | 224 | DECLARE_STATS_COUNTER(total_map_requests); |
225 | 225 | ||
226 | static struct dentry *stats_dir; | 226 | static struct dentry *stats_dir; |
227 | static struct dentry *de_fflush; | 227 | static struct dentry *de_fflush; |
228 | 228 | ||
229 | static void amd_iommu_stats_add(struct __iommu_counter *cnt) | 229 | static void amd_iommu_stats_add(struct __iommu_counter *cnt) |
230 | { | 230 | { |
231 | if (stats_dir == NULL) | 231 | if (stats_dir == NULL) |
232 | return; | 232 | return; |
233 | 233 | ||
234 | cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir, | 234 | cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir, |
235 | &cnt->value); | 235 | &cnt->value); |
236 | } | 236 | } |
237 | 237 | ||
238 | static void amd_iommu_stats_init(void) | 238 | static void amd_iommu_stats_init(void) |
239 | { | 239 | { |
240 | stats_dir = debugfs_create_dir("amd-iommu", NULL); | 240 | stats_dir = debugfs_create_dir("amd-iommu", NULL); |
241 | if (stats_dir == NULL) | 241 | if (stats_dir == NULL) |
242 | return; | 242 | return; |
243 | 243 | ||
244 | de_fflush = debugfs_create_bool("fullflush", 0444, stats_dir, | 244 | de_fflush = debugfs_create_bool("fullflush", 0444, stats_dir, |
245 | (u32 *)&amd_iommu_unmap_flush); | 245 | (u32 *)&amd_iommu_unmap_flush); |
246 | 246 | ||
247 | amd_iommu_stats_add(&compl_wait); | 247 | amd_iommu_stats_add(&compl_wait); |
248 | amd_iommu_stats_add(&cnt_map_single); | 248 | amd_iommu_stats_add(&cnt_map_single); |
249 | amd_iommu_stats_add(&cnt_unmap_single); | 249 | amd_iommu_stats_add(&cnt_unmap_single); |
250 | amd_iommu_stats_add(&cnt_map_sg); | 250 | amd_iommu_stats_add(&cnt_map_sg); |
251 | amd_iommu_stats_add(&cnt_unmap_sg); | 251 | amd_iommu_stats_add(&cnt_unmap_sg); |
252 | amd_iommu_stats_add(&cnt_alloc_coherent); | 252 | amd_iommu_stats_add(&cnt_alloc_coherent); |
253 | amd_iommu_stats_add(&cnt_free_coherent); | 253 | amd_iommu_stats_add(&cnt_free_coherent); |
254 | amd_iommu_stats_add(&cross_page); | 254 | amd_iommu_stats_add(&cross_page); |
255 | amd_iommu_stats_add(&domain_flush_single); | 255 | amd_iommu_stats_add(&domain_flush_single); |
256 | amd_iommu_stats_add(&domain_flush_all); | 256 | amd_iommu_stats_add(&domain_flush_all); |
257 | amd_iommu_stats_add(&alloced_io_mem); | 257 | amd_iommu_stats_add(&alloced_io_mem); |
258 | amd_iommu_stats_add(&total_map_requests); | 258 | amd_iommu_stats_add(&total_map_requests); |
259 | } | 259 | } |
260 | 260 | ||
261 | #endif | 261 | #endif |
262 | 262 | ||
263 | /**************************************************************************** | 263 | /**************************************************************************** |
264 | * | 264 | * |
265 | * Interrupt handling functions | 265 | * Interrupt handling functions |
266 | * | 266 | * |
267 | ****************************************************************************/ | 267 | ****************************************************************************/ |
268 | 268 | ||
269 | static void dump_dte_entry(u16 devid) | 269 | static void dump_dte_entry(u16 devid) |
270 | { | 270 | { |
271 | int i; | 271 | int i; |
272 | 272 | ||
273 | for (i = 0; i < 8; ++i) | 273 | for (i = 0; i < 8; ++i) |
274 | pr_err("AMD-Vi: DTE[%d]: %08x\n", i, | 274 | pr_err("AMD-Vi: DTE[%d]: %08x\n", i, |
275 | amd_iommu_dev_table[devid].data[i]); | 275 | amd_iommu_dev_table[devid].data[i]); |
276 | } | 276 | } |
277 | 277 | ||
278 | static void dump_command(unsigned long phys_addr) | 278 | static void dump_command(unsigned long phys_addr) |
279 | { | 279 | { |
280 | struct iommu_cmd *cmd = phys_to_virt(phys_addr); | 280 | struct iommu_cmd *cmd = phys_to_virt(phys_addr); |
281 | int i; | 281 | int i; |
282 | 282 | ||
283 | for (i = 0; i < 4; ++i) | 283 | for (i = 0; i < 4; ++i) |
284 | pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); | 284 | pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); |
285 | } | 285 | } |
286 | 286 | ||
287 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) | 287 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) |
288 | { | 288 | { |
289 | u32 *event = __evt; | 289 | u32 *event = __evt; |
290 | int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; | 290 | int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; |
291 | int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; | 291 | int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; |
292 | int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; | 292 | int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; |
293 | int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; | 293 | int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; |
294 | u64 address = (u64)(((u64)event[3]) << 32) | event[2]; | 294 | u64 address = (u64)(((u64)event[3]) << 32) | event[2]; |
295 | 295 | ||
296 | printk(KERN_ERR "AMD-Vi: Event logged ["); | 296 | printk(KERN_ERR "AMD-Vi: Event logged ["); |
297 | 297 | ||
298 | switch (type) { | 298 | switch (type) { |
299 | case EVENT_TYPE_ILL_DEV: | 299 | case EVENT_TYPE_ILL_DEV: |
300 | printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " | 300 | printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " |
301 | "address=0x%016llx flags=0x%04x]\n", | 301 | "address=0x%016llx flags=0x%04x]\n", |
302 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 302 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
303 | address, flags); | 303 | address, flags); |
304 | dump_dte_entry(devid); | 304 | dump_dte_entry(devid); |
305 | break; | 305 | break; |
306 | case EVENT_TYPE_IO_FAULT: | 306 | case EVENT_TYPE_IO_FAULT: |
307 | printk("IO_PAGE_FAULT device=%02x:%02x.%x " | 307 | printk("IO_PAGE_FAULT device=%02x:%02x.%x " |
308 | "domain=0x%04x address=0x%016llx flags=0x%04x]\n", | 308 | "domain=0x%04x address=0x%016llx flags=0x%04x]\n", |
309 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 309 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
310 | domid, address, flags); | 310 | domid, address, flags); |
311 | break; | 311 | break; |
312 | case EVENT_TYPE_DEV_TAB_ERR: | 312 | case EVENT_TYPE_DEV_TAB_ERR: |
313 | printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " | 313 | printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " |
314 | "address=0x%016llx flags=0x%04x]\n", | 314 | "address=0x%016llx flags=0x%04x]\n", |
315 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 315 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
316 | address, flags); | 316 | address, flags); |
317 | break; | 317 | break; |
318 | case EVENT_TYPE_PAGE_TAB_ERR: | 318 | case EVENT_TYPE_PAGE_TAB_ERR: |
319 | printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " | 319 | printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " |
320 | "domain=0x%04x address=0x%016llx flags=0x%04x]\n", | 320 | "domain=0x%04x address=0x%016llx flags=0x%04x]\n", |
321 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 321 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
322 | domid, address, flags); | 322 | domid, address, flags); |
323 | break; | 323 | break; |
324 | case EVENT_TYPE_ILL_CMD: | 324 | case EVENT_TYPE_ILL_CMD: |
325 | printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); | 325 | printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); |
326 | dump_command(address); | 326 | dump_command(address); |
327 | break; | 327 | break; |
328 | case EVENT_TYPE_CMD_HARD_ERR: | 328 | case EVENT_TYPE_CMD_HARD_ERR: |
329 | printk("COMMAND_HARDWARE_ERROR address=0x%016llx " | 329 | printk("COMMAND_HARDWARE_ERROR address=0x%016llx " |
330 | "flags=0x%04x]\n", address, flags); | 330 | "flags=0x%04x]\n", address, flags); |
331 | break; | 331 | break; |
332 | case EVENT_TYPE_IOTLB_INV_TO: | 332 | case EVENT_TYPE_IOTLB_INV_TO: |
333 | printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " | 333 | printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " |
334 | "address=0x%016llx]\n", | 334 | "address=0x%016llx]\n", |
335 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 335 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
336 | address); | 336 | address); |
337 | break; | 337 | break; |
338 | case EVENT_TYPE_INV_DEV_REQ: | 338 | case EVENT_TYPE_INV_DEV_REQ: |
339 | printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " | 339 | printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " |
340 | "address=0x%016llx flags=0x%04x]\n", | 340 | "address=0x%016llx flags=0x%04x]\n", |
341 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 341 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
342 | address, flags); | 342 | address, flags); |
343 | break; | 343 | break; |
344 | default: | 344 | default: |
345 | printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); | 345 | printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); |
346 | } | 346 | } |
347 | } | 347 | } |
348 | 348 | ||
349 | static void iommu_poll_events(struct amd_iommu *iommu) | 349 | static void iommu_poll_events(struct amd_iommu *iommu) |
350 | { | 350 | { |
351 | u32 head, tail; | 351 | u32 head, tail; |
352 | unsigned long flags; | 352 | unsigned long flags; |
353 | 353 | ||
354 | spin_lock_irqsave(&iommu->lock, flags); | 354 | spin_lock_irqsave(&iommu->lock, flags); |
355 | 355 | ||
356 | head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); | 356 | head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); |
357 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); | 357 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); |
358 | 358 | ||
359 | while (head != tail) { | 359 | while (head != tail) { |
360 | iommu_print_event(iommu, iommu->evt_buf + head); | 360 | iommu_print_event(iommu, iommu->evt_buf + head); |
361 | head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; | 361 | head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; |
362 | } | 362 | } |
363 | 363 | ||
364 | writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); | 364 | writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); |
365 | 365 | ||
366 | spin_unlock_irqrestore(&iommu->lock, flags); | 366 | spin_unlock_irqrestore(&iommu->lock, flags); |
367 | } | 367 | } |
368 | 368 | ||
369 | irqreturn_t amd_iommu_int_thread(int irq, void *data) | 369 | irqreturn_t amd_iommu_int_thread(int irq, void *data) |
370 | { | 370 | { |
371 | struct amd_iommu *iommu; | 371 | struct amd_iommu *iommu; |
372 | 372 | ||
373 | for_each_iommu(iommu) | 373 | for_each_iommu(iommu) |
374 | iommu_poll_events(iommu); | 374 | iommu_poll_events(iommu); |
375 | 375 | ||
376 | return IRQ_HANDLED; | 376 | return IRQ_HANDLED; |
377 | } | 377 | } |
378 | 378 | ||
379 | irqreturn_t amd_iommu_int_handler(int irq, void *data) | 379 | irqreturn_t amd_iommu_int_handler(int irq, void *data) |
380 | { | 380 | { |
381 | return IRQ_WAKE_THREAD; | 381 | return IRQ_WAKE_THREAD; |
382 | } | 382 | } |
383 | 383 | ||
384 | /**************************************************************************** | 384 | /**************************************************************************** |
385 | * | 385 | * |
386 | * IOMMU command queuing functions | 386 | * IOMMU command queuing functions |
387 | * | 387 | * |
388 | ****************************************************************************/ | 388 | ****************************************************************************/ |
389 | 389 | ||
390 | static int wait_on_sem(volatile u64 *sem) | 390 | static int wait_on_sem(volatile u64 *sem) |
391 | { | 391 | { |
392 | int i = 0; | 392 | int i = 0; |
393 | 393 | ||
394 | while (*sem == 0 && i < LOOP_TIMEOUT) { | 394 | while (*sem == 0 && i < LOOP_TIMEOUT) { |
395 | udelay(1); | 395 | udelay(1); |
396 | i += 1; | 396 | i += 1; |
397 | } | 397 | } |
398 | 398 | ||
399 | if (i == LOOP_TIMEOUT) { | 399 | if (i == LOOP_TIMEOUT) { |
400 | pr_alert("AMD-Vi: Completion-Wait loop timed out\n"); | 400 | pr_alert("AMD-Vi: Completion-Wait loop timed out\n"); |
401 | return -EIO; | 401 | return -EIO; |
402 | } | 402 | } |
403 | 403 | ||
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
407 | static void copy_cmd_to_buffer(struct amd_iommu *iommu, | 407 | static void copy_cmd_to_buffer(struct amd_iommu *iommu, |
408 | struct iommu_cmd *cmd, | 408 | struct iommu_cmd *cmd, |
409 | u32 tail) | 409 | u32 tail) |
410 | { | 410 | { |
411 | u8 *target; | 411 | u8 *target; |
412 | 412 | ||
413 | target = iommu->cmd_buf + tail; | 413 | target = iommu->cmd_buf + tail; |
414 | tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size; | 414 | tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size; |
415 | 415 | ||
416 | /* Copy command to buffer */ | 416 | /* Copy command to buffer */ |
417 | memcpy(target, cmd, sizeof(*cmd)); | 417 | memcpy(target, cmd, sizeof(*cmd)); |
418 | 418 | ||
419 | /* Tell the IOMMU about it */ | 419 | /* Tell the IOMMU about it */ |
420 | writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | 420 | writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); |
421 | } | 421 | } |
422 | 422 | ||
423 | static void build_completion_wait(struct iommu_cmd *cmd, u64 address) | 423 | static void build_completion_wait(struct iommu_cmd *cmd, u64 address) |
424 | { | 424 | { |
425 | WARN_ON(address & 0x7ULL); | 425 | WARN_ON(address & 0x7ULL); |
426 | 426 | ||
427 | memset(cmd, 0, sizeof(*cmd)); | 427 | memset(cmd, 0, sizeof(*cmd)); |
428 | cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK; | 428 | cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK; |
429 | cmd->data[1] = upper_32_bits(__pa(address)); | 429 | cmd->data[1] = upper_32_bits(__pa(address)); |
430 | cmd->data[2] = 1; | 430 | cmd->data[2] = 1; |
431 | CMD_SET_TYPE(cmd, CMD_COMPL_WAIT); | 431 | CMD_SET_TYPE(cmd, CMD_COMPL_WAIT); |
432 | } | 432 | } |
433 | 433 | ||
434 | static void build_inv_dte(struct iommu_cmd *cmd, u16 devid) | 434 | static void build_inv_dte(struct iommu_cmd *cmd, u16 devid) |
435 | { | 435 | { |
436 | memset(cmd, 0, sizeof(*cmd)); | 436 | memset(cmd, 0, sizeof(*cmd)); |
437 | cmd->data[0] = devid; | 437 | cmd->data[0] = devid; |
438 | CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY); | 438 | CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY); |
439 | } | 439 | } |
440 | 440 | ||
441 | static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address, | 441 | static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address, |
442 | size_t size, u16 domid, int pde) | 442 | size_t size, u16 domid, int pde) |
443 | { | 443 | { |
444 | u64 pages; | 444 | u64 pages; |
445 | int s; | 445 | int s; |
446 | 446 | ||
447 | pages = iommu_num_pages(address, size, PAGE_SIZE); | 447 | pages = iommu_num_pages(address, size, PAGE_SIZE); |
448 | s = 0; | 448 | s = 0; |
449 | 449 | ||
450 | if (pages > 1) { | 450 | if (pages > 1) { |
451 | /* | 451 | /* |
452 | * If we have to flush more than one page, flush all | 452 | * If we have to flush more than one page, flush all |
453 | * TLB entries for this domain | 453 | * TLB entries for this domain |
454 | */ | 454 | */ |
455 | address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; | 455 | address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; |
456 | s = 1; | 456 | s = 1; |
457 | } | 457 | } |
458 | 458 | ||
459 | address &= PAGE_MASK; | 459 | address &= PAGE_MASK; |
460 | 460 | ||
461 | memset(cmd, 0, sizeof(*cmd)); | 461 | memset(cmd, 0, sizeof(*cmd)); |
462 | cmd->data[1] |= domid; | 462 | cmd->data[1] |= domid; |
463 | cmd->data[2] = lower_32_bits(address); | 463 | cmd->data[2] = lower_32_bits(address); |
464 | cmd->data[3] = upper_32_bits(address); | 464 | cmd->data[3] = upper_32_bits(address); |
465 | CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES); | 465 | CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES); |
466 | if (s) /* size bit - we flush more than one 4kb page */ | 466 | if (s) /* size bit - we flush more than one 4kb page */ |
467 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK; | 467 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK; |
468 | if (pde) /* PDE bit - we wan't flush everything not only the PTEs */ | 468 | if (pde) /* PDE bit - we wan't flush everything not only the PTEs */ |
469 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK; | 469 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK; |
470 | } | 470 | } |
471 | 471 | ||
472 | static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep, | 472 | static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep, |
473 | u64 address, size_t size) | 473 | u64 address, size_t size) |
474 | { | 474 | { |
475 | u64 pages; | 475 | u64 pages; |
476 | int s; | 476 | int s; |
477 | 477 | ||
478 | pages = iommu_num_pages(address, size, PAGE_SIZE); | 478 | pages = iommu_num_pages(address, size, PAGE_SIZE); |
479 | s = 0; | 479 | s = 0; |
480 | 480 | ||
481 | if (pages > 1) { | 481 | if (pages > 1) { |
482 | /* | 482 | /* |
483 | * If we have to flush more than one page, flush all | 483 | * If we have to flush more than one page, flush all |
484 | * TLB entries for this domain | 484 | * TLB entries for this domain |
485 | */ | 485 | */ |
486 | address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; | 486 | address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; |
487 | s = 1; | 487 | s = 1; |
488 | } | 488 | } |
489 | 489 | ||
490 | address &= PAGE_MASK; | 490 | address &= PAGE_MASK; |
491 | 491 | ||
492 | memset(cmd, 0, sizeof(*cmd)); | 492 | memset(cmd, 0, sizeof(*cmd)); |
493 | cmd->data[0] = devid; | 493 | cmd->data[0] = devid; |
494 | cmd->data[0] |= (qdep & 0xff) << 24; | 494 | cmd->data[0] |= (qdep & 0xff) << 24; |
495 | cmd->data[1] = devid; | 495 | cmd->data[1] = devid; |
496 | cmd->data[2] = lower_32_bits(address); | 496 | cmd->data[2] = lower_32_bits(address); |
497 | cmd->data[3] = upper_32_bits(address); | 497 | cmd->data[3] = upper_32_bits(address); |
498 | CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES); | 498 | CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES); |
499 | if (s) | 499 | if (s) |
500 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK; | 500 | cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK; |
501 | } | 501 | } |
502 | 502 | ||
503 | static void build_inv_all(struct iommu_cmd *cmd) | 503 | static void build_inv_all(struct iommu_cmd *cmd) |
504 | { | 504 | { |
505 | memset(cmd, 0, sizeof(*cmd)); | 505 | memset(cmd, 0, sizeof(*cmd)); |
506 | CMD_SET_TYPE(cmd, CMD_INV_ALL); | 506 | CMD_SET_TYPE(cmd, CMD_INV_ALL); |
507 | } | 507 | } |
508 | 508 | ||
509 | /* | 509 | /* |
510 | * Writes the command to the IOMMUs command buffer and informs the | 510 | * Writes the command to the IOMMUs command buffer and informs the |
511 | * hardware about the new command. | 511 | * hardware about the new command. |
512 | */ | 512 | */ |
513 | static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd) | 513 | static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd) |
514 | { | 514 | { |
515 | u32 left, tail, head, next_tail; | 515 | u32 left, tail, head, next_tail; |
516 | unsigned long flags; | 516 | unsigned long flags; |
517 | 517 | ||
518 | WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED); | 518 | WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED); |
519 | 519 | ||
520 | again: | 520 | again: |
521 | spin_lock_irqsave(&iommu->lock, flags); | 521 | spin_lock_irqsave(&iommu->lock, flags); |
522 | 522 | ||
523 | head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); | 523 | head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); |
524 | tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | 524 | tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); |
525 | next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size; | 525 | next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size; |
526 | left = (head - next_tail) % iommu->cmd_buf_size; | 526 | left = (head - next_tail) % iommu->cmd_buf_size; |
527 | 527 | ||
528 | if (left <= 2) { | 528 | if (left <= 2) { |
529 | struct iommu_cmd sync_cmd; | 529 | struct iommu_cmd sync_cmd; |
530 | volatile u64 sem = 0; | 530 | volatile u64 sem = 0; |
531 | int ret; | 531 | int ret; |
532 | 532 | ||
533 | build_completion_wait(&sync_cmd, (u64)&sem); | 533 | build_completion_wait(&sync_cmd, (u64)&sem); |
534 | copy_cmd_to_buffer(iommu, &sync_cmd, tail); | 534 | copy_cmd_to_buffer(iommu, &sync_cmd, tail); |
535 | 535 | ||
536 | spin_unlock_irqrestore(&iommu->lock, flags); | 536 | spin_unlock_irqrestore(&iommu->lock, flags); |
537 | 537 | ||
538 | if ((ret = wait_on_sem(&sem)) != 0) | 538 | if ((ret = wait_on_sem(&sem)) != 0) |
539 | return ret; | 539 | return ret; |
540 | 540 | ||
541 | goto again; | 541 | goto again; |
542 | } | 542 | } |
543 | 543 | ||
544 | copy_cmd_to_buffer(iommu, cmd, tail); | 544 | copy_cmd_to_buffer(iommu, cmd, tail); |
545 | 545 | ||
546 | /* We need to sync now to make sure all commands are processed */ | 546 | /* We need to sync now to make sure all commands are processed */ |
547 | iommu->need_sync = true; | 547 | iommu->need_sync = true; |
548 | 548 | ||
549 | spin_unlock_irqrestore(&iommu->lock, flags); | 549 | spin_unlock_irqrestore(&iommu->lock, flags); |
550 | 550 | ||
551 | return 0; | 551 | return 0; |
552 | } | 552 | } |
553 | 553 | ||
554 | /* | 554 | /* |
555 | * This function queues a completion wait command into the command | 555 | * This function queues a completion wait command into the command |
556 | * buffer of an IOMMU | 556 | * buffer of an IOMMU |
557 | */ | 557 | */ |
558 | static int iommu_completion_wait(struct amd_iommu *iommu) | 558 | static int iommu_completion_wait(struct amd_iommu *iommu) |
559 | { | 559 | { |
560 | struct iommu_cmd cmd; | 560 | struct iommu_cmd cmd; |
561 | volatile u64 sem = 0; | 561 | volatile u64 sem = 0; |
562 | int ret; | 562 | int ret; |
563 | 563 | ||
564 | if (!iommu->need_sync) | 564 | if (!iommu->need_sync) |
565 | return 0; | 565 | return 0; |
566 | 566 | ||
567 | build_completion_wait(&cmd, (u64)&sem); | 567 | build_completion_wait(&cmd, (u64)&sem); |
568 | 568 | ||
569 | ret = iommu_queue_command(iommu, &cmd); | 569 | ret = iommu_queue_command(iommu, &cmd); |
570 | if (ret) | 570 | if (ret) |
571 | return ret; | 571 | return ret; |
572 | 572 | ||
573 | return wait_on_sem(&sem); | 573 | return wait_on_sem(&sem); |
574 | } | 574 | } |
575 | 575 | ||
576 | static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid) | 576 | static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid) |
577 | { | 577 | { |
578 | struct iommu_cmd cmd; | 578 | struct iommu_cmd cmd; |
579 | 579 | ||
580 | build_inv_dte(&cmd, devid); | 580 | build_inv_dte(&cmd, devid); |
581 | 581 | ||
582 | return iommu_queue_command(iommu, &cmd); | 582 | return iommu_queue_command(iommu, &cmd); |
583 | } | 583 | } |
584 | 584 | ||
585 | static void iommu_flush_dte_all(struct amd_iommu *iommu) | 585 | static void iommu_flush_dte_all(struct amd_iommu *iommu) |
586 | { | 586 | { |
587 | u32 devid; | 587 | u32 devid; |
588 | 588 | ||
589 | for (devid = 0; devid <= 0xffff; ++devid) | 589 | for (devid = 0; devid <= 0xffff; ++devid) |
590 | iommu_flush_dte(iommu, devid); | 590 | iommu_flush_dte(iommu, devid); |
591 | 591 | ||
592 | iommu_completion_wait(iommu); | 592 | iommu_completion_wait(iommu); |
593 | } | 593 | } |
594 | 594 | ||
595 | /* | 595 | /* |
596 | * This function uses heavy locking and may disable irqs for some time. But | 596 | * This function uses heavy locking and may disable irqs for some time. But |
597 | * this is no issue because it is only called during resume. | 597 | * this is no issue because it is only called during resume. |
598 | */ | 598 | */ |
599 | static void iommu_flush_tlb_all(struct amd_iommu *iommu) | 599 | static void iommu_flush_tlb_all(struct amd_iommu *iommu) |
600 | { | 600 | { |
601 | u32 dom_id; | 601 | u32 dom_id; |
602 | 602 | ||
603 | for (dom_id = 0; dom_id <= 0xffff; ++dom_id) { | 603 | for (dom_id = 0; dom_id <= 0xffff; ++dom_id) { |
604 | struct iommu_cmd cmd; | 604 | struct iommu_cmd cmd; |
605 | build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, | 605 | build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, |
606 | dom_id, 1); | 606 | dom_id, 1); |
607 | iommu_queue_command(iommu, &cmd); | 607 | iommu_queue_command(iommu, &cmd); |
608 | } | 608 | } |
609 | 609 | ||
610 | iommu_completion_wait(iommu); | 610 | iommu_completion_wait(iommu); |
611 | } | 611 | } |
612 | 612 | ||
613 | static void iommu_flush_all(struct amd_iommu *iommu) | 613 | static void iommu_flush_all(struct amd_iommu *iommu) |
614 | { | 614 | { |
615 | struct iommu_cmd cmd; | 615 | struct iommu_cmd cmd; |
616 | 616 | ||
617 | build_inv_all(&cmd); | 617 | build_inv_all(&cmd); |
618 | 618 | ||
619 | iommu_queue_command(iommu, &cmd); | 619 | iommu_queue_command(iommu, &cmd); |
620 | iommu_completion_wait(iommu); | 620 | iommu_completion_wait(iommu); |
621 | } | 621 | } |
622 | 622 | ||
623 | void iommu_flush_all_caches(struct amd_iommu *iommu) | 623 | void iommu_flush_all_caches(struct amd_iommu *iommu) |
624 | { | 624 | { |
625 | if (iommu_feature(iommu, FEATURE_IA)) { | 625 | if (iommu_feature(iommu, FEATURE_IA)) { |
626 | iommu_flush_all(iommu); | 626 | iommu_flush_all(iommu); |
627 | } else { | 627 | } else { |
628 | iommu_flush_dte_all(iommu); | 628 | iommu_flush_dte_all(iommu); |
629 | iommu_flush_tlb_all(iommu); | 629 | iommu_flush_tlb_all(iommu); |
630 | } | 630 | } |
631 | } | 631 | } |
632 | 632 | ||
633 | /* | 633 | /* |
634 | * Command send function for flushing on-device TLB | 634 | * Command send function for flushing on-device TLB |
635 | */ | 635 | */ |
636 | static int device_flush_iotlb(struct device *dev, u64 address, size_t size) | 636 | static int device_flush_iotlb(struct device *dev, u64 address, size_t size) |
637 | { | 637 | { |
638 | struct pci_dev *pdev = to_pci_dev(dev); | 638 | struct pci_dev *pdev = to_pci_dev(dev); |
639 | struct amd_iommu *iommu; | 639 | struct amd_iommu *iommu; |
640 | struct iommu_cmd cmd; | 640 | struct iommu_cmd cmd; |
641 | u16 devid; | 641 | u16 devid; |
642 | int qdep; | 642 | int qdep; |
643 | 643 | ||
644 | qdep = pci_ats_queue_depth(pdev); | 644 | qdep = pci_ats_queue_depth(pdev); |
645 | devid = get_device_id(dev); | 645 | devid = get_device_id(dev); |
646 | iommu = amd_iommu_rlookup_table[devid]; | 646 | iommu = amd_iommu_rlookup_table[devid]; |
647 | 647 | ||
648 | build_inv_iotlb_pages(&cmd, devid, qdep, address, size); | 648 | build_inv_iotlb_pages(&cmd, devid, qdep, address, size); |
649 | 649 | ||
650 | return iommu_queue_command(iommu, &cmd); | 650 | return iommu_queue_command(iommu, &cmd); |
651 | } | 651 | } |
652 | 652 | ||
653 | /* | 653 | /* |
654 | * Command send function for invalidating a device table entry | 654 | * Command send function for invalidating a device table entry |
655 | */ | 655 | */ |
656 | static int device_flush_dte(struct device *dev) | 656 | static int device_flush_dte(struct device *dev) |
657 | { | 657 | { |
658 | struct amd_iommu *iommu; | 658 | struct amd_iommu *iommu; |
659 | struct pci_dev *pdev; | 659 | struct pci_dev *pdev; |
660 | u16 devid; | 660 | u16 devid; |
661 | int ret; | 661 | int ret; |
662 | 662 | ||
663 | pdev = to_pci_dev(dev); | 663 | pdev = to_pci_dev(dev); |
664 | devid = get_device_id(dev); | 664 | devid = get_device_id(dev); |
665 | iommu = amd_iommu_rlookup_table[devid]; | 665 | iommu = amd_iommu_rlookup_table[devid]; |
666 | 666 | ||
667 | ret = iommu_flush_dte(iommu, devid); | 667 | ret = iommu_flush_dte(iommu, devid); |
668 | if (ret) | 668 | if (ret) |
669 | return ret; | 669 | return ret; |
670 | 670 | ||
671 | if (pci_ats_enabled(pdev)) | 671 | if (pci_ats_enabled(pdev)) |
672 | ret = device_flush_iotlb(dev, 0, ~0UL); | 672 | ret = device_flush_iotlb(dev, 0, ~0UL); |
673 | 673 | ||
674 | return ret; | 674 | return ret; |
675 | } | 675 | } |
676 | 676 | ||
677 | /* | 677 | /* |
678 | * TLB invalidation function which is called from the mapping functions. | 678 | * TLB invalidation function which is called from the mapping functions. |
679 | * It invalidates a single PTE if the range to flush is within a single | 679 | * It invalidates a single PTE if the range to flush is within a single |
680 | * page. Otherwise it flushes the whole TLB of the IOMMU. | 680 | * page. Otherwise it flushes the whole TLB of the IOMMU. |
681 | */ | 681 | */ |
682 | static void __domain_flush_pages(struct protection_domain *domain, | 682 | static void __domain_flush_pages(struct protection_domain *domain, |
683 | u64 address, size_t size, int pde) | 683 | u64 address, size_t size, int pde) |
684 | { | 684 | { |
685 | struct iommu_dev_data *dev_data; | 685 | struct iommu_dev_data *dev_data; |
686 | struct iommu_cmd cmd; | 686 | struct iommu_cmd cmd; |
687 | int ret = 0, i; | 687 | int ret = 0, i; |
688 | 688 | ||
689 | build_inv_iommu_pages(&cmd, address, size, domain->id, pde); | 689 | build_inv_iommu_pages(&cmd, address, size, domain->id, pde); |
690 | 690 | ||
691 | for (i = 0; i < amd_iommus_present; ++i) { | 691 | for (i = 0; i < amd_iommus_present; ++i) { |
692 | if (!domain->dev_iommu[i]) | 692 | if (!domain->dev_iommu[i]) |
693 | continue; | 693 | continue; |
694 | 694 | ||
695 | /* | 695 | /* |
696 | * Devices of this domain are behind this IOMMU | 696 | * Devices of this domain are behind this IOMMU |
697 | * We need a TLB flush | 697 | * We need a TLB flush |
698 | */ | 698 | */ |
699 | ret |= iommu_queue_command(amd_iommus[i], &cmd); | 699 | ret |= iommu_queue_command(amd_iommus[i], &cmd); |
700 | } | 700 | } |
701 | 701 | ||
702 | list_for_each_entry(dev_data, &domain->dev_list, list) { | 702 | list_for_each_entry(dev_data, &domain->dev_list, list) { |
703 | struct pci_dev *pdev = to_pci_dev(dev_data->dev); | 703 | struct pci_dev *pdev = to_pci_dev(dev_data->dev); |
704 | 704 | ||
705 | if (!pci_ats_enabled(pdev)) | 705 | if (!pci_ats_enabled(pdev)) |
706 | continue; | 706 | continue; |
707 | 707 | ||
708 | ret |= device_flush_iotlb(dev_data->dev, address, size); | 708 | ret |= device_flush_iotlb(dev_data->dev, address, size); |
709 | } | 709 | } |
710 | 710 | ||
711 | WARN_ON(ret); | 711 | WARN_ON(ret); |
712 | } | 712 | } |
713 | 713 | ||
714 | static void domain_flush_pages(struct protection_domain *domain, | 714 | static void domain_flush_pages(struct protection_domain *domain, |
715 | u64 address, size_t size) | 715 | u64 address, size_t size) |
716 | { | 716 | { |
717 | __domain_flush_pages(domain, address, size, 0); | 717 | __domain_flush_pages(domain, address, size, 0); |
718 | } | 718 | } |
719 | 719 | ||
720 | /* Flush the whole IO/TLB for a given protection domain */ | 720 | /* Flush the whole IO/TLB for a given protection domain */ |
721 | static void domain_flush_tlb(struct protection_domain *domain) | 721 | static void domain_flush_tlb(struct protection_domain *domain) |
722 | { | 722 | { |
723 | __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0); | 723 | __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0); |
724 | } | 724 | } |
725 | 725 | ||
726 | /* Flush the whole IO/TLB for a given protection domain - including PDE */ | 726 | /* Flush the whole IO/TLB for a given protection domain - including PDE */ |
727 | static void domain_flush_tlb_pde(struct protection_domain *domain) | 727 | static void domain_flush_tlb_pde(struct protection_domain *domain) |
728 | { | 728 | { |
729 | __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1); | 729 | __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1); |
730 | } | 730 | } |
731 | 731 | ||
732 | static void domain_flush_complete(struct protection_domain *domain) | 732 | static void domain_flush_complete(struct protection_domain *domain) |
733 | { | 733 | { |
734 | int i; | 734 | int i; |
735 | 735 | ||
736 | for (i = 0; i < amd_iommus_present; ++i) { | 736 | for (i = 0; i < amd_iommus_present; ++i) { |
737 | if (!domain->dev_iommu[i]) | 737 | if (!domain->dev_iommu[i]) |
738 | continue; | 738 | continue; |
739 | 739 | ||
740 | /* | 740 | /* |
741 | * Devices of this domain are behind this IOMMU | 741 | * Devices of this domain are behind this IOMMU |
742 | * We need to wait for completion of all commands. | 742 | * We need to wait for completion of all commands. |
743 | */ | 743 | */ |
744 | iommu_completion_wait(amd_iommus[i]); | 744 | iommu_completion_wait(amd_iommus[i]); |
745 | } | 745 | } |
746 | } | 746 | } |
747 | 747 | ||
748 | 748 | ||
749 | /* | 749 | /* |
750 | * This function flushes the DTEs for all devices in domain | 750 | * This function flushes the DTEs for all devices in domain |
751 | */ | 751 | */ |
752 | static void domain_flush_devices(struct protection_domain *domain) | 752 | static void domain_flush_devices(struct protection_domain *domain) |
753 | { | 753 | { |
754 | struct iommu_dev_data *dev_data; | 754 | struct iommu_dev_data *dev_data; |
755 | unsigned long flags; | 755 | unsigned long flags; |
756 | 756 | ||
757 | spin_lock_irqsave(&domain->lock, flags); | 757 | spin_lock_irqsave(&domain->lock, flags); |
758 | 758 | ||
759 | list_for_each_entry(dev_data, &domain->dev_list, list) | 759 | list_for_each_entry(dev_data, &domain->dev_list, list) |
760 | device_flush_dte(dev_data->dev); | 760 | device_flush_dte(dev_data->dev); |
761 | 761 | ||
762 | spin_unlock_irqrestore(&domain->lock, flags); | 762 | spin_unlock_irqrestore(&domain->lock, flags); |
763 | } | 763 | } |
764 | 764 | ||
765 | /**************************************************************************** | 765 | /**************************************************************************** |
766 | * | 766 | * |
767 | * The functions below are used the create the page table mappings for | 767 | * The functions below are used the create the page table mappings for |
768 | * unity mapped regions. | 768 | * unity mapped regions. |
769 | * | 769 | * |
770 | ****************************************************************************/ | 770 | ****************************************************************************/ |
771 | 771 | ||
772 | /* | 772 | /* |
773 | * This function is used to add another level to an IO page table. Adding | 773 | * This function is used to add another level to an IO page table. Adding |
774 | * another level increases the size of the address space by 9 bits to a size up | 774 | * another level increases the size of the address space by 9 bits to a size up |
775 | * to 64 bits. | 775 | * to 64 bits. |
776 | */ | 776 | */ |
777 | static bool increase_address_space(struct protection_domain *domain, | 777 | static bool increase_address_space(struct protection_domain *domain, |
778 | gfp_t gfp) | 778 | gfp_t gfp) |
779 | { | 779 | { |
780 | u64 *pte; | 780 | u64 *pte; |
781 | 781 | ||
782 | if (domain->mode == PAGE_MODE_6_LEVEL) | 782 | if (domain->mode == PAGE_MODE_6_LEVEL) |
783 | /* address space already 64 bit large */ | 783 | /* address space already 64 bit large */ |
784 | return false; | 784 | return false; |
785 | 785 | ||
786 | pte = (void *)get_zeroed_page(gfp); | 786 | pte = (void *)get_zeroed_page(gfp); |
787 | if (!pte) | 787 | if (!pte) |
788 | return false; | 788 | return false; |
789 | 789 | ||
790 | *pte = PM_LEVEL_PDE(domain->mode, | 790 | *pte = PM_LEVEL_PDE(domain->mode, |
791 | virt_to_phys(domain->pt_root)); | 791 | virt_to_phys(domain->pt_root)); |
792 | domain->pt_root = pte; | 792 | domain->pt_root = pte; |
793 | domain->mode += 1; | 793 | domain->mode += 1; |
794 | domain->updated = true; | 794 | domain->updated = true; |
795 | 795 | ||
796 | return true; | 796 | return true; |
797 | } | 797 | } |
798 | 798 | ||
799 | static u64 *alloc_pte(struct protection_domain *domain, | 799 | static u64 *alloc_pte(struct protection_domain *domain, |
800 | unsigned long address, | 800 | unsigned long address, |
801 | unsigned long page_size, | 801 | unsigned long page_size, |
802 | u64 **pte_page, | 802 | u64 **pte_page, |
803 | gfp_t gfp) | 803 | gfp_t gfp) |
804 | { | 804 | { |
805 | int level, end_lvl; | 805 | int level, end_lvl; |
806 | u64 *pte, *page; | 806 | u64 *pte, *page; |
807 | 807 | ||
808 | BUG_ON(!is_power_of_2(page_size)); | 808 | BUG_ON(!is_power_of_2(page_size)); |
809 | 809 | ||
810 | while (address > PM_LEVEL_SIZE(domain->mode)) | 810 | while (address > PM_LEVEL_SIZE(domain->mode)) |
811 | increase_address_space(domain, gfp); | 811 | increase_address_space(domain, gfp); |
812 | 812 | ||
813 | level = domain->mode - 1; | 813 | level = domain->mode - 1; |
814 | pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; | 814 | pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; |
815 | address = PAGE_SIZE_ALIGN(address, page_size); | 815 | address = PAGE_SIZE_ALIGN(address, page_size); |
816 | end_lvl = PAGE_SIZE_LEVEL(page_size); | 816 | end_lvl = PAGE_SIZE_LEVEL(page_size); |
817 | 817 | ||
818 | while (level > end_lvl) { | 818 | while (level > end_lvl) { |
819 | if (!IOMMU_PTE_PRESENT(*pte)) { | 819 | if (!IOMMU_PTE_PRESENT(*pte)) { |
820 | page = (u64 *)get_zeroed_page(gfp); | 820 | page = (u64 *)get_zeroed_page(gfp); |
821 | if (!page) | 821 | if (!page) |
822 | return NULL; | 822 | return NULL; |
823 | *pte = PM_LEVEL_PDE(level, virt_to_phys(page)); | 823 | *pte = PM_LEVEL_PDE(level, virt_to_phys(page)); |
824 | } | 824 | } |
825 | 825 | ||
826 | /* No level skipping support yet */ | 826 | /* No level skipping support yet */ |
827 | if (PM_PTE_LEVEL(*pte) != level) | 827 | if (PM_PTE_LEVEL(*pte) != level) |
828 | return NULL; | 828 | return NULL; |
829 | 829 | ||
830 | level -= 1; | 830 | level -= 1; |
831 | 831 | ||
832 | pte = IOMMU_PTE_PAGE(*pte); | 832 | pte = IOMMU_PTE_PAGE(*pte); |
833 | 833 | ||
834 | if (pte_page && level == end_lvl) | 834 | if (pte_page && level == end_lvl) |
835 | *pte_page = pte; | 835 | *pte_page = pte; |
836 | 836 | ||
837 | pte = &pte[PM_LEVEL_INDEX(level, address)]; | 837 | pte = &pte[PM_LEVEL_INDEX(level, address)]; |
838 | } | 838 | } |
839 | 839 | ||
840 | return pte; | 840 | return pte; |
841 | } | 841 | } |
842 | 842 | ||
843 | /* | 843 | /* |
844 | * This function checks if there is a PTE for a given dma address. If | 844 | * This function checks if there is a PTE for a given dma address. If |
845 | * there is one, it returns the pointer to it. | 845 | * there is one, it returns the pointer to it. |
846 | */ | 846 | */ |
847 | static u64 *fetch_pte(struct protection_domain *domain, unsigned long address) | 847 | static u64 *fetch_pte(struct protection_domain *domain, unsigned long address) |
848 | { | 848 | { |
849 | int level; | 849 | int level; |
850 | u64 *pte; | 850 | u64 *pte; |
851 | 851 | ||
852 | if (address > PM_LEVEL_SIZE(domain->mode)) | 852 | if (address > PM_LEVEL_SIZE(domain->mode)) |
853 | return NULL; | 853 | return NULL; |
854 | 854 | ||
855 | level = domain->mode - 1; | 855 | level = domain->mode - 1; |
856 | pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; | 856 | pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; |
857 | 857 | ||
858 | while (level > 0) { | 858 | while (level > 0) { |
859 | 859 | ||
860 | /* Not Present */ | 860 | /* Not Present */ |
861 | if (!IOMMU_PTE_PRESENT(*pte)) | 861 | if (!IOMMU_PTE_PRESENT(*pte)) |
862 | return NULL; | 862 | return NULL; |
863 | 863 | ||
864 | /* Large PTE */ | 864 | /* Large PTE */ |
865 | if (PM_PTE_LEVEL(*pte) == 0x07) { | 865 | if (PM_PTE_LEVEL(*pte) == 0x07) { |
866 | unsigned long pte_mask, __pte; | 866 | unsigned long pte_mask, __pte; |
867 | 867 | ||
868 | /* | 868 | /* |
869 | * If we have a series of large PTEs, make | 869 | * If we have a series of large PTEs, make |
870 | * sure to return a pointer to the first one. | 870 | * sure to return a pointer to the first one. |
871 | */ | 871 | */ |
872 | pte_mask = PTE_PAGE_SIZE(*pte); | 872 | pte_mask = PTE_PAGE_SIZE(*pte); |
873 | pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1); | 873 | pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1); |
874 | __pte = ((unsigned long)pte) & pte_mask; | 874 | __pte = ((unsigned long)pte) & pte_mask; |
875 | 875 | ||
876 | return (u64 *)__pte; | 876 | return (u64 *)__pte; |
877 | } | 877 | } |
878 | 878 | ||
879 | /* No level skipping support yet */ | 879 | /* No level skipping support yet */ |
880 | if (PM_PTE_LEVEL(*pte) != level) | 880 | if (PM_PTE_LEVEL(*pte) != level) |
881 | return NULL; | 881 | return NULL; |
882 | 882 | ||
883 | level -= 1; | 883 | level -= 1; |
884 | 884 | ||
885 | /* Walk to the next level */ | 885 | /* Walk to the next level */ |
886 | pte = IOMMU_PTE_PAGE(*pte); | 886 | pte = IOMMU_PTE_PAGE(*pte); |
887 | pte = &pte[PM_LEVEL_INDEX(level, address)]; | 887 | pte = &pte[PM_LEVEL_INDEX(level, address)]; |
888 | } | 888 | } |
889 | 889 | ||
890 | return pte; | 890 | return pte; |
891 | } | 891 | } |
892 | 892 | ||
893 | /* | 893 | /* |
894 | * Generic mapping functions. It maps a physical address into a DMA | 894 | * Generic mapping functions. It maps a physical address into a DMA |
895 | * address space. It allocates the page table pages if necessary. | 895 | * address space. It allocates the page table pages if necessary. |
896 | * In the future it can be extended to a generic mapping function | 896 | * In the future it can be extended to a generic mapping function |
897 | * supporting all features of AMD IOMMU page tables like level skipping | 897 | * supporting all features of AMD IOMMU page tables like level skipping |
898 | * and full 64 bit address spaces. | 898 | * and full 64 bit address spaces. |
899 | */ | 899 | */ |
900 | static int iommu_map_page(struct protection_domain *dom, | 900 | static int iommu_map_page(struct protection_domain *dom, |
901 | unsigned long bus_addr, | 901 | unsigned long bus_addr, |
902 | unsigned long phys_addr, | 902 | unsigned long phys_addr, |
903 | int prot, | 903 | int prot, |
904 | unsigned long page_size) | 904 | unsigned long page_size) |
905 | { | 905 | { |
906 | u64 __pte, *pte; | 906 | u64 __pte, *pte; |
907 | int i, count; | 907 | int i, count; |
908 | 908 | ||
909 | if (!(prot & IOMMU_PROT_MASK)) | 909 | if (!(prot & IOMMU_PROT_MASK)) |
910 | return -EINVAL; | 910 | return -EINVAL; |
911 | 911 | ||
912 | bus_addr = PAGE_ALIGN(bus_addr); | 912 | bus_addr = PAGE_ALIGN(bus_addr); |
913 | phys_addr = PAGE_ALIGN(phys_addr); | 913 | phys_addr = PAGE_ALIGN(phys_addr); |
914 | count = PAGE_SIZE_PTE_COUNT(page_size); | 914 | count = PAGE_SIZE_PTE_COUNT(page_size); |
915 | pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL); | 915 | pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL); |
916 | 916 | ||
917 | for (i = 0; i < count; ++i) | 917 | for (i = 0; i < count; ++i) |
918 | if (IOMMU_PTE_PRESENT(pte[i])) | 918 | if (IOMMU_PTE_PRESENT(pte[i])) |
919 | return -EBUSY; | 919 | return -EBUSY; |
920 | 920 | ||
921 | if (page_size > PAGE_SIZE) { | 921 | if (page_size > PAGE_SIZE) { |
922 | __pte = PAGE_SIZE_PTE(phys_addr, page_size); | 922 | __pte = PAGE_SIZE_PTE(phys_addr, page_size); |
923 | __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC; | 923 | __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC; |
924 | } else | 924 | } else |
925 | __pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC; | 925 | __pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC; |
926 | 926 | ||
927 | if (prot & IOMMU_PROT_IR) | 927 | if (prot & IOMMU_PROT_IR) |
928 | __pte |= IOMMU_PTE_IR; | 928 | __pte |= IOMMU_PTE_IR; |
929 | if (prot & IOMMU_PROT_IW) | 929 | if (prot & IOMMU_PROT_IW) |
930 | __pte |= IOMMU_PTE_IW; | 930 | __pte |= IOMMU_PTE_IW; |
931 | 931 | ||
932 | for (i = 0; i < count; ++i) | 932 | for (i = 0; i < count; ++i) |
933 | pte[i] = __pte; | 933 | pte[i] = __pte; |
934 | 934 | ||
935 | update_domain(dom); | 935 | update_domain(dom); |
936 | 936 | ||
937 | return 0; | 937 | return 0; |
938 | } | 938 | } |
939 | 939 | ||
940 | static unsigned long iommu_unmap_page(struct protection_domain *dom, | 940 | static unsigned long iommu_unmap_page(struct protection_domain *dom, |
941 | unsigned long bus_addr, | 941 | unsigned long bus_addr, |
942 | unsigned long page_size) | 942 | unsigned long page_size) |
943 | { | 943 | { |
944 | unsigned long long unmap_size, unmapped; | 944 | unsigned long long unmap_size, unmapped; |
945 | u64 *pte; | 945 | u64 *pte; |
946 | 946 | ||
947 | BUG_ON(!is_power_of_2(page_size)); | 947 | BUG_ON(!is_power_of_2(page_size)); |
948 | 948 | ||
949 | unmapped = 0; | 949 | unmapped = 0; |
950 | 950 | ||
951 | while (unmapped < page_size) { | 951 | while (unmapped < page_size) { |
952 | 952 | ||
953 | pte = fetch_pte(dom, bus_addr); | 953 | pte = fetch_pte(dom, bus_addr); |
954 | 954 | ||
955 | if (!pte) { | 955 | if (!pte) { |
956 | /* | 956 | /* |
957 | * No PTE for this address | 957 | * No PTE for this address |
958 | * move forward in 4kb steps | 958 | * move forward in 4kb steps |
959 | */ | 959 | */ |
960 | unmap_size = PAGE_SIZE; | 960 | unmap_size = PAGE_SIZE; |
961 | } else if (PM_PTE_LEVEL(*pte) == 0) { | 961 | } else if (PM_PTE_LEVEL(*pte) == 0) { |
962 | /* 4kb PTE found for this address */ | 962 | /* 4kb PTE found for this address */ |
963 | unmap_size = PAGE_SIZE; | 963 | unmap_size = PAGE_SIZE; |
964 | *pte = 0ULL; | 964 | *pte = 0ULL; |
965 | } else { | 965 | } else { |
966 | int count, i; | 966 | int count, i; |
967 | 967 | ||
968 | /* Large PTE found which maps this address */ | 968 | /* Large PTE found which maps this address */ |
969 | unmap_size = PTE_PAGE_SIZE(*pte); | 969 | unmap_size = PTE_PAGE_SIZE(*pte); |
970 | count = PAGE_SIZE_PTE_COUNT(unmap_size); | 970 | count = PAGE_SIZE_PTE_COUNT(unmap_size); |
971 | for (i = 0; i < count; i++) | 971 | for (i = 0; i < count; i++) |
972 | pte[i] = 0ULL; | 972 | pte[i] = 0ULL; |
973 | } | 973 | } |
974 | 974 | ||
975 | bus_addr = (bus_addr & ~(unmap_size - 1)) + unmap_size; | 975 | bus_addr = (bus_addr & ~(unmap_size - 1)) + unmap_size; |
976 | unmapped += unmap_size; | 976 | unmapped += unmap_size; |
977 | } | 977 | } |
978 | 978 | ||
979 | BUG_ON(!is_power_of_2(unmapped)); | 979 | BUG_ON(!is_power_of_2(unmapped)); |
980 | 980 | ||
981 | return unmapped; | 981 | return unmapped; |
982 | } | 982 | } |
983 | 983 | ||
984 | /* | 984 | /* |
985 | * This function checks if a specific unity mapping entry is needed for | 985 | * This function checks if a specific unity mapping entry is needed for |
986 | * this specific IOMMU. | 986 | * this specific IOMMU. |
987 | */ | 987 | */ |
988 | static int iommu_for_unity_map(struct amd_iommu *iommu, | 988 | static int iommu_for_unity_map(struct amd_iommu *iommu, |
989 | struct unity_map_entry *entry) | 989 | struct unity_map_entry *entry) |
990 | { | 990 | { |
991 | u16 bdf, i; | 991 | u16 bdf, i; |
992 | 992 | ||
993 | for (i = entry->devid_start; i <= entry->devid_end; ++i) { | 993 | for (i = entry->devid_start; i <= entry->devid_end; ++i) { |
994 | bdf = amd_iommu_alias_table[i]; | 994 | bdf = amd_iommu_alias_table[i]; |
995 | if (amd_iommu_rlookup_table[bdf] == iommu) | 995 | if (amd_iommu_rlookup_table[bdf] == iommu) |
996 | return 1; | 996 | return 1; |
997 | } | 997 | } |
998 | 998 | ||
999 | return 0; | 999 | return 0; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | /* | 1002 | /* |
1003 | * This function actually applies the mapping to the page table of the | 1003 | * This function actually applies the mapping to the page table of the |
1004 | * dma_ops domain. | 1004 | * dma_ops domain. |
1005 | */ | 1005 | */ |
1006 | static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, | 1006 | static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, |
1007 | struct unity_map_entry *e) | 1007 | struct unity_map_entry *e) |
1008 | { | 1008 | { |
1009 | u64 addr; | 1009 | u64 addr; |
1010 | int ret; | 1010 | int ret; |
1011 | 1011 | ||
1012 | for (addr = e->address_start; addr < e->address_end; | 1012 | for (addr = e->address_start; addr < e->address_end; |
1013 | addr += PAGE_SIZE) { | 1013 | addr += PAGE_SIZE) { |
1014 | ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot, | 1014 | ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot, |
1015 | PAGE_SIZE); | 1015 | PAGE_SIZE); |
1016 | if (ret) | 1016 | if (ret) |
1017 | return ret; | 1017 | return ret; |
1018 | /* | 1018 | /* |
1019 | * if unity mapping is in aperture range mark the page | 1019 | * if unity mapping is in aperture range mark the page |
1020 | * as allocated in the aperture | 1020 | * as allocated in the aperture |
1021 | */ | 1021 | */ |
1022 | if (addr < dma_dom->aperture_size) | 1022 | if (addr < dma_dom->aperture_size) |
1023 | __set_bit(addr >> PAGE_SHIFT, | 1023 | __set_bit(addr >> PAGE_SHIFT, |
1024 | dma_dom->aperture[0]->bitmap); | 1024 | dma_dom->aperture[0]->bitmap); |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | return 0; | 1027 | return 0; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | /* | 1030 | /* |
1031 | * Init the unity mappings for a specific IOMMU in the system | 1031 | * Init the unity mappings for a specific IOMMU in the system |
1032 | * | 1032 | * |
1033 | * Basically iterates over all unity mapping entries and applies them to | 1033 | * Basically iterates over all unity mapping entries and applies them to |
1034 | * the default domain DMA of that IOMMU if necessary. | 1034 | * the default domain DMA of that IOMMU if necessary. |
1035 | */ | 1035 | */ |
1036 | static int iommu_init_unity_mappings(struct amd_iommu *iommu) | 1036 | static int iommu_init_unity_mappings(struct amd_iommu *iommu) |
1037 | { | 1037 | { |
1038 | struct unity_map_entry *entry; | 1038 | struct unity_map_entry *entry; |
1039 | int ret; | 1039 | int ret; |
1040 | 1040 | ||
1041 | list_for_each_entry(entry, &amd_iommu_unity_map, list) { | 1041 | list_for_each_entry(entry, &amd_iommu_unity_map, list) { |
1042 | if (!iommu_for_unity_map(iommu, entry)) | 1042 | if (!iommu_for_unity_map(iommu, entry)) |
1043 | continue; | 1043 | continue; |
1044 | ret = dma_ops_unity_map(iommu->default_dom, entry); | 1044 | ret = dma_ops_unity_map(iommu->default_dom, entry); |
1045 | if (ret) | 1045 | if (ret) |
1046 | return ret; | 1046 | return ret; |
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | return 0; | 1049 | return 0; |
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | /* | 1052 | /* |
1053 | * Inits the unity mappings required for a specific device | 1053 | * Inits the unity mappings required for a specific device |
1054 | */ | 1054 | */ |
1055 | static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, | 1055 | static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, |
1056 | u16 devid) | 1056 | u16 devid) |
1057 | { | 1057 | { |
1058 | struct unity_map_entry *e; | 1058 | struct unity_map_entry *e; |
1059 | int ret; | 1059 | int ret; |
1060 | 1060 | ||
1061 | list_for_each_entry(e, &amd_iommu_unity_map, list) { | 1061 | list_for_each_entry(e, &amd_iommu_unity_map, list) { |
1062 | if (!(devid >= e->devid_start && devid <= e->devid_end)) | 1062 | if (!(devid >= e->devid_start && devid <= e->devid_end)) |
1063 | continue; | 1063 | continue; |
1064 | ret = dma_ops_unity_map(dma_dom, e); | 1064 | ret = dma_ops_unity_map(dma_dom, e); |
1065 | if (ret) | 1065 | if (ret) |
1066 | return ret; | 1066 | return ret; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | return 0; | 1069 | return 0; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | /**************************************************************************** | 1072 | /**************************************************************************** |
1073 | * | 1073 | * |
1074 | * The next functions belong to the address allocator for the dma_ops | 1074 | * The next functions belong to the address allocator for the dma_ops |
1075 | * interface functions. They work like the allocators in the other IOMMU | 1075 | * interface functions. They work like the allocators in the other IOMMU |
1076 | * drivers. Its basically a bitmap which marks the allocated pages in | 1076 | * drivers. Its basically a bitmap which marks the allocated pages in |
1077 | * the aperture. Maybe it could be enhanced in the future to a more | 1077 | * the aperture. Maybe it could be enhanced in the future to a more |
1078 | * efficient allocator. | 1078 | * efficient allocator. |
1079 | * | 1079 | * |
1080 | ****************************************************************************/ | 1080 | ****************************************************************************/ |
1081 | 1081 | ||
1082 | /* | 1082 | /* |
1083 | * The address allocator core functions. | 1083 | * The address allocator core functions. |
1084 | * | 1084 | * |
1085 | * called with domain->lock held | 1085 | * called with domain->lock held |
1086 | */ | 1086 | */ |
1087 | 1087 | ||
1088 | /* | 1088 | /* |
1089 | * Used to reserve address ranges in the aperture (e.g. for exclusion | 1089 | * Used to reserve address ranges in the aperture (e.g. for exclusion |
1090 | * ranges. | 1090 | * ranges. |
1091 | */ | 1091 | */ |
1092 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, | 1092 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, |
1093 | unsigned long start_page, | 1093 | unsigned long start_page, |
1094 | unsigned int pages) | 1094 | unsigned int pages) |
1095 | { | 1095 | { |
1096 | unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT; | 1096 | unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT; |
1097 | 1097 | ||
1098 | if (start_page + pages > last_page) | 1098 | if (start_page + pages > last_page) |
1099 | pages = last_page - start_page; | 1099 | pages = last_page - start_page; |
1100 | 1100 | ||
1101 | for (i = start_page; i < start_page + pages; ++i) { | 1101 | for (i = start_page; i < start_page + pages; ++i) { |
1102 | int index = i / APERTURE_RANGE_PAGES; | 1102 | int index = i / APERTURE_RANGE_PAGES; |
1103 | int page = i % APERTURE_RANGE_PAGES; | 1103 | int page = i % APERTURE_RANGE_PAGES; |
1104 | __set_bit(page, dom->aperture[index]->bitmap); | 1104 | __set_bit(page, dom->aperture[index]->bitmap); |
1105 | } | 1105 | } |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | /* | 1108 | /* |
1109 | * This function is used to add a new aperture range to an existing | 1109 | * This function is used to add a new aperture range to an existing |
1110 | * aperture in case of dma_ops domain allocation or address allocation | 1110 | * aperture in case of dma_ops domain allocation or address allocation |
1111 | * failure. | 1111 | * failure. |
1112 | */ | 1112 | */ |
1113 | static int alloc_new_range(struct dma_ops_domain *dma_dom, | 1113 | static int alloc_new_range(struct dma_ops_domain *dma_dom, |
1114 | bool populate, gfp_t gfp) | 1114 | bool populate, gfp_t gfp) |
1115 | { | 1115 | { |
1116 | int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; | 1116 | int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; |
1117 | struct amd_iommu *iommu; | 1117 | struct amd_iommu *iommu; |
1118 | unsigned long i; | 1118 | unsigned long i; |
1119 | 1119 | ||
1120 | #ifdef CONFIG_IOMMU_STRESS | 1120 | #ifdef CONFIG_IOMMU_STRESS |
1121 | populate = false; | 1121 | populate = false; |
1122 | #endif | 1122 | #endif |
1123 | 1123 | ||
1124 | if (index >= APERTURE_MAX_RANGES) | 1124 | if (index >= APERTURE_MAX_RANGES) |
1125 | return -ENOMEM; | 1125 | return -ENOMEM; |
1126 | 1126 | ||
1127 | dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp); | 1127 | dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp); |
1128 | if (!dma_dom->aperture[index]) | 1128 | if (!dma_dom->aperture[index]) |
1129 | return -ENOMEM; | 1129 | return -ENOMEM; |
1130 | 1130 | ||
1131 | dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp); | 1131 | dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp); |
1132 | if (!dma_dom->aperture[index]->bitmap) | 1132 | if (!dma_dom->aperture[index]->bitmap) |
1133 | goto out_free; | 1133 | goto out_free; |
1134 | 1134 | ||
1135 | dma_dom->aperture[index]->offset = dma_dom->aperture_size; | 1135 | dma_dom->aperture[index]->offset = dma_dom->aperture_size; |
1136 | 1136 | ||
1137 | if (populate) { | 1137 | if (populate) { |
1138 | unsigned long address = dma_dom->aperture_size; | 1138 | unsigned long address = dma_dom->aperture_size; |
1139 | int i, num_ptes = APERTURE_RANGE_PAGES / 512; | 1139 | int i, num_ptes = APERTURE_RANGE_PAGES / 512; |
1140 | u64 *pte, *pte_page; | 1140 | u64 *pte, *pte_page; |
1141 | 1141 | ||
1142 | for (i = 0; i < num_ptes; ++i) { | 1142 | for (i = 0; i < num_ptes; ++i) { |
1143 | pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE, | 1143 | pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE, |
1144 | &pte_page, gfp); | 1144 | &pte_page, gfp); |
1145 | if (!pte) | 1145 | if (!pte) |
1146 | goto out_free; | 1146 | goto out_free; |
1147 | 1147 | ||
1148 | dma_dom->aperture[index]->pte_pages[i] = pte_page; | 1148 | dma_dom->aperture[index]->pte_pages[i] = pte_page; |
1149 | 1149 | ||
1150 | address += APERTURE_RANGE_SIZE / 64; | 1150 | address += APERTURE_RANGE_SIZE / 64; |
1151 | } | 1151 | } |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | dma_dom->aperture_size += APERTURE_RANGE_SIZE; | 1154 | dma_dom->aperture_size += APERTURE_RANGE_SIZE; |
1155 | 1155 | ||
1156 | /* Initialize the exclusion range if necessary */ | 1156 | /* Initialize the exclusion range if necessary */ |
1157 | for_each_iommu(iommu) { | 1157 | for_each_iommu(iommu) { |
1158 | if (iommu->exclusion_start && | 1158 | if (iommu->exclusion_start && |
1159 | iommu->exclusion_start >= dma_dom->aperture[index]->offset | 1159 | iommu->exclusion_start >= dma_dom->aperture[index]->offset |
1160 | && iommu->exclusion_start < dma_dom->aperture_size) { | 1160 | && iommu->exclusion_start < dma_dom->aperture_size) { |
1161 | unsigned long startpage; | 1161 | unsigned long startpage; |
1162 | int pages = iommu_num_pages(iommu->exclusion_start, | 1162 | int pages = iommu_num_pages(iommu->exclusion_start, |
1163 | iommu->exclusion_length, | 1163 | iommu->exclusion_length, |
1164 | PAGE_SIZE); | 1164 | PAGE_SIZE); |
1165 | startpage = iommu->exclusion_start >> PAGE_SHIFT; | 1165 | startpage = iommu->exclusion_start >> PAGE_SHIFT; |
1166 | dma_ops_reserve_addresses(dma_dom, startpage, pages); | 1166 | dma_ops_reserve_addresses(dma_dom, startpage, pages); |
1167 | } | 1167 | } |
1168 | } | 1168 | } |
1169 | 1169 | ||
1170 | /* | 1170 | /* |
1171 | * Check for areas already mapped as present in the new aperture | 1171 | * Check for areas already mapped as present in the new aperture |
1172 | * range and mark those pages as reserved in the allocator. Such | 1172 | * range and mark those pages as reserved in the allocator. Such |
1173 | * mappings may already exist as a result of requested unity | 1173 | * mappings may already exist as a result of requested unity |
1174 | * mappings for devices. | 1174 | * mappings for devices. |
1175 | */ | 1175 | */ |
1176 | for (i = dma_dom->aperture[index]->offset; | 1176 | for (i = dma_dom->aperture[index]->offset; |
1177 | i < dma_dom->aperture_size; | 1177 | i < dma_dom->aperture_size; |
1178 | i += PAGE_SIZE) { | 1178 | i += PAGE_SIZE) { |
1179 | u64 *pte = fetch_pte(&dma_dom->domain, i); | 1179 | u64 *pte = fetch_pte(&dma_dom->domain, i); |
1180 | if (!pte || !IOMMU_PTE_PRESENT(*pte)) | 1180 | if (!pte || !IOMMU_PTE_PRESENT(*pte)) |
1181 | continue; | 1181 | continue; |
1182 | 1182 | ||
1183 | dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1); | 1183 | dma_ops_reserve_addresses(dma_dom, i << PAGE_SHIFT, 1); |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | update_domain(&dma_dom->domain); | 1186 | update_domain(&dma_dom->domain); |
1187 | 1187 | ||
1188 | return 0; | 1188 | return 0; |
1189 | 1189 | ||
1190 | out_free: | 1190 | out_free: |
1191 | update_domain(&dma_dom->domain); | 1191 | update_domain(&dma_dom->domain); |
1192 | 1192 | ||
1193 | free_page((unsigned long)dma_dom->aperture[index]->bitmap); | 1193 | free_page((unsigned long)dma_dom->aperture[index]->bitmap); |
1194 | 1194 | ||
1195 | kfree(dma_dom->aperture[index]); | 1195 | kfree(dma_dom->aperture[index]); |
1196 | dma_dom->aperture[index] = NULL; | 1196 | dma_dom->aperture[index] = NULL; |
1197 | 1197 | ||
1198 | return -ENOMEM; | 1198 | return -ENOMEM; |
1199 | } | 1199 | } |
1200 | 1200 | ||
1201 | static unsigned long dma_ops_area_alloc(struct device *dev, | 1201 | static unsigned long dma_ops_area_alloc(struct device *dev, |
1202 | struct dma_ops_domain *dom, | 1202 | struct dma_ops_domain *dom, |
1203 | unsigned int pages, | 1203 | unsigned int pages, |
1204 | unsigned long align_mask, | 1204 | unsigned long align_mask, |
1205 | u64 dma_mask, | 1205 | u64 dma_mask, |
1206 | unsigned long start) | 1206 | unsigned long start) |
1207 | { | 1207 | { |
1208 | unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE; | 1208 | unsigned long next_bit = dom->next_address % APERTURE_RANGE_SIZE; |
1209 | int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT; | 1209 | int max_index = dom->aperture_size >> APERTURE_RANGE_SHIFT; |
1210 | int i = start >> APERTURE_RANGE_SHIFT; | 1210 | int i = start >> APERTURE_RANGE_SHIFT; |
1211 | unsigned long boundary_size; | 1211 | unsigned long boundary_size; |
1212 | unsigned long address = -1; | 1212 | unsigned long address = -1; |
1213 | unsigned long limit; | 1213 | unsigned long limit; |
1214 | 1214 | ||
1215 | next_bit >>= PAGE_SHIFT; | 1215 | next_bit >>= PAGE_SHIFT; |
1216 | 1216 | ||
1217 | boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, | 1217 | boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, |
1218 | PAGE_SIZE) >> PAGE_SHIFT; | 1218 | PAGE_SIZE) >> PAGE_SHIFT; |
1219 | 1219 | ||
1220 | for (;i < max_index; ++i) { | 1220 | for (;i < max_index; ++i) { |
1221 | unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT; | 1221 | unsigned long offset = dom->aperture[i]->offset >> PAGE_SHIFT; |
1222 | 1222 | ||
1223 | if (dom->aperture[i]->offset >= dma_mask) | 1223 | if (dom->aperture[i]->offset >= dma_mask) |
1224 | break; | 1224 | break; |
1225 | 1225 | ||
1226 | limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset, | 1226 | limit = iommu_device_max_index(APERTURE_RANGE_PAGES, offset, |
1227 | dma_mask >> PAGE_SHIFT); | 1227 | dma_mask >> PAGE_SHIFT); |
1228 | 1228 | ||
1229 | address = iommu_area_alloc(dom->aperture[i]->bitmap, | 1229 | address = iommu_area_alloc(dom->aperture[i]->bitmap, |
1230 | limit, next_bit, pages, 0, | 1230 | limit, next_bit, pages, 0, |
1231 | boundary_size, align_mask); | 1231 | boundary_size, align_mask); |
1232 | if (address != -1) { | 1232 | if (address != -1) { |
1233 | address = dom->aperture[i]->offset + | 1233 | address = dom->aperture[i]->offset + |
1234 | (address << PAGE_SHIFT); | 1234 | (address << PAGE_SHIFT); |
1235 | dom->next_address = address + (pages << PAGE_SHIFT); | 1235 | dom->next_address = address + (pages << PAGE_SHIFT); |
1236 | break; | 1236 | break; |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | next_bit = 0; | 1239 | next_bit = 0; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | return address; | 1242 | return address; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | static unsigned long dma_ops_alloc_addresses(struct device *dev, | 1245 | static unsigned long dma_ops_alloc_addresses(struct device *dev, |
1246 | struct dma_ops_domain *dom, | 1246 | struct dma_ops_domain *dom, |
1247 | unsigned int pages, | 1247 | unsigned int pages, |
1248 | unsigned long align_mask, | 1248 | unsigned long align_mask, |
1249 | u64 dma_mask) | 1249 | u64 dma_mask) |
1250 | { | 1250 | { |
1251 | unsigned long address; | 1251 | unsigned long address; |
1252 | 1252 | ||
1253 | #ifdef CONFIG_IOMMU_STRESS | 1253 | #ifdef CONFIG_IOMMU_STRESS |
1254 | dom->next_address = 0; | 1254 | dom->next_address = 0; |
1255 | dom->need_flush = true; | 1255 | dom->need_flush = true; |
1256 | #endif | 1256 | #endif |
1257 | 1257 | ||
1258 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, | 1258 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, |
1259 | dma_mask, dom->next_address); | 1259 | dma_mask, dom->next_address); |
1260 | 1260 | ||
1261 | if (address == -1) { | 1261 | if (address == -1) { |
1262 | dom->next_address = 0; | 1262 | dom->next_address = 0; |
1263 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, | 1263 | address = dma_ops_area_alloc(dev, dom, pages, align_mask, |
1264 | dma_mask, 0); | 1264 | dma_mask, 0); |
1265 | dom->need_flush = true; | 1265 | dom->need_flush = true; |
1266 | } | 1266 | } |
1267 | 1267 | ||
1268 | if (unlikely(address == -1)) | 1268 | if (unlikely(address == -1)) |
1269 | address = DMA_ERROR_CODE; | 1269 | address = DMA_ERROR_CODE; |
1270 | 1270 | ||
1271 | WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size); | 1271 | WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size); |
1272 | 1272 | ||
1273 | return address; | 1273 | return address; |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | /* | 1276 | /* |
1277 | * The address free function. | 1277 | * The address free function. |
1278 | * | 1278 | * |
1279 | * called with domain->lock held | 1279 | * called with domain->lock held |
1280 | */ | 1280 | */ |
1281 | static void dma_ops_free_addresses(struct dma_ops_domain *dom, | 1281 | static void dma_ops_free_addresses(struct dma_ops_domain *dom, |
1282 | unsigned long address, | 1282 | unsigned long address, |
1283 | unsigned int pages) | 1283 | unsigned int pages) |
1284 | { | 1284 | { |
1285 | unsigned i = address >> APERTURE_RANGE_SHIFT; | 1285 | unsigned i = address >> APERTURE_RANGE_SHIFT; |
1286 | struct aperture_range *range = dom->aperture[i]; | 1286 | struct aperture_range *range = dom->aperture[i]; |
1287 | 1287 | ||
1288 | BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL); | 1288 | BUG_ON(i >= APERTURE_MAX_RANGES || range == NULL); |
1289 | 1289 | ||
1290 | #ifdef CONFIG_IOMMU_STRESS | 1290 | #ifdef CONFIG_IOMMU_STRESS |
1291 | if (i < 4) | 1291 | if (i < 4) |
1292 | return; | 1292 | return; |
1293 | #endif | 1293 | #endif |
1294 | 1294 | ||
1295 | if (address >= dom->next_address) | 1295 | if (address >= dom->next_address) |
1296 | dom->need_flush = true; | 1296 | dom->need_flush = true; |
1297 | 1297 | ||
1298 | address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT; | 1298 | address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT; |
1299 | 1299 | ||
1300 | bitmap_clear(range->bitmap, address, pages); | 1300 | bitmap_clear(range->bitmap, address, pages); |
1301 | 1301 | ||
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | /**************************************************************************** | 1304 | /**************************************************************************** |
1305 | * | 1305 | * |
1306 | * The next functions belong to the domain allocation. A domain is | 1306 | * The next functions belong to the domain allocation. A domain is |
1307 | * allocated for every IOMMU as the default domain. If device isolation | 1307 | * allocated for every IOMMU as the default domain. If device isolation |
1308 | * is enabled, every device get its own domain. The most important thing | 1308 | * is enabled, every device get its own domain. The most important thing |
1309 | * about domains is the page table mapping the DMA address space they | 1309 | * about domains is the page table mapping the DMA address space they |
1310 | * contain. | 1310 | * contain. |
1311 | * | 1311 | * |
1312 | ****************************************************************************/ | 1312 | ****************************************************************************/ |
1313 | 1313 | ||
1314 | /* | 1314 | /* |
1315 | * This function adds a protection domain to the global protection domain list | 1315 | * This function adds a protection domain to the global protection domain list |
1316 | */ | 1316 | */ |
1317 | static void add_domain_to_list(struct protection_domain *domain) | 1317 | static void add_domain_to_list(struct protection_domain *domain) |
1318 | { | 1318 | { |
1319 | unsigned long flags; | 1319 | unsigned long flags; |
1320 | 1320 | ||
1321 | spin_lock_irqsave(&amd_iommu_pd_lock, flags); | 1321 | spin_lock_irqsave(&amd_iommu_pd_lock, flags); |
1322 | list_add(&domain->list, &amd_iommu_pd_list); | 1322 | list_add(&domain->list, &amd_iommu_pd_list); |
1323 | spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); | 1323 | spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | /* | 1326 | /* |
1327 | * This function removes a protection domain to the global | 1327 | * This function removes a protection domain to the global |
1328 | * protection domain list | 1328 | * protection domain list |
1329 | */ | 1329 | */ |
1330 | static void del_domain_from_list(struct protection_domain *domain) | 1330 | static void del_domain_from_list(struct protection_domain *domain) |
1331 | { | 1331 | { |
1332 | unsigned long flags; | 1332 | unsigned long flags; |
1333 | 1333 | ||
1334 | spin_lock_irqsave(&amd_iommu_pd_lock, flags); | 1334 | spin_lock_irqsave(&amd_iommu_pd_lock, flags); |
1335 | list_del(&domain->list); | 1335 | list_del(&domain->list); |
1336 | spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); | 1336 | spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | static u16 domain_id_alloc(void) | 1339 | static u16 domain_id_alloc(void) |
1340 | { | 1340 | { |
1341 | unsigned long flags; | 1341 | unsigned long flags; |
1342 | int id; | 1342 | int id; |
1343 | 1343 | ||
1344 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 1344 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1345 | id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID); | 1345 | id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID); |
1346 | BUG_ON(id == 0); | 1346 | BUG_ON(id == 0); |
1347 | if (id > 0 && id < MAX_DOMAIN_ID) | 1347 | if (id > 0 && id < MAX_DOMAIN_ID) |
1348 | __set_bit(id, amd_iommu_pd_alloc_bitmap); | 1348 | __set_bit(id, amd_iommu_pd_alloc_bitmap); |
1349 | else | 1349 | else |
1350 | id = 0; | 1350 | id = 0; |
1351 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1351 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
1352 | 1352 | ||
1353 | return id; | 1353 | return id; |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | static void domain_id_free(int id) | 1356 | static void domain_id_free(int id) |
1357 | { | 1357 | { |
1358 | unsigned long flags; | 1358 | unsigned long flags; |
1359 | 1359 | ||
1360 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 1360 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1361 | if (id > 0 && id < MAX_DOMAIN_ID) | 1361 | if (id > 0 && id < MAX_DOMAIN_ID) |
1362 | __clear_bit(id, amd_iommu_pd_alloc_bitmap); | 1362 | __clear_bit(id, amd_iommu_pd_alloc_bitmap); |
1363 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1363 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
1364 | } | 1364 | } |
1365 | 1365 | ||
1366 | static void free_pagetable(struct protection_domain *domain) | 1366 | static void free_pagetable(struct protection_domain *domain) |
1367 | { | 1367 | { |
1368 | int i, j; | 1368 | int i, j; |
1369 | u64 *p1, *p2, *p3; | 1369 | u64 *p1, *p2, *p3; |
1370 | 1370 | ||
1371 | p1 = domain->pt_root; | 1371 | p1 = domain->pt_root; |
1372 | 1372 | ||
1373 | if (!p1) | 1373 | if (!p1) |
1374 | return; | 1374 | return; |
1375 | 1375 | ||
1376 | for (i = 0; i < 512; ++i) { | 1376 | for (i = 0; i < 512; ++i) { |
1377 | if (!IOMMU_PTE_PRESENT(p1[i])) | 1377 | if (!IOMMU_PTE_PRESENT(p1[i])) |
1378 | continue; | 1378 | continue; |
1379 | 1379 | ||
1380 | p2 = IOMMU_PTE_PAGE(p1[i]); | 1380 | p2 = IOMMU_PTE_PAGE(p1[i]); |
1381 | for (j = 0; j < 512; ++j) { | 1381 | for (j = 0; j < 512; ++j) { |
1382 | if (!IOMMU_PTE_PRESENT(p2[j])) | 1382 | if (!IOMMU_PTE_PRESENT(p2[j])) |
1383 | continue; | 1383 | continue; |
1384 | p3 = IOMMU_PTE_PAGE(p2[j]); | 1384 | p3 = IOMMU_PTE_PAGE(p2[j]); |
1385 | free_page((unsigned long)p3); | 1385 | free_page((unsigned long)p3); |
1386 | } | 1386 | } |
1387 | 1387 | ||
1388 | free_page((unsigned long)p2); | 1388 | free_page((unsigned long)p2); |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | free_page((unsigned long)p1); | 1391 | free_page((unsigned long)p1); |
1392 | 1392 | ||
1393 | domain->pt_root = NULL; | 1393 | domain->pt_root = NULL; |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | /* | 1396 | /* |
1397 | * Free a domain, only used if something went wrong in the | 1397 | * Free a domain, only used if something went wrong in the |
1398 | * allocation path and we need to free an already allocated page table | 1398 | * allocation path and we need to free an already allocated page table |
1399 | */ | 1399 | */ |
1400 | static void dma_ops_domain_free(struct dma_ops_domain *dom) | 1400 | static void dma_ops_domain_free(struct dma_ops_domain *dom) |
1401 | { | 1401 | { |
1402 | int i; | 1402 | int i; |
1403 | 1403 | ||
1404 | if (!dom) | 1404 | if (!dom) |
1405 | return; | 1405 | return; |
1406 | 1406 | ||
1407 | del_domain_from_list(&dom->domain); | 1407 | del_domain_from_list(&dom->domain); |
1408 | 1408 | ||
1409 | free_pagetable(&dom->domain); | 1409 | free_pagetable(&dom->domain); |
1410 | 1410 | ||
1411 | for (i = 0; i < APERTURE_MAX_RANGES; ++i) { | 1411 | for (i = 0; i < APERTURE_MAX_RANGES; ++i) { |
1412 | if (!dom->aperture[i]) | 1412 | if (!dom->aperture[i]) |
1413 | continue; | 1413 | continue; |
1414 | free_page((unsigned long)dom->aperture[i]->bitmap); | 1414 | free_page((unsigned long)dom->aperture[i]->bitmap); |
1415 | kfree(dom->aperture[i]); | 1415 | kfree(dom->aperture[i]); |
1416 | } | 1416 | } |
1417 | 1417 | ||
1418 | kfree(dom); | 1418 | kfree(dom); |
1419 | } | 1419 | } |
1420 | 1420 | ||
1421 | /* | 1421 | /* |
1422 | * Allocates a new protection domain usable for the dma_ops functions. | 1422 | * Allocates a new protection domain usable for the dma_ops functions. |
1423 | * It also initializes the page table and the address allocator data | 1423 | * It also initializes the page table and the address allocator data |
1424 | * structures required for the dma_ops interface | 1424 | * structures required for the dma_ops interface |
1425 | */ | 1425 | */ |
1426 | static struct dma_ops_domain *dma_ops_domain_alloc(void) | 1426 | static struct dma_ops_domain *dma_ops_domain_alloc(void) |
1427 | { | 1427 | { |
1428 | struct dma_ops_domain *dma_dom; | 1428 | struct dma_ops_domain *dma_dom; |
1429 | 1429 | ||
1430 | dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL); | 1430 | dma_dom = kzalloc(sizeof(struct dma_ops_domain), GFP_KERNEL); |
1431 | if (!dma_dom) | 1431 | if (!dma_dom) |
1432 | return NULL; | 1432 | return NULL; |
1433 | 1433 | ||
1434 | spin_lock_init(&dma_dom->domain.lock); | 1434 | spin_lock_init(&dma_dom->domain.lock); |
1435 | 1435 | ||
1436 | dma_dom->domain.id = domain_id_alloc(); | 1436 | dma_dom->domain.id = domain_id_alloc(); |
1437 | if (dma_dom->domain.id == 0) | 1437 | if (dma_dom->domain.id == 0) |
1438 | goto free_dma_dom; | 1438 | goto free_dma_dom; |
1439 | INIT_LIST_HEAD(&dma_dom->domain.dev_list); | 1439 | INIT_LIST_HEAD(&dma_dom->domain.dev_list); |
1440 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; | 1440 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; |
1441 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); | 1441 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); |
1442 | dma_dom->domain.flags = PD_DMA_OPS_MASK; | 1442 | dma_dom->domain.flags = PD_DMA_OPS_MASK; |
1443 | dma_dom->domain.priv = dma_dom; | 1443 | dma_dom->domain.priv = dma_dom; |
1444 | if (!dma_dom->domain.pt_root) | 1444 | if (!dma_dom->domain.pt_root) |
1445 | goto free_dma_dom; | 1445 | goto free_dma_dom; |
1446 | 1446 | ||
1447 | dma_dom->need_flush = false; | 1447 | dma_dom->need_flush = false; |
1448 | dma_dom->target_dev = 0xffff; | 1448 | dma_dom->target_dev = 0xffff; |
1449 | 1449 | ||
1450 | add_domain_to_list(&dma_dom->domain); | 1450 | add_domain_to_list(&dma_dom->domain); |
1451 | 1451 | ||
1452 | if (alloc_new_range(dma_dom, true, GFP_KERNEL)) | 1452 | if (alloc_new_range(dma_dom, true, GFP_KERNEL)) |
1453 | goto free_dma_dom; | 1453 | goto free_dma_dom; |
1454 | 1454 | ||
1455 | /* | 1455 | /* |
1456 | * mark the first page as allocated so we never return 0 as | 1456 | * mark the first page as allocated so we never return 0 as |
1457 | * a valid dma-address. So we can use 0 as error value | 1457 | * a valid dma-address. So we can use 0 as error value |
1458 | */ | 1458 | */ |
1459 | dma_dom->aperture[0]->bitmap[0] = 1; | 1459 | dma_dom->aperture[0]->bitmap[0] = 1; |
1460 | dma_dom->next_address = 0; | 1460 | dma_dom->next_address = 0; |
1461 | 1461 | ||
1462 | 1462 | ||
1463 | return dma_dom; | 1463 | return dma_dom; |
1464 | 1464 | ||
1465 | free_dma_dom: | 1465 | free_dma_dom: |
1466 | dma_ops_domain_free(dma_dom); | 1466 | dma_ops_domain_free(dma_dom); |
1467 | 1467 | ||
1468 | return NULL; | 1468 | return NULL; |
1469 | } | 1469 | } |
1470 | 1470 | ||
1471 | /* | 1471 | /* |
1472 | * little helper function to check whether a given protection domain is a | 1472 | * little helper function to check whether a given protection domain is a |
1473 | * dma_ops domain | 1473 | * dma_ops domain |
1474 | */ | 1474 | */ |
1475 | static bool dma_ops_domain(struct protection_domain *domain) | 1475 | static bool dma_ops_domain(struct protection_domain *domain) |
1476 | { | 1476 | { |
1477 | return domain->flags & PD_DMA_OPS_MASK; | 1477 | return domain->flags & PD_DMA_OPS_MASK; |
1478 | } | 1478 | } |
1479 | 1479 | ||
1480 | static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) | 1480 | static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) |
1481 | { | 1481 | { |
1482 | u64 pte_root = virt_to_phys(domain->pt_root); | 1482 | u64 pte_root = virt_to_phys(domain->pt_root); |
1483 | u32 flags = 0; | 1483 | u32 flags = 0; |
1484 | 1484 | ||
1485 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) | 1485 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) |
1486 | << DEV_ENTRY_MODE_SHIFT; | 1486 | << DEV_ENTRY_MODE_SHIFT; |
1487 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; | 1487 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; |
1488 | 1488 | ||
1489 | if (ats) | 1489 | if (ats) |
1490 | flags |= DTE_FLAG_IOTLB; | 1490 | flags |= DTE_FLAG_IOTLB; |
1491 | 1491 | ||
1492 | amd_iommu_dev_table[devid].data[3] |= flags; | 1492 | amd_iommu_dev_table[devid].data[3] |= flags; |
1493 | amd_iommu_dev_table[devid].data[2] = domain->id; | 1493 | amd_iommu_dev_table[devid].data[2] = domain->id; |
1494 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); | 1494 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); |
1495 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); | 1495 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static void clear_dte_entry(u16 devid) | 1498 | static void clear_dte_entry(u16 devid) |
1499 | { | 1499 | { |
1500 | /* remove entry from the device table seen by the hardware */ | 1500 | /* remove entry from the device table seen by the hardware */ |
1501 | amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; | 1501 | amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; |
1502 | amd_iommu_dev_table[devid].data[1] = 0; | 1502 | amd_iommu_dev_table[devid].data[1] = 0; |
1503 | amd_iommu_dev_table[devid].data[2] = 0; | 1503 | amd_iommu_dev_table[devid].data[2] = 0; |
1504 | 1504 | ||
1505 | amd_iommu_apply_erratum_63(devid); | 1505 | amd_iommu_apply_erratum_63(devid); |
1506 | } | 1506 | } |
1507 | 1507 | ||
1508 | static void do_attach(struct device *dev, struct protection_domain *domain) | 1508 | static void do_attach(struct device *dev, struct protection_domain *domain) |
1509 | { | 1509 | { |
1510 | struct iommu_dev_data *dev_data; | 1510 | struct iommu_dev_data *dev_data; |
1511 | struct amd_iommu *iommu; | 1511 | struct amd_iommu *iommu; |
1512 | struct pci_dev *pdev; | 1512 | struct pci_dev *pdev; |
1513 | bool ats = false; | 1513 | bool ats = false; |
1514 | u16 devid; | 1514 | u16 devid; |
1515 | 1515 | ||
1516 | devid = get_device_id(dev); | 1516 | devid = get_device_id(dev); |
1517 | iommu = amd_iommu_rlookup_table[devid]; | 1517 | iommu = amd_iommu_rlookup_table[devid]; |
1518 | dev_data = get_dev_data(dev); | 1518 | dev_data = get_dev_data(dev); |
1519 | pdev = to_pci_dev(dev); | 1519 | pdev = to_pci_dev(dev); |
1520 | 1520 | ||
1521 | if (amd_iommu_iotlb_sup) | 1521 | if (amd_iommu_iotlb_sup) |
1522 | ats = pci_ats_enabled(pdev); | 1522 | ats = pci_ats_enabled(pdev); |
1523 | 1523 | ||
1524 | /* Update data structures */ | 1524 | /* Update data structures */ |
1525 | dev_data->domain = domain; | 1525 | dev_data->domain = domain; |
1526 | list_add(&dev_data->list, &domain->dev_list); | 1526 | list_add(&dev_data->list, &domain->dev_list); |
1527 | set_dte_entry(devid, domain, ats); | 1527 | set_dte_entry(devid, domain, ats); |
1528 | 1528 | ||
1529 | /* Do reference counting */ | 1529 | /* Do reference counting */ |
1530 | domain->dev_iommu[iommu->index] += 1; | 1530 | domain->dev_iommu[iommu->index] += 1; |
1531 | domain->dev_cnt += 1; | 1531 | domain->dev_cnt += 1; |
1532 | 1532 | ||
1533 | /* Flush the DTE entry */ | 1533 | /* Flush the DTE entry */ |
1534 | device_flush_dte(dev); | 1534 | device_flush_dte(dev); |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | static void do_detach(struct device *dev) | 1537 | static void do_detach(struct device *dev) |
1538 | { | 1538 | { |
1539 | struct iommu_dev_data *dev_data; | 1539 | struct iommu_dev_data *dev_data; |
1540 | struct amd_iommu *iommu; | 1540 | struct amd_iommu *iommu; |
1541 | struct pci_dev *pdev; | ||
1542 | u16 devid; | 1541 | u16 devid; |
1543 | 1542 | ||
1544 | devid = get_device_id(dev); | 1543 | devid = get_device_id(dev); |
1545 | iommu = amd_iommu_rlookup_table[devid]; | 1544 | iommu = amd_iommu_rlookup_table[devid]; |
1546 | dev_data = get_dev_data(dev); | 1545 | dev_data = get_dev_data(dev); |
1547 | pdev = to_pci_dev(dev); | ||
1548 | 1546 | ||
1549 | /* decrease reference counters */ | 1547 | /* decrease reference counters */ |
1550 | dev_data->domain->dev_iommu[iommu->index] -= 1; | 1548 | dev_data->domain->dev_iommu[iommu->index] -= 1; |
1551 | dev_data->domain->dev_cnt -= 1; | 1549 | dev_data->domain->dev_cnt -= 1; |
1552 | 1550 | ||
1553 | /* Update data structures */ | 1551 | /* Update data structures */ |
1554 | dev_data->domain = NULL; | 1552 | dev_data->domain = NULL; |
1555 | list_del(&dev_data->list); | 1553 | list_del(&dev_data->list); |
1556 | clear_dte_entry(devid); | 1554 | clear_dte_entry(devid); |
1557 | 1555 | ||
1558 | /* Flush the DTE entry */ | 1556 | /* Flush the DTE entry */ |
1559 | device_flush_dte(dev); | 1557 | device_flush_dte(dev); |
1560 | } | 1558 | } |
1561 | 1559 | ||
1562 | /* | 1560 | /* |
1563 | * If a device is not yet associated with a domain, this function does | 1561 | * If a device is not yet associated with a domain, this function does |
1564 | * assigns it visible for the hardware | 1562 | * assigns it visible for the hardware |
1565 | */ | 1563 | */ |
1566 | static int __attach_device(struct device *dev, | 1564 | static int __attach_device(struct device *dev, |
1567 | struct protection_domain *domain) | 1565 | struct protection_domain *domain) |
1568 | { | 1566 | { |
1569 | struct iommu_dev_data *dev_data, *alias_data; | 1567 | struct iommu_dev_data *dev_data, *alias_data; |
1570 | int ret; | 1568 | int ret; |
1571 | 1569 | ||
1572 | dev_data = get_dev_data(dev); | 1570 | dev_data = get_dev_data(dev); |
1573 | alias_data = get_dev_data(dev_data->alias); | 1571 | alias_data = get_dev_data(dev_data->alias); |
1574 | 1572 | ||
1575 | if (!alias_data) | 1573 | if (!alias_data) |
1576 | return -EINVAL; | 1574 | return -EINVAL; |
1577 | 1575 | ||
1578 | /* lock domain */ | 1576 | /* lock domain */ |
1579 | spin_lock(&domain->lock); | 1577 | spin_lock(&domain->lock); |
1580 | 1578 | ||
1581 | /* Some sanity checks */ | 1579 | /* Some sanity checks */ |
1582 | ret = -EBUSY; | 1580 | ret = -EBUSY; |
1583 | if (alias_data->domain != NULL && | 1581 | if (alias_data->domain != NULL && |
1584 | alias_data->domain != domain) | 1582 | alias_data->domain != domain) |
1585 | goto out_unlock; | 1583 | goto out_unlock; |
1586 | 1584 | ||
1587 | if (dev_data->domain != NULL && | 1585 | if (dev_data->domain != NULL && |
1588 | dev_data->domain != domain) | 1586 | dev_data->domain != domain) |
1589 | goto out_unlock; | 1587 | goto out_unlock; |
1590 | 1588 | ||
1591 | /* Do real assignment */ | 1589 | /* Do real assignment */ |
1592 | if (dev_data->alias != dev) { | 1590 | if (dev_data->alias != dev) { |
1593 | alias_data = get_dev_data(dev_data->alias); | 1591 | alias_data = get_dev_data(dev_data->alias); |
1594 | if (alias_data->domain == NULL) | 1592 | if (alias_data->domain == NULL) |
1595 | do_attach(dev_data->alias, domain); | 1593 | do_attach(dev_data->alias, domain); |
1596 | 1594 | ||
1597 | atomic_inc(&alias_data->bind); | 1595 | atomic_inc(&alias_data->bind); |
1598 | } | 1596 | } |
1599 | 1597 | ||
1600 | if (dev_data->domain == NULL) | 1598 | if (dev_data->domain == NULL) |
1601 | do_attach(dev, domain); | 1599 | do_attach(dev, domain); |
1602 | 1600 | ||
1603 | atomic_inc(&dev_data->bind); | 1601 | atomic_inc(&dev_data->bind); |
1604 | 1602 | ||
1605 | ret = 0; | 1603 | ret = 0; |
1606 | 1604 | ||
1607 | out_unlock: | 1605 | out_unlock: |
1608 | 1606 | ||
1609 | /* ready */ | 1607 | /* ready */ |
1610 | spin_unlock(&domain->lock); | 1608 | spin_unlock(&domain->lock); |
1611 | 1609 | ||
1612 | return ret; | 1610 | return ret; |
1613 | } | 1611 | } |
1614 | 1612 | ||
1615 | /* | 1613 | /* |
1616 | * If a device is not yet associated with a domain, this function does | 1614 | * If a device is not yet associated with a domain, this function does |
1617 | * assigns it visible for the hardware | 1615 | * assigns it visible for the hardware |
1618 | */ | 1616 | */ |
1619 | static int attach_device(struct device *dev, | 1617 | static int attach_device(struct device *dev, |
1620 | struct protection_domain *domain) | 1618 | struct protection_domain *domain) |
1621 | { | 1619 | { |
1622 | struct pci_dev *pdev = to_pci_dev(dev); | 1620 | struct pci_dev *pdev = to_pci_dev(dev); |
1623 | unsigned long flags; | 1621 | unsigned long flags; |
1624 | int ret; | 1622 | int ret; |
1625 | 1623 | ||
1626 | if (amd_iommu_iotlb_sup) | 1624 | if (amd_iommu_iotlb_sup) |
1627 | pci_enable_ats(pdev, PAGE_SHIFT); | 1625 | pci_enable_ats(pdev, PAGE_SHIFT); |
1628 | 1626 | ||
1629 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 1627 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1630 | ret = __attach_device(dev, domain); | 1628 | ret = __attach_device(dev, domain); |
1631 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1629 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
1632 | 1630 | ||
1633 | /* | 1631 | /* |
1634 | * We might boot into a crash-kernel here. The crashed kernel | 1632 | * We might boot into a crash-kernel here. The crashed kernel |
1635 | * left the caches in the IOMMU dirty. So we have to flush | 1633 | * left the caches in the IOMMU dirty. So we have to flush |
1636 | * here to evict all dirty stuff. | 1634 | * here to evict all dirty stuff. |
1637 | */ | 1635 | */ |
1638 | domain_flush_tlb_pde(domain); | 1636 | domain_flush_tlb_pde(domain); |
1639 | 1637 | ||
1640 | return ret; | 1638 | return ret; |
1641 | } | 1639 | } |
1642 | 1640 | ||
1643 | /* | 1641 | /* |
1644 | * Removes a device from a protection domain (unlocked) | 1642 | * Removes a device from a protection domain (unlocked) |
1645 | */ | 1643 | */ |
1646 | static void __detach_device(struct device *dev) | 1644 | static void __detach_device(struct device *dev) |
1647 | { | 1645 | { |
1648 | struct iommu_dev_data *dev_data = get_dev_data(dev); | 1646 | struct iommu_dev_data *dev_data = get_dev_data(dev); |
1649 | struct iommu_dev_data *alias_data; | 1647 | struct iommu_dev_data *alias_data; |
1650 | struct protection_domain *domain; | 1648 | struct protection_domain *domain; |
1651 | unsigned long flags; | 1649 | unsigned long flags; |
1652 | 1650 | ||
1653 | BUG_ON(!dev_data->domain); | 1651 | BUG_ON(!dev_data->domain); |
1654 | 1652 | ||
1655 | domain = dev_data->domain; | 1653 | domain = dev_data->domain; |
1656 | 1654 | ||
1657 | spin_lock_irqsave(&domain->lock, flags); | 1655 | spin_lock_irqsave(&domain->lock, flags); |
1658 | 1656 | ||
1659 | if (dev_data->alias != dev) { | 1657 | if (dev_data->alias != dev) { |
1660 | alias_data = get_dev_data(dev_data->alias); | 1658 | alias_data = get_dev_data(dev_data->alias); |
1661 | if (atomic_dec_and_test(&alias_data->bind)) | 1659 | if (atomic_dec_and_test(&alias_data->bind)) |
1662 | do_detach(dev_data->alias); | 1660 | do_detach(dev_data->alias); |
1663 | } | 1661 | } |
1664 | 1662 | ||
1665 | if (atomic_dec_and_test(&dev_data->bind)) | 1663 | if (atomic_dec_and_test(&dev_data->bind)) |
1666 | do_detach(dev); | 1664 | do_detach(dev); |
1667 | 1665 | ||
1668 | spin_unlock_irqrestore(&domain->lock, flags); | 1666 | spin_unlock_irqrestore(&domain->lock, flags); |
1669 | 1667 | ||
1670 | /* | 1668 | /* |
1671 | * If we run in passthrough mode the device must be assigned to the | 1669 | * If we run in passthrough mode the device must be assigned to the |
1672 | * passthrough domain if it is detached from any other domain. | 1670 | * passthrough domain if it is detached from any other domain. |
1673 | * Make sure we can deassign from the pt_domain itself. | 1671 | * Make sure we can deassign from the pt_domain itself. |
1674 | */ | 1672 | */ |
1675 | if (iommu_pass_through && | 1673 | if (iommu_pass_through && |
1676 | (dev_data->domain == NULL && domain != pt_domain)) | 1674 | (dev_data->domain == NULL && domain != pt_domain)) |
1677 | __attach_device(dev, pt_domain); | 1675 | __attach_device(dev, pt_domain); |
1678 | } | 1676 | } |
1679 | 1677 | ||
1680 | /* | 1678 | /* |
1681 | * Removes a device from a protection domain (with devtable_lock held) | 1679 | * Removes a device from a protection domain (with devtable_lock held) |
1682 | */ | 1680 | */ |
1683 | static void detach_device(struct device *dev) | 1681 | static void detach_device(struct device *dev) |
1684 | { | 1682 | { |
1685 | struct pci_dev *pdev = to_pci_dev(dev); | 1683 | struct pci_dev *pdev = to_pci_dev(dev); |
1686 | unsigned long flags; | 1684 | unsigned long flags; |
1687 | 1685 | ||
1688 | /* lock device table */ | 1686 | /* lock device table */ |
1689 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 1687 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1690 | __detach_device(dev); | 1688 | __detach_device(dev); |
1691 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1689 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
1692 | 1690 | ||
1693 | if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev)) | 1691 | if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev)) |
1694 | pci_disable_ats(pdev); | 1692 | pci_disable_ats(pdev); |
1695 | } | 1693 | } |
1696 | 1694 | ||
1697 | /* | 1695 | /* |
1698 | * Find out the protection domain structure for a given PCI device. This | 1696 | * Find out the protection domain structure for a given PCI device. This |
1699 | * will give us the pointer to the page table root for example. | 1697 | * will give us the pointer to the page table root for example. |
1700 | */ | 1698 | */ |
1701 | static struct protection_domain *domain_for_device(struct device *dev) | 1699 | static struct protection_domain *domain_for_device(struct device *dev) |
1702 | { | 1700 | { |
1703 | struct protection_domain *dom; | 1701 | struct protection_domain *dom; |
1704 | struct iommu_dev_data *dev_data, *alias_data; | 1702 | struct iommu_dev_data *dev_data, *alias_data; |
1705 | unsigned long flags; | 1703 | unsigned long flags; |
1706 | u16 devid, alias; | 1704 | u16 devid; |
1707 | 1705 | ||
1708 | devid = get_device_id(dev); | 1706 | devid = get_device_id(dev); |
1709 | alias = amd_iommu_alias_table[devid]; | ||
1710 | dev_data = get_dev_data(dev); | 1707 | dev_data = get_dev_data(dev); |
1711 | alias_data = get_dev_data(dev_data->alias); | 1708 | alias_data = get_dev_data(dev_data->alias); |
1712 | if (!alias_data) | 1709 | if (!alias_data) |
1713 | return NULL; | 1710 | return NULL; |
1714 | 1711 | ||
1715 | read_lock_irqsave(&amd_iommu_devtable_lock, flags); | 1712 | read_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1716 | dom = dev_data->domain; | 1713 | dom = dev_data->domain; |
1717 | if (dom == NULL && | 1714 | if (dom == NULL && |
1718 | alias_data->domain != NULL) { | 1715 | alias_data->domain != NULL) { |
1719 | __attach_device(dev, alias_data->domain); | 1716 | __attach_device(dev, alias_data->domain); |
1720 | dom = alias_data->domain; | 1717 | dom = alias_data->domain; |
1721 | } | 1718 | } |
1722 | 1719 | ||
1723 | read_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1720 | read_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
1724 | 1721 | ||
1725 | return dom; | 1722 | return dom; |
1726 | } | 1723 | } |
1727 | 1724 | ||
1728 | static int device_change_notifier(struct notifier_block *nb, | 1725 | static int device_change_notifier(struct notifier_block *nb, |
1729 | unsigned long action, void *data) | 1726 | unsigned long action, void *data) |
1730 | { | 1727 | { |
1731 | struct device *dev = data; | 1728 | struct device *dev = data; |
1732 | u16 devid; | 1729 | u16 devid; |
1733 | struct protection_domain *domain; | 1730 | struct protection_domain *domain; |
1734 | struct dma_ops_domain *dma_domain; | 1731 | struct dma_ops_domain *dma_domain; |
1735 | struct amd_iommu *iommu; | 1732 | struct amd_iommu *iommu; |
1736 | unsigned long flags; | 1733 | unsigned long flags; |
1737 | 1734 | ||
1738 | if (!check_device(dev)) | 1735 | if (!check_device(dev)) |
1739 | return 0; | 1736 | return 0; |
1740 | 1737 | ||
1741 | devid = get_device_id(dev); | 1738 | devid = get_device_id(dev); |
1742 | iommu = amd_iommu_rlookup_table[devid]; | 1739 | iommu = amd_iommu_rlookup_table[devid]; |
1743 | 1740 | ||
1744 | switch (action) { | 1741 | switch (action) { |
1745 | case BUS_NOTIFY_UNBOUND_DRIVER: | 1742 | case BUS_NOTIFY_UNBOUND_DRIVER: |
1746 | 1743 | ||
1747 | domain = domain_for_device(dev); | 1744 | domain = domain_for_device(dev); |
1748 | 1745 | ||
1749 | if (!domain) | 1746 | if (!domain) |
1750 | goto out; | 1747 | goto out; |
1751 | if (iommu_pass_through) | 1748 | if (iommu_pass_through) |
1752 | break; | 1749 | break; |
1753 | detach_device(dev); | 1750 | detach_device(dev); |
1754 | break; | 1751 | break; |
1755 | case BUS_NOTIFY_ADD_DEVICE: | 1752 | case BUS_NOTIFY_ADD_DEVICE: |
1756 | 1753 | ||
1757 | iommu_init_device(dev); | 1754 | iommu_init_device(dev); |
1758 | 1755 | ||
1759 | domain = domain_for_device(dev); | 1756 | domain = domain_for_device(dev); |
1760 | 1757 | ||
1761 | /* allocate a protection domain if a device is added */ | 1758 | /* allocate a protection domain if a device is added */ |
1762 | dma_domain = find_protection_domain(devid); | 1759 | dma_domain = find_protection_domain(devid); |
1763 | if (dma_domain) | 1760 | if (dma_domain) |
1764 | goto out; | 1761 | goto out; |
1765 | dma_domain = dma_ops_domain_alloc(); | 1762 | dma_domain = dma_ops_domain_alloc(); |
1766 | if (!dma_domain) | 1763 | if (!dma_domain) |
1767 | goto out; | 1764 | goto out; |
1768 | dma_domain->target_dev = devid; | 1765 | dma_domain->target_dev = devid; |
1769 | 1766 | ||
1770 | spin_lock_irqsave(&iommu_pd_list_lock, flags); | 1767 | spin_lock_irqsave(&iommu_pd_list_lock, flags); |
1771 | list_add_tail(&dma_domain->list, &iommu_pd_list); | 1768 | list_add_tail(&dma_domain->list, &iommu_pd_list); |
1772 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); | 1769 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); |
1773 | 1770 | ||
1774 | break; | 1771 | break; |
1775 | case BUS_NOTIFY_DEL_DEVICE: | 1772 | case BUS_NOTIFY_DEL_DEVICE: |
1776 | 1773 | ||
1777 | iommu_uninit_device(dev); | 1774 | iommu_uninit_device(dev); |
1778 | 1775 | ||
1779 | default: | 1776 | default: |
1780 | goto out; | 1777 | goto out; |
1781 | } | 1778 | } |
1782 | 1779 | ||
1783 | device_flush_dte(dev); | 1780 | device_flush_dte(dev); |
1784 | iommu_completion_wait(iommu); | 1781 | iommu_completion_wait(iommu); |
1785 | 1782 | ||
1786 | out: | 1783 | out: |
1787 | return 0; | 1784 | return 0; |
1788 | } | 1785 | } |
1789 | 1786 | ||
1790 | static struct notifier_block device_nb = { | 1787 | static struct notifier_block device_nb = { |
1791 | .notifier_call = device_change_notifier, | 1788 | .notifier_call = device_change_notifier, |
1792 | }; | 1789 | }; |
1793 | 1790 | ||
1794 | void amd_iommu_init_notifier(void) | 1791 | void amd_iommu_init_notifier(void) |
1795 | { | 1792 | { |
1796 | bus_register_notifier(&pci_bus_type, &device_nb); | 1793 | bus_register_notifier(&pci_bus_type, &device_nb); |
1797 | } | 1794 | } |
1798 | 1795 | ||
1799 | /***************************************************************************** | 1796 | /***************************************************************************** |
1800 | * | 1797 | * |
1801 | * The next functions belong to the dma_ops mapping/unmapping code. | 1798 | * The next functions belong to the dma_ops mapping/unmapping code. |
1802 | * | 1799 | * |
1803 | *****************************************************************************/ | 1800 | *****************************************************************************/ |
1804 | 1801 | ||
1805 | /* | 1802 | /* |
1806 | * In the dma_ops path we only have the struct device. This function | 1803 | * In the dma_ops path we only have the struct device. This function |
1807 | * finds the corresponding IOMMU, the protection domain and the | 1804 | * finds the corresponding IOMMU, the protection domain and the |
1808 | * requestor id for a given device. | 1805 | * requestor id for a given device. |
1809 | * If the device is not yet associated with a domain this is also done | 1806 | * If the device is not yet associated with a domain this is also done |
1810 | * in this function. | 1807 | * in this function. |
1811 | */ | 1808 | */ |
1812 | static struct protection_domain *get_domain(struct device *dev) | 1809 | static struct protection_domain *get_domain(struct device *dev) |
1813 | { | 1810 | { |
1814 | struct protection_domain *domain; | 1811 | struct protection_domain *domain; |
1815 | struct dma_ops_domain *dma_dom; | 1812 | struct dma_ops_domain *dma_dom; |
1816 | u16 devid = get_device_id(dev); | 1813 | u16 devid = get_device_id(dev); |
1817 | 1814 | ||
1818 | if (!check_device(dev)) | 1815 | if (!check_device(dev)) |
1819 | return ERR_PTR(-EINVAL); | 1816 | return ERR_PTR(-EINVAL); |
1820 | 1817 | ||
1821 | domain = domain_for_device(dev); | 1818 | domain = domain_for_device(dev); |
1822 | if (domain != NULL && !dma_ops_domain(domain)) | 1819 | if (domain != NULL && !dma_ops_domain(domain)) |
1823 | return ERR_PTR(-EBUSY); | 1820 | return ERR_PTR(-EBUSY); |
1824 | 1821 | ||
1825 | if (domain != NULL) | 1822 | if (domain != NULL) |
1826 | return domain; | 1823 | return domain; |
1827 | 1824 | ||
1828 | /* Device not bount yet - bind it */ | 1825 | /* Device not bount yet - bind it */ |
1829 | dma_dom = find_protection_domain(devid); | 1826 | dma_dom = find_protection_domain(devid); |
1830 | if (!dma_dom) | 1827 | if (!dma_dom) |
1831 | dma_dom = amd_iommu_rlookup_table[devid]->default_dom; | 1828 | dma_dom = amd_iommu_rlookup_table[devid]->default_dom; |
1832 | attach_device(dev, &dma_dom->domain); | 1829 | attach_device(dev, &dma_dom->domain); |
1833 | DUMP_printk("Using protection domain %d for device %s\n", | 1830 | DUMP_printk("Using protection domain %d for device %s\n", |
1834 | dma_dom->domain.id, dev_name(dev)); | 1831 | dma_dom->domain.id, dev_name(dev)); |
1835 | 1832 | ||
1836 | return &dma_dom->domain; | 1833 | return &dma_dom->domain; |
1837 | } | 1834 | } |
1838 | 1835 | ||
1839 | static void update_device_table(struct protection_domain *domain) | 1836 | static void update_device_table(struct protection_domain *domain) |
1840 | { | 1837 | { |
1841 | struct iommu_dev_data *dev_data; | 1838 | struct iommu_dev_data *dev_data; |
1842 | 1839 | ||
1843 | list_for_each_entry(dev_data, &domain->dev_list, list) { | 1840 | list_for_each_entry(dev_data, &domain->dev_list, list) { |
1844 | struct pci_dev *pdev = to_pci_dev(dev_data->dev); | 1841 | struct pci_dev *pdev = to_pci_dev(dev_data->dev); |
1845 | u16 devid = get_device_id(dev_data->dev); | 1842 | u16 devid = get_device_id(dev_data->dev); |
1846 | set_dte_entry(devid, domain, pci_ats_enabled(pdev)); | 1843 | set_dte_entry(devid, domain, pci_ats_enabled(pdev)); |
1847 | } | 1844 | } |
1848 | } | 1845 | } |
1849 | 1846 | ||
1850 | static void update_domain(struct protection_domain *domain) | 1847 | static void update_domain(struct protection_domain *domain) |
1851 | { | 1848 | { |
1852 | if (!domain->updated) | 1849 | if (!domain->updated) |
1853 | return; | 1850 | return; |
1854 | 1851 | ||
1855 | update_device_table(domain); | 1852 | update_device_table(domain); |
1856 | 1853 | ||
1857 | domain_flush_devices(domain); | 1854 | domain_flush_devices(domain); |
1858 | domain_flush_tlb_pde(domain); | 1855 | domain_flush_tlb_pde(domain); |
1859 | 1856 | ||
1860 | domain->updated = false; | 1857 | domain->updated = false; |
1861 | } | 1858 | } |
1862 | 1859 | ||
1863 | /* | 1860 | /* |
1864 | * This function fetches the PTE for a given address in the aperture | 1861 | * This function fetches the PTE for a given address in the aperture |
1865 | */ | 1862 | */ |
1866 | static u64* dma_ops_get_pte(struct dma_ops_domain *dom, | 1863 | static u64* dma_ops_get_pte(struct dma_ops_domain *dom, |
1867 | unsigned long address) | 1864 | unsigned long address) |
1868 | { | 1865 | { |
1869 | struct aperture_range *aperture; | 1866 | struct aperture_range *aperture; |
1870 | u64 *pte, *pte_page; | 1867 | u64 *pte, *pte_page; |
1871 | 1868 | ||
1872 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; | 1869 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; |
1873 | if (!aperture) | 1870 | if (!aperture) |
1874 | return NULL; | 1871 | return NULL; |
1875 | 1872 | ||
1876 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; | 1873 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; |
1877 | if (!pte) { | 1874 | if (!pte) { |
1878 | pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page, | 1875 | pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page, |
1879 | GFP_ATOMIC); | 1876 | GFP_ATOMIC); |
1880 | aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page; | 1877 | aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page; |
1881 | } else | 1878 | } else |
1882 | pte += PM_LEVEL_INDEX(0, address); | 1879 | pte += PM_LEVEL_INDEX(0, address); |
1883 | 1880 | ||
1884 | update_domain(&dom->domain); | 1881 | update_domain(&dom->domain); |
1885 | 1882 | ||
1886 | return pte; | 1883 | return pte; |
1887 | } | 1884 | } |
1888 | 1885 | ||
1889 | /* | 1886 | /* |
1890 | * This is the generic map function. It maps one 4kb page at paddr to | 1887 | * This is the generic map function. It maps one 4kb page at paddr to |
1891 | * the given address in the DMA address space for the domain. | 1888 | * the given address in the DMA address space for the domain. |
1892 | */ | 1889 | */ |
1893 | static dma_addr_t dma_ops_domain_map(struct dma_ops_domain *dom, | 1890 | static dma_addr_t dma_ops_domain_map(struct dma_ops_domain *dom, |
1894 | unsigned long address, | 1891 | unsigned long address, |
1895 | phys_addr_t paddr, | 1892 | phys_addr_t paddr, |
1896 | int direction) | 1893 | int direction) |
1897 | { | 1894 | { |
1898 | u64 *pte, __pte; | 1895 | u64 *pte, __pte; |
1899 | 1896 | ||
1900 | WARN_ON(address > dom->aperture_size); | 1897 | WARN_ON(address > dom->aperture_size); |
1901 | 1898 | ||
1902 | paddr &= PAGE_MASK; | 1899 | paddr &= PAGE_MASK; |
1903 | 1900 | ||
1904 | pte = dma_ops_get_pte(dom, address); | 1901 | pte = dma_ops_get_pte(dom, address); |
1905 | if (!pte) | 1902 | if (!pte) |
1906 | return DMA_ERROR_CODE; | 1903 | return DMA_ERROR_CODE; |
1907 | 1904 | ||
1908 | __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; | 1905 | __pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; |
1909 | 1906 | ||
1910 | if (direction == DMA_TO_DEVICE) | 1907 | if (direction == DMA_TO_DEVICE) |
1911 | __pte |= IOMMU_PTE_IR; | 1908 | __pte |= IOMMU_PTE_IR; |
1912 | else if (direction == DMA_FROM_DEVICE) | 1909 | else if (direction == DMA_FROM_DEVICE) |
1913 | __pte |= IOMMU_PTE_IW; | 1910 | __pte |= IOMMU_PTE_IW; |
1914 | else if (direction == DMA_BIDIRECTIONAL) | 1911 | else if (direction == DMA_BIDIRECTIONAL) |
1915 | __pte |= IOMMU_PTE_IR | IOMMU_PTE_IW; | 1912 | __pte |= IOMMU_PTE_IR | IOMMU_PTE_IW; |
1916 | 1913 | ||
1917 | WARN_ON(*pte); | 1914 | WARN_ON(*pte); |
1918 | 1915 | ||
1919 | *pte = __pte; | 1916 | *pte = __pte; |
1920 | 1917 | ||
1921 | return (dma_addr_t)address; | 1918 | return (dma_addr_t)address; |
1922 | } | 1919 | } |
1923 | 1920 | ||
1924 | /* | 1921 | /* |
1925 | * The generic unmapping function for on page in the DMA address space. | 1922 | * The generic unmapping function for on page in the DMA address space. |
1926 | */ | 1923 | */ |
1927 | static void dma_ops_domain_unmap(struct dma_ops_domain *dom, | 1924 | static void dma_ops_domain_unmap(struct dma_ops_domain *dom, |
1928 | unsigned long address) | 1925 | unsigned long address) |
1929 | { | 1926 | { |
1930 | struct aperture_range *aperture; | 1927 | struct aperture_range *aperture; |
1931 | u64 *pte; | 1928 | u64 *pte; |
1932 | 1929 | ||
1933 | if (address >= dom->aperture_size) | 1930 | if (address >= dom->aperture_size) |
1934 | return; | 1931 | return; |
1935 | 1932 | ||
1936 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; | 1933 | aperture = dom->aperture[APERTURE_RANGE_INDEX(address)]; |
1937 | if (!aperture) | 1934 | if (!aperture) |
1938 | return; | 1935 | return; |
1939 | 1936 | ||
1940 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; | 1937 | pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; |
1941 | if (!pte) | 1938 | if (!pte) |
1942 | return; | 1939 | return; |
1943 | 1940 | ||
1944 | pte += PM_LEVEL_INDEX(0, address); | 1941 | pte += PM_LEVEL_INDEX(0, address); |
1945 | 1942 | ||
1946 | WARN_ON(!*pte); | 1943 | WARN_ON(!*pte); |
1947 | 1944 | ||
1948 | *pte = 0ULL; | 1945 | *pte = 0ULL; |
1949 | } | 1946 | } |
1950 | 1947 | ||
1951 | /* | 1948 | /* |
1952 | * This function contains common code for mapping of a physically | 1949 | * This function contains common code for mapping of a physically |
1953 | * contiguous memory region into DMA address space. It is used by all | 1950 | * contiguous memory region into DMA address space. It is used by all |
1954 | * mapping functions provided with this IOMMU driver. | 1951 | * mapping functions provided with this IOMMU driver. |
1955 | * Must be called with the domain lock held. | 1952 | * Must be called with the domain lock held. |
1956 | */ | 1953 | */ |
1957 | static dma_addr_t __map_single(struct device *dev, | 1954 | static dma_addr_t __map_single(struct device *dev, |
1958 | struct dma_ops_domain *dma_dom, | 1955 | struct dma_ops_domain *dma_dom, |
1959 | phys_addr_t paddr, | 1956 | phys_addr_t paddr, |
1960 | size_t size, | 1957 | size_t size, |
1961 | int dir, | 1958 | int dir, |
1962 | bool align, | 1959 | bool align, |
1963 | u64 dma_mask) | 1960 | u64 dma_mask) |
1964 | { | 1961 | { |
1965 | dma_addr_t offset = paddr & ~PAGE_MASK; | 1962 | dma_addr_t offset = paddr & ~PAGE_MASK; |
1966 | dma_addr_t address, start, ret; | 1963 | dma_addr_t address, start, ret; |
1967 | unsigned int pages; | 1964 | unsigned int pages; |
1968 | unsigned long align_mask = 0; | 1965 | unsigned long align_mask = 0; |
1969 | int i; | 1966 | int i; |
1970 | 1967 | ||
1971 | pages = iommu_num_pages(paddr, size, PAGE_SIZE); | 1968 | pages = iommu_num_pages(paddr, size, PAGE_SIZE); |
1972 | paddr &= PAGE_MASK; | 1969 | paddr &= PAGE_MASK; |
1973 | 1970 | ||
1974 | INC_STATS_COUNTER(total_map_requests); | 1971 | INC_STATS_COUNTER(total_map_requests); |
1975 | 1972 | ||
1976 | if (pages > 1) | 1973 | if (pages > 1) |
1977 | INC_STATS_COUNTER(cross_page); | 1974 | INC_STATS_COUNTER(cross_page); |
1978 | 1975 | ||
1979 | if (align) | 1976 | if (align) |
1980 | align_mask = (1UL << get_order(size)) - 1; | 1977 | align_mask = (1UL << get_order(size)) - 1; |
1981 | 1978 | ||
1982 | retry: | 1979 | retry: |
1983 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, | 1980 | address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask, |
1984 | dma_mask); | 1981 | dma_mask); |
1985 | if (unlikely(address == DMA_ERROR_CODE)) { | 1982 | if (unlikely(address == DMA_ERROR_CODE)) { |
1986 | /* | 1983 | /* |
1987 | * setting next_address here will let the address | 1984 | * setting next_address here will let the address |
1988 | * allocator only scan the new allocated range in the | 1985 | * allocator only scan the new allocated range in the |
1989 | * first run. This is a small optimization. | 1986 | * first run. This is a small optimization. |
1990 | */ | 1987 | */ |
1991 | dma_dom->next_address = dma_dom->aperture_size; | 1988 | dma_dom->next_address = dma_dom->aperture_size; |
1992 | 1989 | ||
1993 | if (alloc_new_range(dma_dom, false, GFP_ATOMIC)) | 1990 | if (alloc_new_range(dma_dom, false, GFP_ATOMIC)) |
1994 | goto out; | 1991 | goto out; |
1995 | 1992 | ||
1996 | /* | 1993 | /* |
1997 | * aperture was successfully enlarged by 128 MB, try | 1994 | * aperture was successfully enlarged by 128 MB, try |
1998 | * allocation again | 1995 | * allocation again |
1999 | */ | 1996 | */ |
2000 | goto retry; | 1997 | goto retry; |
2001 | } | 1998 | } |
2002 | 1999 | ||
2003 | start = address; | 2000 | start = address; |
2004 | for (i = 0; i < pages; ++i) { | 2001 | for (i = 0; i < pages; ++i) { |
2005 | ret = dma_ops_domain_map(dma_dom, start, paddr, dir); | 2002 | ret = dma_ops_domain_map(dma_dom, start, paddr, dir); |
2006 | if (ret == DMA_ERROR_CODE) | 2003 | if (ret == DMA_ERROR_CODE) |
2007 | goto out_unmap; | 2004 | goto out_unmap; |
2008 | 2005 | ||
2009 | paddr += PAGE_SIZE; | 2006 | paddr += PAGE_SIZE; |
2010 | start += PAGE_SIZE; | 2007 | start += PAGE_SIZE; |
2011 | } | 2008 | } |
2012 | address += offset; | 2009 | address += offset; |
2013 | 2010 | ||
2014 | ADD_STATS_COUNTER(alloced_io_mem, size); | 2011 | ADD_STATS_COUNTER(alloced_io_mem, size); |
2015 | 2012 | ||
2016 | if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) { | 2013 | if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) { |
2017 | domain_flush_tlb(&dma_dom->domain); | 2014 | domain_flush_tlb(&dma_dom->domain); |
2018 | dma_dom->need_flush = false; | 2015 | dma_dom->need_flush = false; |
2019 | } else if (unlikely(amd_iommu_np_cache)) | 2016 | } else if (unlikely(amd_iommu_np_cache)) |
2020 | domain_flush_pages(&dma_dom->domain, address, size); | 2017 | domain_flush_pages(&dma_dom->domain, address, size); |
2021 | 2018 | ||
2022 | out: | 2019 | out: |
2023 | return address; | 2020 | return address; |
2024 | 2021 | ||
2025 | out_unmap: | 2022 | out_unmap: |
2026 | 2023 | ||
2027 | for (--i; i >= 0; --i) { | 2024 | for (--i; i >= 0; --i) { |
2028 | start -= PAGE_SIZE; | 2025 | start -= PAGE_SIZE; |
2029 | dma_ops_domain_unmap(dma_dom, start); | 2026 | dma_ops_domain_unmap(dma_dom, start); |
2030 | } | 2027 | } |
2031 | 2028 | ||
2032 | dma_ops_free_addresses(dma_dom, address, pages); | 2029 | dma_ops_free_addresses(dma_dom, address, pages); |
2033 | 2030 | ||
2034 | return DMA_ERROR_CODE; | 2031 | return DMA_ERROR_CODE; |
2035 | } | 2032 | } |
2036 | 2033 | ||
2037 | /* | 2034 | /* |
2038 | * Does the reverse of the __map_single function. Must be called with | 2035 | * Does the reverse of the __map_single function. Must be called with |
2039 | * the domain lock held too | 2036 | * the domain lock held too |
2040 | */ | 2037 | */ |
2041 | static void __unmap_single(struct dma_ops_domain *dma_dom, | 2038 | static void __unmap_single(struct dma_ops_domain *dma_dom, |
2042 | dma_addr_t dma_addr, | 2039 | dma_addr_t dma_addr, |
2043 | size_t size, | 2040 | size_t size, |
2044 | int dir) | 2041 | int dir) |
2045 | { | 2042 | { |
2046 | dma_addr_t flush_addr; | 2043 | dma_addr_t flush_addr; |
2047 | dma_addr_t i, start; | 2044 | dma_addr_t i, start; |
2048 | unsigned int pages; | 2045 | unsigned int pages; |
2049 | 2046 | ||
2050 | if ((dma_addr == DMA_ERROR_CODE) || | 2047 | if ((dma_addr == DMA_ERROR_CODE) || |
2051 | (dma_addr + size > dma_dom->aperture_size)) | 2048 | (dma_addr + size > dma_dom->aperture_size)) |
2052 | return; | 2049 | return; |
2053 | 2050 | ||
2054 | flush_addr = dma_addr; | 2051 | flush_addr = dma_addr; |
2055 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); | 2052 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); |
2056 | dma_addr &= PAGE_MASK; | 2053 | dma_addr &= PAGE_MASK; |
2057 | start = dma_addr; | 2054 | start = dma_addr; |
2058 | 2055 | ||
2059 | for (i = 0; i < pages; ++i) { | 2056 | for (i = 0; i < pages; ++i) { |
2060 | dma_ops_domain_unmap(dma_dom, start); | 2057 | dma_ops_domain_unmap(dma_dom, start); |
2061 | start += PAGE_SIZE; | 2058 | start += PAGE_SIZE; |
2062 | } | 2059 | } |
2063 | 2060 | ||
2064 | SUB_STATS_COUNTER(alloced_io_mem, size); | 2061 | SUB_STATS_COUNTER(alloced_io_mem, size); |
2065 | 2062 | ||
2066 | dma_ops_free_addresses(dma_dom, dma_addr, pages); | 2063 | dma_ops_free_addresses(dma_dom, dma_addr, pages); |
2067 | 2064 | ||
2068 | if (amd_iommu_unmap_flush || dma_dom->need_flush) { | 2065 | if (amd_iommu_unmap_flush || dma_dom->need_flush) { |
2069 | domain_flush_pages(&dma_dom->domain, flush_addr, size); | 2066 | domain_flush_pages(&dma_dom->domain, flush_addr, size); |
2070 | dma_dom->need_flush = false; | 2067 | dma_dom->need_flush = false; |
2071 | } | 2068 | } |
2072 | } | 2069 | } |
2073 | 2070 | ||
2074 | /* | 2071 | /* |
2075 | * The exported map_single function for dma_ops. | 2072 | * The exported map_single function for dma_ops. |
2076 | */ | 2073 | */ |
2077 | static dma_addr_t map_page(struct device *dev, struct page *page, | 2074 | static dma_addr_t map_page(struct device *dev, struct page *page, |
2078 | unsigned long offset, size_t size, | 2075 | unsigned long offset, size_t size, |
2079 | enum dma_data_direction dir, | 2076 | enum dma_data_direction dir, |
2080 | struct dma_attrs *attrs) | 2077 | struct dma_attrs *attrs) |
2081 | { | 2078 | { |
2082 | unsigned long flags; | 2079 | unsigned long flags; |
2083 | struct protection_domain *domain; | 2080 | struct protection_domain *domain; |
2084 | dma_addr_t addr; | 2081 | dma_addr_t addr; |
2085 | u64 dma_mask; | 2082 | u64 dma_mask; |
2086 | phys_addr_t paddr = page_to_phys(page) + offset; | 2083 | phys_addr_t paddr = page_to_phys(page) + offset; |
2087 | 2084 | ||
2088 | INC_STATS_COUNTER(cnt_map_single); | 2085 | INC_STATS_COUNTER(cnt_map_single); |
2089 | 2086 | ||
2090 | domain = get_domain(dev); | 2087 | domain = get_domain(dev); |
2091 | if (PTR_ERR(domain) == -EINVAL) | 2088 | if (PTR_ERR(domain) == -EINVAL) |
2092 | return (dma_addr_t)paddr; | 2089 | return (dma_addr_t)paddr; |
2093 | else if (IS_ERR(domain)) | 2090 | else if (IS_ERR(domain)) |
2094 | return DMA_ERROR_CODE; | 2091 | return DMA_ERROR_CODE; |
2095 | 2092 | ||
2096 | dma_mask = *dev->dma_mask; | 2093 | dma_mask = *dev->dma_mask; |
2097 | 2094 | ||
2098 | spin_lock_irqsave(&domain->lock, flags); | 2095 | spin_lock_irqsave(&domain->lock, flags); |
2099 | 2096 | ||
2100 | addr = __map_single(dev, domain->priv, paddr, size, dir, false, | 2097 | addr = __map_single(dev, domain->priv, paddr, size, dir, false, |
2101 | dma_mask); | 2098 | dma_mask); |
2102 | if (addr == DMA_ERROR_CODE) | 2099 | if (addr == DMA_ERROR_CODE) |
2103 | goto out; | 2100 | goto out; |
2104 | 2101 | ||
2105 | domain_flush_complete(domain); | 2102 | domain_flush_complete(domain); |
2106 | 2103 | ||
2107 | out: | 2104 | out: |
2108 | spin_unlock_irqrestore(&domain->lock, flags); | 2105 | spin_unlock_irqrestore(&domain->lock, flags); |
2109 | 2106 | ||
2110 | return addr; | 2107 | return addr; |
2111 | } | 2108 | } |
2112 | 2109 | ||
2113 | /* | 2110 | /* |
2114 | * The exported unmap_single function for dma_ops. | 2111 | * The exported unmap_single function for dma_ops. |
2115 | */ | 2112 | */ |
2116 | static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | 2113 | static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, |
2117 | enum dma_data_direction dir, struct dma_attrs *attrs) | 2114 | enum dma_data_direction dir, struct dma_attrs *attrs) |
2118 | { | 2115 | { |
2119 | unsigned long flags; | 2116 | unsigned long flags; |
2120 | struct protection_domain *domain; | 2117 | struct protection_domain *domain; |
2121 | 2118 | ||
2122 | INC_STATS_COUNTER(cnt_unmap_single); | 2119 | INC_STATS_COUNTER(cnt_unmap_single); |
2123 | 2120 | ||
2124 | domain = get_domain(dev); | 2121 | domain = get_domain(dev); |
2125 | if (IS_ERR(domain)) | 2122 | if (IS_ERR(domain)) |
2126 | return; | 2123 | return; |
2127 | 2124 | ||
2128 | spin_lock_irqsave(&domain->lock, flags); | 2125 | spin_lock_irqsave(&domain->lock, flags); |
2129 | 2126 | ||
2130 | __unmap_single(domain->priv, dma_addr, size, dir); | 2127 | __unmap_single(domain->priv, dma_addr, size, dir); |
2131 | 2128 | ||
2132 | domain_flush_complete(domain); | 2129 | domain_flush_complete(domain); |
2133 | 2130 | ||
2134 | spin_unlock_irqrestore(&domain->lock, flags); | 2131 | spin_unlock_irqrestore(&domain->lock, flags); |
2135 | } | 2132 | } |
2136 | 2133 | ||
2137 | /* | 2134 | /* |
2138 | * This is a special map_sg function which is used if we should map a | 2135 | * This is a special map_sg function which is used if we should map a |
2139 | * device which is not handled by an AMD IOMMU in the system. | 2136 | * device which is not handled by an AMD IOMMU in the system. |
2140 | */ | 2137 | */ |
2141 | static int map_sg_no_iommu(struct device *dev, struct scatterlist *sglist, | 2138 | static int map_sg_no_iommu(struct device *dev, struct scatterlist *sglist, |
2142 | int nelems, int dir) | 2139 | int nelems, int dir) |
2143 | { | 2140 | { |
2144 | struct scatterlist *s; | 2141 | struct scatterlist *s; |
2145 | int i; | 2142 | int i; |
2146 | 2143 | ||
2147 | for_each_sg(sglist, s, nelems, i) { | 2144 | for_each_sg(sglist, s, nelems, i) { |
2148 | s->dma_address = (dma_addr_t)sg_phys(s); | 2145 | s->dma_address = (dma_addr_t)sg_phys(s); |
2149 | s->dma_length = s->length; | 2146 | s->dma_length = s->length; |
2150 | } | 2147 | } |
2151 | 2148 | ||
2152 | return nelems; | 2149 | return nelems; |
2153 | } | 2150 | } |
2154 | 2151 | ||
2155 | /* | 2152 | /* |
2156 | * The exported map_sg function for dma_ops (handles scatter-gather | 2153 | * The exported map_sg function for dma_ops (handles scatter-gather |
2157 | * lists). | 2154 | * lists). |
2158 | */ | 2155 | */ |
2159 | static int map_sg(struct device *dev, struct scatterlist *sglist, | 2156 | static int map_sg(struct device *dev, struct scatterlist *sglist, |
2160 | int nelems, enum dma_data_direction dir, | 2157 | int nelems, enum dma_data_direction dir, |
2161 | struct dma_attrs *attrs) | 2158 | struct dma_attrs *attrs) |
2162 | { | 2159 | { |
2163 | unsigned long flags; | 2160 | unsigned long flags; |
2164 | struct protection_domain *domain; | 2161 | struct protection_domain *domain; |
2165 | int i; | 2162 | int i; |
2166 | struct scatterlist *s; | 2163 | struct scatterlist *s; |
2167 | phys_addr_t paddr; | 2164 | phys_addr_t paddr; |
2168 | int mapped_elems = 0; | 2165 | int mapped_elems = 0; |
2169 | u64 dma_mask; | 2166 | u64 dma_mask; |
2170 | 2167 | ||
2171 | INC_STATS_COUNTER(cnt_map_sg); | 2168 | INC_STATS_COUNTER(cnt_map_sg); |
2172 | 2169 | ||
2173 | domain = get_domain(dev); | 2170 | domain = get_domain(dev); |
2174 | if (PTR_ERR(domain) == -EINVAL) | 2171 | if (PTR_ERR(domain) == -EINVAL) |
2175 | return map_sg_no_iommu(dev, sglist, nelems, dir); | 2172 | return map_sg_no_iommu(dev, sglist, nelems, dir); |
2176 | else if (IS_ERR(domain)) | 2173 | else if (IS_ERR(domain)) |
2177 | return 0; | 2174 | return 0; |
2178 | 2175 | ||
2179 | dma_mask = *dev->dma_mask; | 2176 | dma_mask = *dev->dma_mask; |
2180 | 2177 | ||
2181 | spin_lock_irqsave(&domain->lock, flags); | 2178 | spin_lock_irqsave(&domain->lock, flags); |
2182 | 2179 | ||
2183 | for_each_sg(sglist, s, nelems, i) { | 2180 | for_each_sg(sglist, s, nelems, i) { |
2184 | paddr = sg_phys(s); | 2181 | paddr = sg_phys(s); |
2185 | 2182 | ||
2186 | s->dma_address = __map_single(dev, domain->priv, | 2183 | s->dma_address = __map_single(dev, domain->priv, |
2187 | paddr, s->length, dir, false, | 2184 | paddr, s->length, dir, false, |
2188 | dma_mask); | 2185 | dma_mask); |
2189 | 2186 | ||
2190 | if (s->dma_address) { | 2187 | if (s->dma_address) { |
2191 | s->dma_length = s->length; | 2188 | s->dma_length = s->length; |
2192 | mapped_elems++; | 2189 | mapped_elems++; |
2193 | } else | 2190 | } else |
2194 | goto unmap; | 2191 | goto unmap; |
2195 | } | 2192 | } |
2196 | 2193 | ||
2197 | domain_flush_complete(domain); | 2194 | domain_flush_complete(domain); |
2198 | 2195 | ||
2199 | out: | 2196 | out: |
2200 | spin_unlock_irqrestore(&domain->lock, flags); | 2197 | spin_unlock_irqrestore(&domain->lock, flags); |
2201 | 2198 | ||
2202 | return mapped_elems; | 2199 | return mapped_elems; |
2203 | unmap: | 2200 | unmap: |
2204 | for_each_sg(sglist, s, mapped_elems, i) { | 2201 | for_each_sg(sglist, s, mapped_elems, i) { |
2205 | if (s->dma_address) | 2202 | if (s->dma_address) |
2206 | __unmap_single(domain->priv, s->dma_address, | 2203 | __unmap_single(domain->priv, s->dma_address, |
2207 | s->dma_length, dir); | 2204 | s->dma_length, dir); |
2208 | s->dma_address = s->dma_length = 0; | 2205 | s->dma_address = s->dma_length = 0; |
2209 | } | 2206 | } |
2210 | 2207 | ||
2211 | mapped_elems = 0; | 2208 | mapped_elems = 0; |
2212 | 2209 | ||
2213 | goto out; | 2210 | goto out; |
2214 | } | 2211 | } |
2215 | 2212 | ||
2216 | /* | 2213 | /* |
2217 | * The exported map_sg function for dma_ops (handles scatter-gather | 2214 | * The exported map_sg function for dma_ops (handles scatter-gather |
2218 | * lists). | 2215 | * lists). |
2219 | */ | 2216 | */ |
2220 | static void unmap_sg(struct device *dev, struct scatterlist *sglist, | 2217 | static void unmap_sg(struct device *dev, struct scatterlist *sglist, |
2221 | int nelems, enum dma_data_direction dir, | 2218 | int nelems, enum dma_data_direction dir, |
2222 | struct dma_attrs *attrs) | 2219 | struct dma_attrs *attrs) |
2223 | { | 2220 | { |
2224 | unsigned long flags; | 2221 | unsigned long flags; |
2225 | struct protection_domain *domain; | 2222 | struct protection_domain *domain; |
2226 | struct scatterlist *s; | 2223 | struct scatterlist *s; |
2227 | int i; | 2224 | int i; |
2228 | 2225 | ||
2229 | INC_STATS_COUNTER(cnt_unmap_sg); | 2226 | INC_STATS_COUNTER(cnt_unmap_sg); |
2230 | 2227 | ||
2231 | domain = get_domain(dev); | 2228 | domain = get_domain(dev); |
2232 | if (IS_ERR(domain)) | 2229 | if (IS_ERR(domain)) |
2233 | return; | 2230 | return; |
2234 | 2231 | ||
2235 | spin_lock_irqsave(&domain->lock, flags); | 2232 | spin_lock_irqsave(&domain->lock, flags); |
2236 | 2233 | ||
2237 | for_each_sg(sglist, s, nelems, i) { | 2234 | for_each_sg(sglist, s, nelems, i) { |
2238 | __unmap_single(domain->priv, s->dma_address, | 2235 | __unmap_single(domain->priv, s->dma_address, |
2239 | s->dma_length, dir); | 2236 | s->dma_length, dir); |
2240 | s->dma_address = s->dma_length = 0; | 2237 | s->dma_address = s->dma_length = 0; |
2241 | } | 2238 | } |
2242 | 2239 | ||
2243 | domain_flush_complete(domain); | 2240 | domain_flush_complete(domain); |
2244 | 2241 | ||
2245 | spin_unlock_irqrestore(&domain->lock, flags); | 2242 | spin_unlock_irqrestore(&domain->lock, flags); |
2246 | } | 2243 | } |
2247 | 2244 | ||
2248 | /* | 2245 | /* |
2249 | * The exported alloc_coherent function for dma_ops. | 2246 | * The exported alloc_coherent function for dma_ops. |
2250 | */ | 2247 | */ |
2251 | static void *alloc_coherent(struct device *dev, size_t size, | 2248 | static void *alloc_coherent(struct device *dev, size_t size, |
2252 | dma_addr_t *dma_addr, gfp_t flag) | 2249 | dma_addr_t *dma_addr, gfp_t flag) |
2253 | { | 2250 | { |
2254 | unsigned long flags; | 2251 | unsigned long flags; |
2255 | void *virt_addr; | 2252 | void *virt_addr; |
2256 | struct protection_domain *domain; | 2253 | struct protection_domain *domain; |
2257 | phys_addr_t paddr; | 2254 | phys_addr_t paddr; |
2258 | u64 dma_mask = dev->coherent_dma_mask; | 2255 | u64 dma_mask = dev->coherent_dma_mask; |
2259 | 2256 | ||
2260 | INC_STATS_COUNTER(cnt_alloc_coherent); | 2257 | INC_STATS_COUNTER(cnt_alloc_coherent); |
2261 | 2258 | ||
2262 | domain = get_domain(dev); | 2259 | domain = get_domain(dev); |
2263 | if (PTR_ERR(domain) == -EINVAL) { | 2260 | if (PTR_ERR(domain) == -EINVAL) { |
2264 | virt_addr = (void *)__get_free_pages(flag, get_order(size)); | 2261 | virt_addr = (void *)__get_free_pages(flag, get_order(size)); |
2265 | *dma_addr = __pa(virt_addr); | 2262 | *dma_addr = __pa(virt_addr); |
2266 | return virt_addr; | 2263 | return virt_addr; |
2267 | } else if (IS_ERR(domain)) | 2264 | } else if (IS_ERR(domain)) |
2268 | return NULL; | 2265 | return NULL; |
2269 | 2266 | ||
2270 | dma_mask = dev->coherent_dma_mask; | 2267 | dma_mask = dev->coherent_dma_mask; |
2271 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); | 2268 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); |
2272 | flag |= __GFP_ZERO; | 2269 | flag |= __GFP_ZERO; |
2273 | 2270 | ||
2274 | virt_addr = (void *)__get_free_pages(flag, get_order(size)); | 2271 | virt_addr = (void *)__get_free_pages(flag, get_order(size)); |
2275 | if (!virt_addr) | 2272 | if (!virt_addr) |
2276 | return NULL; | 2273 | return NULL; |
2277 | 2274 | ||
2278 | paddr = virt_to_phys(virt_addr); | 2275 | paddr = virt_to_phys(virt_addr); |
2279 | 2276 | ||
2280 | if (!dma_mask) | 2277 | if (!dma_mask) |
2281 | dma_mask = *dev->dma_mask; | 2278 | dma_mask = *dev->dma_mask; |
2282 | 2279 | ||
2283 | spin_lock_irqsave(&domain->lock, flags); | 2280 | spin_lock_irqsave(&domain->lock, flags); |
2284 | 2281 | ||
2285 | *dma_addr = __map_single(dev, domain->priv, paddr, | 2282 | *dma_addr = __map_single(dev, domain->priv, paddr, |
2286 | size, DMA_BIDIRECTIONAL, true, dma_mask); | 2283 | size, DMA_BIDIRECTIONAL, true, dma_mask); |
2287 | 2284 | ||
2288 | if (*dma_addr == DMA_ERROR_CODE) { | 2285 | if (*dma_addr == DMA_ERROR_CODE) { |
2289 | spin_unlock_irqrestore(&domain->lock, flags); | 2286 | spin_unlock_irqrestore(&domain->lock, flags); |
2290 | goto out_free; | 2287 | goto out_free; |
2291 | } | 2288 | } |
2292 | 2289 | ||
2293 | domain_flush_complete(domain); | 2290 | domain_flush_complete(domain); |
2294 | 2291 | ||
2295 | spin_unlock_irqrestore(&domain->lock, flags); | 2292 | spin_unlock_irqrestore(&domain->lock, flags); |
2296 | 2293 | ||
2297 | return virt_addr; | 2294 | return virt_addr; |
2298 | 2295 | ||
2299 | out_free: | 2296 | out_free: |
2300 | 2297 | ||
2301 | free_pages((unsigned long)virt_addr, get_order(size)); | 2298 | free_pages((unsigned long)virt_addr, get_order(size)); |
2302 | 2299 | ||
2303 | return NULL; | 2300 | return NULL; |
2304 | } | 2301 | } |
2305 | 2302 | ||
2306 | /* | 2303 | /* |
2307 | * The exported free_coherent function for dma_ops. | 2304 | * The exported free_coherent function for dma_ops. |
2308 | */ | 2305 | */ |
2309 | static void free_coherent(struct device *dev, size_t size, | 2306 | static void free_coherent(struct device *dev, size_t size, |
2310 | void *virt_addr, dma_addr_t dma_addr) | 2307 | void *virt_addr, dma_addr_t dma_addr) |
2311 | { | 2308 | { |
2312 | unsigned long flags; | 2309 | unsigned long flags; |
2313 | struct protection_domain *domain; | 2310 | struct protection_domain *domain; |
2314 | 2311 | ||
2315 | INC_STATS_COUNTER(cnt_free_coherent); | 2312 | INC_STATS_COUNTER(cnt_free_coherent); |
2316 | 2313 | ||
2317 | domain = get_domain(dev); | 2314 | domain = get_domain(dev); |
2318 | if (IS_ERR(domain)) | 2315 | if (IS_ERR(domain)) |
2319 | goto free_mem; | 2316 | goto free_mem; |
2320 | 2317 | ||
2321 | spin_lock_irqsave(&domain->lock, flags); | 2318 | spin_lock_irqsave(&domain->lock, flags); |
2322 | 2319 | ||
2323 | __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); | 2320 | __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); |
2324 | 2321 | ||
2325 | domain_flush_complete(domain); | 2322 | domain_flush_complete(domain); |
2326 | 2323 | ||
2327 | spin_unlock_irqrestore(&domain->lock, flags); | 2324 | spin_unlock_irqrestore(&domain->lock, flags); |
2328 | 2325 | ||
2329 | free_mem: | 2326 | free_mem: |
2330 | free_pages((unsigned long)virt_addr, get_order(size)); | 2327 | free_pages((unsigned long)virt_addr, get_order(size)); |
2331 | } | 2328 | } |
2332 | 2329 | ||
2333 | /* | 2330 | /* |
2334 | * This function is called by the DMA layer to find out if we can handle a | 2331 | * This function is called by the DMA layer to find out if we can handle a |
2335 | * particular device. It is part of the dma_ops. | 2332 | * particular device. It is part of the dma_ops. |
2336 | */ | 2333 | */ |
2337 | static int amd_iommu_dma_supported(struct device *dev, u64 mask) | 2334 | static int amd_iommu_dma_supported(struct device *dev, u64 mask) |
2338 | { | 2335 | { |
2339 | return check_device(dev); | 2336 | return check_device(dev); |
2340 | } | 2337 | } |
2341 | 2338 | ||
2342 | /* | 2339 | /* |
2343 | * The function for pre-allocating protection domains. | 2340 | * The function for pre-allocating protection domains. |
2344 | * | 2341 | * |
2345 | * If the driver core informs the DMA layer if a driver grabs a device | 2342 | * If the driver core informs the DMA layer if a driver grabs a device |
2346 | * we don't need to preallocate the protection domains anymore. | 2343 | * we don't need to preallocate the protection domains anymore. |
2347 | * For now we have to. | 2344 | * For now we have to. |
2348 | */ | 2345 | */ |
2349 | static void prealloc_protection_domains(void) | 2346 | static void prealloc_protection_domains(void) |
2350 | { | 2347 | { |
2351 | struct pci_dev *dev = NULL; | 2348 | struct pci_dev *dev = NULL; |
2352 | struct dma_ops_domain *dma_dom; | 2349 | struct dma_ops_domain *dma_dom; |
2353 | u16 devid; | 2350 | u16 devid; |
2354 | 2351 | ||
2355 | for_each_pci_dev(dev) { | 2352 | for_each_pci_dev(dev) { |
2356 | 2353 | ||
2357 | /* Do we handle this device? */ | 2354 | /* Do we handle this device? */ |
2358 | if (!check_device(&dev->dev)) | 2355 | if (!check_device(&dev->dev)) |
2359 | continue; | 2356 | continue; |
2360 | 2357 | ||
2361 | /* Is there already any domain for it? */ | 2358 | /* Is there already any domain for it? */ |
2362 | if (domain_for_device(&dev->dev)) | 2359 | if (domain_for_device(&dev->dev)) |
2363 | continue; | 2360 | continue; |
2364 | 2361 | ||
2365 | devid = get_device_id(&dev->dev); | 2362 | devid = get_device_id(&dev->dev); |
2366 | 2363 | ||
2367 | dma_dom = dma_ops_domain_alloc(); | 2364 | dma_dom = dma_ops_domain_alloc(); |
2368 | if (!dma_dom) | 2365 | if (!dma_dom) |
2369 | continue; | 2366 | continue; |
2370 | init_unity_mappings_for_device(dma_dom, devid); | 2367 | init_unity_mappings_for_device(dma_dom, devid); |
2371 | dma_dom->target_dev = devid; | 2368 | dma_dom->target_dev = devid; |
2372 | 2369 | ||
2373 | attach_device(&dev->dev, &dma_dom->domain); | 2370 | attach_device(&dev->dev, &dma_dom->domain); |
2374 | 2371 | ||
2375 | list_add_tail(&dma_dom->list, &iommu_pd_list); | 2372 | list_add_tail(&dma_dom->list, &iommu_pd_list); |
2376 | } | 2373 | } |
2377 | } | 2374 | } |
2378 | 2375 | ||
2379 | static struct dma_map_ops amd_iommu_dma_ops = { | 2376 | static struct dma_map_ops amd_iommu_dma_ops = { |
2380 | .alloc_coherent = alloc_coherent, | 2377 | .alloc_coherent = alloc_coherent, |
2381 | .free_coherent = free_coherent, | 2378 | .free_coherent = free_coherent, |
2382 | .map_page = map_page, | 2379 | .map_page = map_page, |
2383 | .unmap_page = unmap_page, | 2380 | .unmap_page = unmap_page, |
2384 | .map_sg = map_sg, | 2381 | .map_sg = map_sg, |
2385 | .unmap_sg = unmap_sg, | 2382 | .unmap_sg = unmap_sg, |
2386 | .dma_supported = amd_iommu_dma_supported, | 2383 | .dma_supported = amd_iommu_dma_supported, |
2387 | }; | 2384 | }; |
2388 | 2385 | ||
2389 | /* | 2386 | /* |
2390 | * The function which clues the AMD IOMMU driver into dma_ops. | 2387 | * The function which clues the AMD IOMMU driver into dma_ops. |
2391 | */ | 2388 | */ |
2392 | 2389 | ||
2393 | void __init amd_iommu_init_api(void) | 2390 | void __init amd_iommu_init_api(void) |
2394 | { | 2391 | { |
2395 | register_iommu(&amd_iommu_ops); | 2392 | register_iommu(&amd_iommu_ops); |
2396 | } | 2393 | } |
2397 | 2394 | ||
2398 | int __init amd_iommu_init_dma_ops(void) | 2395 | int __init amd_iommu_init_dma_ops(void) |
2399 | { | 2396 | { |
2400 | struct amd_iommu *iommu; | 2397 | struct amd_iommu *iommu; |
2401 | int ret; | 2398 | int ret; |
2402 | 2399 | ||
2403 | /* | 2400 | /* |
2404 | * first allocate a default protection domain for every IOMMU we | 2401 | * first allocate a default protection domain for every IOMMU we |
2405 | * found in the system. Devices not assigned to any other | 2402 | * found in the system. Devices not assigned to any other |
2406 | * protection domain will be assigned to the default one. | 2403 | * protection domain will be assigned to the default one. |
2407 | */ | 2404 | */ |
2408 | for_each_iommu(iommu) { | 2405 | for_each_iommu(iommu) { |
2409 | iommu->default_dom = dma_ops_domain_alloc(); | 2406 | iommu->default_dom = dma_ops_domain_alloc(); |
2410 | if (iommu->default_dom == NULL) | 2407 | if (iommu->default_dom == NULL) |
2411 | return -ENOMEM; | 2408 | return -ENOMEM; |
2412 | iommu->default_dom->domain.flags |= PD_DEFAULT_MASK; | 2409 | iommu->default_dom->domain.flags |= PD_DEFAULT_MASK; |
2413 | ret = iommu_init_unity_mappings(iommu); | 2410 | ret = iommu_init_unity_mappings(iommu); |
2414 | if (ret) | 2411 | if (ret) |
2415 | goto free_domains; | 2412 | goto free_domains; |
2416 | } | 2413 | } |
2417 | 2414 | ||
2418 | /* | 2415 | /* |
2419 | * Pre-allocate the protection domains for each device. | 2416 | * Pre-allocate the protection domains for each device. |
2420 | */ | 2417 | */ |
2421 | prealloc_protection_domains(); | 2418 | prealloc_protection_domains(); |
2422 | 2419 | ||
2423 | iommu_detected = 1; | 2420 | iommu_detected = 1; |
2424 | swiotlb = 0; | 2421 | swiotlb = 0; |
2425 | 2422 | ||
2426 | /* Make the driver finally visible to the drivers */ | 2423 | /* Make the driver finally visible to the drivers */ |
2427 | dma_ops = &amd_iommu_dma_ops; | 2424 | dma_ops = &amd_iommu_dma_ops; |
2428 | 2425 | ||
2429 | amd_iommu_stats_init(); | 2426 | amd_iommu_stats_init(); |
2430 | 2427 | ||
2431 | return 0; | 2428 | return 0; |
2432 | 2429 | ||
2433 | free_domains: | 2430 | free_domains: |
2434 | 2431 | ||
2435 | for_each_iommu(iommu) { | 2432 | for_each_iommu(iommu) { |
2436 | if (iommu->default_dom) | 2433 | if (iommu->default_dom) |
2437 | dma_ops_domain_free(iommu->default_dom); | 2434 | dma_ops_domain_free(iommu->default_dom); |
2438 | } | 2435 | } |
2439 | 2436 | ||
2440 | return ret; | 2437 | return ret; |
2441 | } | 2438 | } |
2442 | 2439 | ||
2443 | /***************************************************************************** | 2440 | /***************************************************************************** |
2444 | * | 2441 | * |
2445 | * The following functions belong to the exported interface of AMD IOMMU | 2442 | * The following functions belong to the exported interface of AMD IOMMU |
2446 | * | 2443 | * |
2447 | * This interface allows access to lower level functions of the IOMMU | 2444 | * This interface allows access to lower level functions of the IOMMU |
2448 | * like protection domain handling and assignement of devices to domains | 2445 | * like protection domain handling and assignement of devices to domains |
2449 | * which is not possible with the dma_ops interface. | 2446 | * which is not possible with the dma_ops interface. |
2450 | * | 2447 | * |
2451 | *****************************************************************************/ | 2448 | *****************************************************************************/ |
2452 | 2449 | ||
2453 | static void cleanup_domain(struct protection_domain *domain) | 2450 | static void cleanup_domain(struct protection_domain *domain) |
2454 | { | 2451 | { |
2455 | struct iommu_dev_data *dev_data, *next; | 2452 | struct iommu_dev_data *dev_data, *next; |
2456 | unsigned long flags; | 2453 | unsigned long flags; |
2457 | 2454 | ||
2458 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 2455 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
2459 | 2456 | ||
2460 | list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { | 2457 | list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { |
2461 | struct device *dev = dev_data->dev; | 2458 | struct device *dev = dev_data->dev; |
2462 | 2459 | ||
2463 | __detach_device(dev); | 2460 | __detach_device(dev); |
2464 | atomic_set(&dev_data->bind, 0); | 2461 | atomic_set(&dev_data->bind, 0); |
2465 | } | 2462 | } |
2466 | 2463 | ||
2467 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 2464 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
2468 | } | 2465 | } |
2469 | 2466 | ||
2470 | static void protection_domain_free(struct protection_domain *domain) | 2467 | static void protection_domain_free(struct protection_domain *domain) |
2471 | { | 2468 | { |
2472 | if (!domain) | 2469 | if (!domain) |
2473 | return; | 2470 | return; |
2474 | 2471 | ||
2475 | del_domain_from_list(domain); | 2472 | del_domain_from_list(domain); |
2476 | 2473 | ||
2477 | if (domain->id) | 2474 | if (domain->id) |
2478 | domain_id_free(domain->id); | 2475 | domain_id_free(domain->id); |
2479 | 2476 | ||
2480 | kfree(domain); | 2477 | kfree(domain); |
2481 | } | 2478 | } |
2482 | 2479 | ||
2483 | static struct protection_domain *protection_domain_alloc(void) | 2480 | static struct protection_domain *protection_domain_alloc(void) |
2484 | { | 2481 | { |
2485 | struct protection_domain *domain; | 2482 | struct protection_domain *domain; |
2486 | 2483 | ||
2487 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | 2484 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); |
2488 | if (!domain) | 2485 | if (!domain) |
2489 | return NULL; | 2486 | return NULL; |
2490 | 2487 | ||
2491 | spin_lock_init(&domain->lock); | 2488 | spin_lock_init(&domain->lock); |
2492 | mutex_init(&domain->api_lock); | 2489 | mutex_init(&domain->api_lock); |
2493 | domain->id = domain_id_alloc(); | 2490 | domain->id = domain_id_alloc(); |
2494 | if (!domain->id) | 2491 | if (!domain->id) |
2495 | goto out_err; | 2492 | goto out_err; |
2496 | INIT_LIST_HEAD(&domain->dev_list); | 2493 | INIT_LIST_HEAD(&domain->dev_list); |
2497 | 2494 | ||
2498 | add_domain_to_list(domain); | 2495 | add_domain_to_list(domain); |
2499 | 2496 | ||
2500 | return domain; | 2497 | return domain; |
2501 | 2498 | ||
2502 | out_err: | 2499 | out_err: |
2503 | kfree(domain); | 2500 | kfree(domain); |
2504 | 2501 | ||
2505 | return NULL; | 2502 | return NULL; |
2506 | } | 2503 | } |
2507 | 2504 | ||
2508 | static int amd_iommu_domain_init(struct iommu_domain *dom) | 2505 | static int amd_iommu_domain_init(struct iommu_domain *dom) |
2509 | { | 2506 | { |
2510 | struct protection_domain *domain; | 2507 | struct protection_domain *domain; |
2511 | 2508 | ||
2512 | domain = protection_domain_alloc(); | 2509 | domain = protection_domain_alloc(); |
2513 | if (!domain) | 2510 | if (!domain) |
2514 | goto out_free; | 2511 | goto out_free; |
2515 | 2512 | ||
2516 | domain->mode = PAGE_MODE_3_LEVEL; | 2513 | domain->mode = PAGE_MODE_3_LEVEL; |
2517 | domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL); | 2514 | domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL); |
2518 | if (!domain->pt_root) | 2515 | if (!domain->pt_root) |
2519 | goto out_free; | 2516 | goto out_free; |
2520 | 2517 | ||
2521 | dom->priv = domain; | 2518 | dom->priv = domain; |
2522 | 2519 | ||
2523 | return 0; | 2520 | return 0; |
2524 | 2521 | ||
2525 | out_free: | 2522 | out_free: |
2526 | protection_domain_free(domain); | 2523 | protection_domain_free(domain); |
2527 | 2524 | ||
2528 | return -ENOMEM; | 2525 | return -ENOMEM; |
2529 | } | 2526 | } |
2530 | 2527 | ||
2531 | static void amd_iommu_domain_destroy(struct iommu_domain *dom) | 2528 | static void amd_iommu_domain_destroy(struct iommu_domain *dom) |
2532 | { | 2529 | { |
2533 | struct protection_domain *domain = dom->priv; | 2530 | struct protection_domain *domain = dom->priv; |
2534 | 2531 | ||
2535 | if (!domain) | 2532 | if (!domain) |
2536 | return; | 2533 | return; |
2537 | 2534 | ||
2538 | if (domain->dev_cnt > 0) | 2535 | if (domain->dev_cnt > 0) |
2539 | cleanup_domain(domain); | 2536 | cleanup_domain(domain); |
2540 | 2537 | ||
2541 | BUG_ON(domain->dev_cnt != 0); | 2538 | BUG_ON(domain->dev_cnt != 0); |
2542 | 2539 | ||
2543 | free_pagetable(domain); | 2540 | free_pagetable(domain); |
2544 | 2541 | ||
2545 | protection_domain_free(domain); | 2542 | protection_domain_free(domain); |
2546 | 2543 | ||
2547 | dom->priv = NULL; | 2544 | dom->priv = NULL; |
2548 | } | 2545 | } |
2549 | 2546 | ||
2550 | static void amd_iommu_detach_device(struct iommu_domain *dom, | 2547 | static void amd_iommu_detach_device(struct iommu_domain *dom, |
2551 | struct device *dev) | 2548 | struct device *dev) |
2552 | { | 2549 | { |
2553 | struct iommu_dev_data *dev_data = dev->archdata.iommu; | 2550 | struct iommu_dev_data *dev_data = dev->archdata.iommu; |
2554 | struct amd_iommu *iommu; | 2551 | struct amd_iommu *iommu; |
2555 | u16 devid; | 2552 | u16 devid; |
2556 | 2553 | ||
2557 | if (!check_device(dev)) | 2554 | if (!check_device(dev)) |
2558 | return; | 2555 | return; |
2559 | 2556 | ||
2560 | devid = get_device_id(dev); | 2557 | devid = get_device_id(dev); |
2561 | 2558 | ||
2562 | if (dev_data->domain != NULL) | 2559 | if (dev_data->domain != NULL) |
2563 | detach_device(dev); | 2560 | detach_device(dev); |
2564 | 2561 | ||
2565 | iommu = amd_iommu_rlookup_table[devid]; | 2562 | iommu = amd_iommu_rlookup_table[devid]; |
2566 | if (!iommu) | 2563 | if (!iommu) |
2567 | return; | 2564 | return; |
2568 | 2565 | ||
2569 | device_flush_dte(dev); | 2566 | device_flush_dte(dev); |
2570 | iommu_completion_wait(iommu); | 2567 | iommu_completion_wait(iommu); |
2571 | } | 2568 | } |
2572 | 2569 | ||
2573 | static int amd_iommu_attach_device(struct iommu_domain *dom, | 2570 | static int amd_iommu_attach_device(struct iommu_domain *dom, |
2574 | struct device *dev) | 2571 | struct device *dev) |
2575 | { | 2572 | { |
2576 | struct protection_domain *domain = dom->priv; | 2573 | struct protection_domain *domain = dom->priv; |
2577 | struct iommu_dev_data *dev_data; | 2574 | struct iommu_dev_data *dev_data; |
2578 | struct amd_iommu *iommu; | 2575 | struct amd_iommu *iommu; |
2579 | int ret; | 2576 | int ret; |
2580 | u16 devid; | 2577 | u16 devid; |
2581 | 2578 | ||
2582 | if (!check_device(dev)) | 2579 | if (!check_device(dev)) |
2583 | return -EINVAL; | 2580 | return -EINVAL; |
2584 | 2581 | ||
2585 | dev_data = dev->archdata.iommu; | 2582 | dev_data = dev->archdata.iommu; |
2586 | 2583 | ||
2587 | devid = get_device_id(dev); | 2584 | devid = get_device_id(dev); |
2588 | 2585 | ||
2589 | iommu = amd_iommu_rlookup_table[devid]; | 2586 | iommu = amd_iommu_rlookup_table[devid]; |
2590 | if (!iommu) | 2587 | if (!iommu) |
2591 | return -EINVAL; | 2588 | return -EINVAL; |
2592 | 2589 | ||
2593 | if (dev_data->domain) | 2590 | if (dev_data->domain) |
2594 | detach_device(dev); | 2591 | detach_device(dev); |
2595 | 2592 | ||
2596 | ret = attach_device(dev, domain); | 2593 | ret = attach_device(dev, domain); |
2597 | 2594 | ||
2598 | iommu_completion_wait(iommu); | 2595 | iommu_completion_wait(iommu); |
2599 | 2596 | ||
2600 | return ret; | 2597 | return ret; |
2601 | } | 2598 | } |
2602 | 2599 | ||
2603 | static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova, | 2600 | static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova, |
2604 | phys_addr_t paddr, int gfp_order, int iommu_prot) | 2601 | phys_addr_t paddr, int gfp_order, int iommu_prot) |
2605 | { | 2602 | { |
2606 | unsigned long page_size = 0x1000UL << gfp_order; | 2603 | unsigned long page_size = 0x1000UL << gfp_order; |
2607 | struct protection_domain *domain = dom->priv; | 2604 | struct protection_domain *domain = dom->priv; |
2608 | int prot = 0; | 2605 | int prot = 0; |
2609 | int ret; | 2606 | int ret; |
2610 | 2607 | ||
2611 | if (iommu_prot & IOMMU_READ) | 2608 | if (iommu_prot & IOMMU_READ) |
2612 | prot |= IOMMU_PROT_IR; | 2609 | prot |= IOMMU_PROT_IR; |
2613 | if (iommu_prot & IOMMU_WRITE) | 2610 | if (iommu_prot & IOMMU_WRITE) |
2614 | prot |= IOMMU_PROT_IW; | 2611 | prot |= IOMMU_PROT_IW; |
2615 | 2612 | ||
2616 | mutex_lock(&domain->api_lock); | 2613 | mutex_lock(&domain->api_lock); |
2617 | ret = iommu_map_page(domain, iova, paddr, prot, page_size); | 2614 | ret = iommu_map_page(domain, iova, paddr, prot, page_size); |
2618 | mutex_unlock(&domain->api_lock); | 2615 | mutex_unlock(&domain->api_lock); |
2619 | 2616 | ||
2620 | return ret; | 2617 | return ret; |
2621 | } | 2618 | } |
2622 | 2619 | ||
2623 | static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, | 2620 | static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, |
2624 | int gfp_order) | 2621 | int gfp_order) |
2625 | { | 2622 | { |
2626 | struct protection_domain *domain = dom->priv; | 2623 | struct protection_domain *domain = dom->priv; |
2627 | unsigned long page_size, unmap_size; | 2624 | unsigned long page_size, unmap_size; |
2628 | 2625 | ||
2629 | page_size = 0x1000UL << gfp_order; | 2626 | page_size = 0x1000UL << gfp_order; |
2630 | 2627 | ||
2631 | mutex_lock(&domain->api_lock); | 2628 | mutex_lock(&domain->api_lock); |
2632 | unmap_size = iommu_unmap_page(domain, iova, page_size); | 2629 | unmap_size = iommu_unmap_page(domain, iova, page_size); |
2633 | mutex_unlock(&domain->api_lock); | 2630 | mutex_unlock(&domain->api_lock); |
2634 | 2631 | ||
2635 | domain_flush_tlb_pde(domain); | 2632 | domain_flush_tlb_pde(domain); |
2636 | 2633 | ||
2637 | return get_order(unmap_size); | 2634 | return get_order(unmap_size); |
2638 | } | 2635 | } |
2639 | 2636 | ||
2640 | static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, | 2637 | static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, |
2641 | unsigned long iova) | 2638 | unsigned long iova) |
2642 | { | 2639 | { |
2643 | struct protection_domain *domain = dom->priv; | 2640 | struct protection_domain *domain = dom->priv; |
2644 | unsigned long offset_mask; | 2641 | unsigned long offset_mask; |
2645 | phys_addr_t paddr; | 2642 | phys_addr_t paddr; |
2646 | u64 *pte, __pte; | 2643 | u64 *pte, __pte; |
2647 | 2644 | ||
2648 | pte = fetch_pte(domain, iova); | 2645 | pte = fetch_pte(domain, iova); |
2649 | 2646 | ||
2650 | if (!pte || !IOMMU_PTE_PRESENT(*pte)) | 2647 | if (!pte || !IOMMU_PTE_PRESENT(*pte)) |
2651 | return 0; | 2648 | return 0; |
2652 | 2649 | ||
2653 | if (PM_PTE_LEVEL(*pte) == 0) | 2650 | if (PM_PTE_LEVEL(*pte) == 0) |
2654 | offset_mask = PAGE_SIZE - 1; | 2651 | offset_mask = PAGE_SIZE - 1; |
2655 | else | 2652 | else |
2656 | offset_mask = PTE_PAGE_SIZE(*pte) - 1; | 2653 | offset_mask = PTE_PAGE_SIZE(*pte) - 1; |
2657 | 2654 | ||
2658 | __pte = *pte & PM_ADDR_MASK; | 2655 | __pte = *pte & PM_ADDR_MASK; |
2659 | paddr = (__pte & ~offset_mask) | (iova & offset_mask); | 2656 | paddr = (__pte & ~offset_mask) | (iova & offset_mask); |
2660 | 2657 | ||
2661 | return paddr; | 2658 | return paddr; |
2662 | } | 2659 | } |
2663 | 2660 | ||
2664 | static int amd_iommu_domain_has_cap(struct iommu_domain *domain, | 2661 | static int amd_iommu_domain_has_cap(struct iommu_domain *domain, |
2665 | unsigned long cap) | 2662 | unsigned long cap) |
2666 | { | 2663 | { |
2667 | switch (cap) { | 2664 | switch (cap) { |
2668 | case IOMMU_CAP_CACHE_COHERENCY: | 2665 | case IOMMU_CAP_CACHE_COHERENCY: |
2669 | return 1; | 2666 | return 1; |
2670 | } | 2667 | } |
2671 | 2668 | ||
2672 | return 0; | 2669 | return 0; |
2673 | } | 2670 | } |
2674 | 2671 | ||
2675 | static struct iommu_ops amd_iommu_ops = { | 2672 | static struct iommu_ops amd_iommu_ops = { |
2676 | .domain_init = amd_iommu_domain_init, | 2673 | .domain_init = amd_iommu_domain_init, |
2677 | .domain_destroy = amd_iommu_domain_destroy, | 2674 | .domain_destroy = amd_iommu_domain_destroy, |
2678 | .attach_dev = amd_iommu_attach_device, | 2675 | .attach_dev = amd_iommu_attach_device, |
2679 | .detach_dev = amd_iommu_detach_device, | 2676 | .detach_dev = amd_iommu_detach_device, |
2680 | .map = amd_iommu_map, | 2677 | .map = amd_iommu_map, |
2681 | .unmap = amd_iommu_unmap, | 2678 | .unmap = amd_iommu_unmap, |
2682 | .iova_to_phys = amd_iommu_iova_to_phys, | 2679 | .iova_to_phys = amd_iommu_iova_to_phys, |
2683 | .domain_has_cap = amd_iommu_domain_has_cap, | 2680 | .domain_has_cap = amd_iommu_domain_has_cap, |
2684 | }; | 2681 | }; |
2685 | 2682 | ||
2686 | /***************************************************************************** | 2683 | /***************************************************************************** |
2687 | * | 2684 | * |
2688 | * The next functions do a basic initialization of IOMMU for pass through | 2685 | * The next functions do a basic initialization of IOMMU for pass through |
2689 | * mode | 2686 | * mode |
2690 | * | 2687 | * |
2691 | * In passthrough mode the IOMMU is initialized and enabled but not used for | 2688 | * In passthrough mode the IOMMU is initialized and enabled but not used for |
2692 | * DMA-API translation. | 2689 | * DMA-API translation. |
2693 | * | 2690 | * |
2694 | *****************************************************************************/ | 2691 | *****************************************************************************/ |
2695 | 2692 | ||
2696 | int __init amd_iommu_init_passthrough(void) | 2693 | int __init amd_iommu_init_passthrough(void) |
2697 | { | 2694 | { |
2698 | struct amd_iommu *iommu; | 2695 | struct amd_iommu *iommu; |
2699 | struct pci_dev *dev = NULL; | 2696 | struct pci_dev *dev = NULL; |
2700 | u16 devid; | 2697 | u16 devid; |
2701 | 2698 | ||
2702 | /* allocate passthrough domain */ | 2699 | /* allocate passthrough domain */ |
2703 | pt_domain = protection_domain_alloc(); | 2700 | pt_domain = protection_domain_alloc(); |
2704 | if (!pt_domain) | 2701 | if (!pt_domain) |
2705 | return -ENOMEM; | 2702 | return -ENOMEM; |
2706 | 2703 | ||
2707 | pt_domain->mode |= PAGE_MODE_NONE; | 2704 | pt_domain->mode |= PAGE_MODE_NONE; |
2708 | 2705 | ||
2709 | for_each_pci_dev(dev) { | 2706 | for_each_pci_dev(dev) { |
2710 | if (!check_device(&dev->dev)) | 2707 | if (!check_device(&dev->dev)) |
2711 | continue; | 2708 | continue; |
2712 | 2709 | ||
2713 | devid = get_device_id(&dev->dev); | 2710 | devid = get_device_id(&dev->dev); |
2714 | 2711 | ||
2715 | iommu = amd_iommu_rlookup_table[devid]; | 2712 | iommu = amd_iommu_rlookup_table[devid]; |
2716 | if (!iommu) | 2713 | if (!iommu) |
2717 | continue; | 2714 | continue; |
2718 | 2715 | ||
2719 | attach_device(&dev->dev, pt_domain); | 2716 | attach_device(&dev->dev, pt_domain); |
2720 | } | 2717 | } |
2721 | 2718 | ||
2722 | pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); | 2719 | pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); |
2723 | 2720 | ||
2724 | return 0; | 2721 | return 0; |
2725 | } | 2722 | } |
2726 | 2723 |
arch/x86/kernel/test_nx.c
1 | /* | 1 | /* |
2 | * test_nx.c: functional test for NX functionality | 2 | * test_nx.c: functional test for NX functionality |
3 | * | 3 | * |
4 | * (C) Copyright 2008 Intel Corporation | 4 | * (C) Copyright 2008 Intel Corporation |
5 | * Author: Arjan van de Ven <arjan@linux.intel.com> | 5 | * Author: Arjan van de Ven <arjan@linux.intel.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
9 | * as published by the Free Software Foundation; version 2 | 9 | * as published by the Free Software Foundation; version 2 |
10 | * of the License. | 10 | * of the License. |
11 | */ | 11 | */ |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sort.h> | 13 | #include <linux/sort.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | 15 | ||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/asm.h> | 17 | #include <asm/asm.h> |
18 | 18 | ||
19 | extern int rodata_test_data; | 19 | extern int rodata_test_data; |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * This file checks 4 things: | 22 | * This file checks 4 things: |
23 | * 1) Check if the stack is not executable | 23 | * 1) Check if the stack is not executable |
24 | * 2) Check if kmalloc memory is not executable | 24 | * 2) Check if kmalloc memory is not executable |
25 | * 3) Check if the .rodata section is not executable | 25 | * 3) Check if the .rodata section is not executable |
26 | * 4) Check if the .data section of a module is not executable | 26 | * 4) Check if the .data section of a module is not executable |
27 | * | 27 | * |
28 | * To do this, the test code tries to execute memory in stack/kmalloc/etc, | 28 | * To do this, the test code tries to execute memory in stack/kmalloc/etc, |
29 | * and then checks if the expected trap happens. | 29 | * and then checks if the expected trap happens. |
30 | * | 30 | * |
31 | * Sadly, this implies having a dynamic exception handling table entry. | 31 | * Sadly, this implies having a dynamic exception handling table entry. |
32 | * ... which can be done (and will make Rusty cry)... but it can only | 32 | * ... which can be done (and will make Rusty cry)... but it can only |
33 | * be done in a stand-alone module with only 1 entry total. | 33 | * be done in a stand-alone module with only 1 entry total. |
34 | * (otherwise we'd have to sort and that's just too messy) | 34 | * (otherwise we'd have to sort and that's just too messy) |
35 | */ | 35 | */ |
36 | 36 | ||
37 | 37 | ||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * We want to set up an exception handling point on our stack, | 40 | * We want to set up an exception handling point on our stack, |
41 | * which means a variable value. This function is rather dirty | 41 | * which means a variable value. This function is rather dirty |
42 | * and walks the exception table of the module, looking for a magic | 42 | * and walks the exception table of the module, looking for a magic |
43 | * marker and replaces it with a specific function. | 43 | * marker and replaces it with a specific function. |
44 | */ | 44 | */ |
45 | static void fudze_exception_table(void *marker, void *new) | 45 | static void fudze_exception_table(void *marker, void *new) |
46 | { | 46 | { |
47 | struct module *mod = THIS_MODULE; | 47 | struct module *mod = THIS_MODULE; |
48 | struct exception_table_entry *extable; | 48 | struct exception_table_entry *extable; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Note: This module has only 1 exception table entry, | 51 | * Note: This module has only 1 exception table entry, |
52 | * so searching and sorting is not needed. If that changes, | 52 | * so searching and sorting is not needed. If that changes, |
53 | * this would be the place to search and re-sort the exception | 53 | * this would be the place to search and re-sort the exception |
54 | * table. | 54 | * table. |
55 | */ | 55 | */ |
56 | if (mod->num_exentries > 1) { | 56 | if (mod->num_exentries > 1) { |
57 | printk(KERN_ERR "test_nx: too many exception table entries!\n"); | 57 | printk(KERN_ERR "test_nx: too many exception table entries!\n"); |
58 | printk(KERN_ERR "test_nx: test results are not reliable.\n"); | 58 | printk(KERN_ERR "test_nx: test results are not reliable.\n"); |
59 | return; | 59 | return; |
60 | } | 60 | } |
61 | extable = (struct exception_table_entry *)mod->extable; | 61 | extable = (struct exception_table_entry *)mod->extable; |
62 | extable[0].insn = (unsigned long)new; | 62 | extable[0].insn = (unsigned long)new; |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | /* | 66 | /* |
67 | * exception tables get their symbols translated so we need | 67 | * exception tables get their symbols translated so we need |
68 | * to use a fake function to put in there, which we can then | 68 | * to use a fake function to put in there, which we can then |
69 | * replace at runtime. | 69 | * replace at runtime. |
70 | */ | 70 | */ |
71 | void foo_label(void); | 71 | void foo_label(void); |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * returns 0 for not-executable, negative for executable | 74 | * returns 0 for not-executable, negative for executable |
75 | * | 75 | * |
76 | * Note: we cannot allow this function to be inlined, because | 76 | * Note: we cannot allow this function to be inlined, because |
77 | * that would give us more than 1 exception table entry. | 77 | * that would give us more than 1 exception table entry. |
78 | * This in turn would break the assumptions above. | 78 | * This in turn would break the assumptions above. |
79 | */ | 79 | */ |
80 | static noinline int test_address(void *address) | 80 | static noinline int test_address(void *address) |
81 | { | 81 | { |
82 | unsigned long result; | 82 | unsigned long result; |
83 | 83 | ||
84 | /* Set up an exception table entry for our address */ | 84 | /* Set up an exception table entry for our address */ |
85 | fudze_exception_table(&foo_label, address); | 85 | fudze_exception_table(&foo_label, address); |
86 | result = 1; | 86 | result = 1; |
87 | asm volatile( | 87 | asm volatile( |
88 | "foo_label:\n" | 88 | "foo_label:\n" |
89 | "0: call *%[fake_code]\n" | 89 | "0: call *%[fake_code]\n" |
90 | "1:\n" | 90 | "1:\n" |
91 | ".section .fixup,\"ax\"\n" | 91 | ".section .fixup,\"ax\"\n" |
92 | "2: mov %[zero], %[rslt]\n" | 92 | "2: mov %[zero], %[rslt]\n" |
93 | " ret\n" | 93 | " ret\n" |
94 | ".previous\n" | 94 | ".previous\n" |
95 | _ASM_EXTABLE(0b,2b) | 95 | _ASM_EXTABLE(0b,2b) |
96 | : [rslt] "=r" (result) | 96 | : [rslt] "=r" (result) |
97 | : [fake_code] "r" (address), [zero] "r" (0UL), "0" (result) | 97 | : [fake_code] "r" (address), [zero] "r" (0UL), "0" (result) |
98 | ); | 98 | ); |
99 | /* change the exception table back for the next round */ | 99 | /* change the exception table back for the next round */ |
100 | fudze_exception_table(address, &foo_label); | 100 | fudze_exception_table(address, &foo_label); |
101 | 101 | ||
102 | if (result) | 102 | if (result) |
103 | return -ENODEV; | 103 | return -ENODEV; |
104 | return 0; | 104 | return 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | static unsigned char test_data = 0xC3; /* 0xC3 is the opcode for "ret" */ | 107 | static unsigned char test_data = 0xC3; /* 0xC3 is the opcode for "ret" */ |
108 | 108 | ||
109 | static int test_NX(void) | 109 | static int test_NX(void) |
110 | { | 110 | { |
111 | int ret = 0; | 111 | int ret = 0; |
112 | /* 0xC3 is the opcode for "ret" */ | 112 | /* 0xC3 is the opcode for "ret" */ |
113 | char stackcode[] = {0xC3, 0x90, 0 }; | 113 | char stackcode[] = {0xC3, 0x90, 0 }; |
114 | char *heap; | 114 | char *heap; |
115 | 115 | ||
116 | test_data = 0xC3; | 116 | test_data = 0xC3; |
117 | 117 | ||
118 | printk(KERN_INFO "Testing NX protection\n"); | 118 | printk(KERN_INFO "Testing NX protection\n"); |
119 | 119 | ||
120 | /* Test 1: check if the stack is not executable */ | 120 | /* Test 1: check if the stack is not executable */ |
121 | if (test_address(&stackcode)) { | 121 | if (test_address(&stackcode)) { |
122 | printk(KERN_ERR "test_nx: stack was executable\n"); | 122 | printk(KERN_ERR "test_nx: stack was executable\n"); |
123 | ret = -ENODEV; | 123 | ret = -ENODEV; |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | /* Test 2: Check if the heap is executable */ | 127 | /* Test 2: Check if the heap is executable */ |
128 | heap = kmalloc(64, GFP_KERNEL); | 128 | heap = kmalloc(64, GFP_KERNEL); |
129 | if (!heap) | 129 | if (!heap) |
130 | return -ENOMEM; | 130 | return -ENOMEM; |
131 | heap[0] = 0xC3; /* opcode for "ret" */ | 131 | heap[0] = 0xC3; /* opcode for "ret" */ |
132 | 132 | ||
133 | if (test_address(heap)) { | 133 | if (test_address(heap)) { |
134 | printk(KERN_ERR "test_nx: heap was executable\n"); | 134 | printk(KERN_ERR "test_nx: heap was executable\n"); |
135 | ret = -ENODEV; | 135 | ret = -ENODEV; |
136 | } | 136 | } |
137 | kfree(heap); | 137 | kfree(heap); |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * The following 2 tests currently fail, this needs to get fixed | 140 | * The following 2 tests currently fail, this needs to get fixed |
141 | * Until then, don't run them to avoid too many people getting scared | 141 | * Until then, don't run them to avoid too many people getting scared |
142 | * by the error message | 142 | * by the error message |
143 | */ | 143 | */ |
144 | 144 | ||
145 | #ifdef CONFIG_DEBUG_RODATA | 145 | #ifdef CONFIG_DEBUG_RODATA |
146 | /* Test 3: Check if the .rodata section is executable */ | 146 | /* Test 3: Check if the .rodata section is executable */ |
147 | if (rodata_test_data != 0xC3) { | 147 | if (rodata_test_data != 0xC3) { |
148 | printk(KERN_ERR "test_nx: .rodata marker has invalid value\n"); | 148 | printk(KERN_ERR "test_nx: .rodata marker has invalid value\n"); |
149 | ret = -ENODEV; | 149 | ret = -ENODEV; |
150 | } else if (test_address(&rodata_test_data)) { | 150 | } else if (test_address(&rodata_test_data)) { |
151 | printk(KERN_ERR "test_nx: .rodata section is executable\n"); | 151 | printk(KERN_ERR "test_nx: .rodata section is executable\n"); |
152 | ret = -ENODEV; | 152 | ret = -ENODEV; |
153 | } | 153 | } |
154 | #endif | 154 | #endif |
155 | 155 | ||
156 | #if 0 | 156 | #if 0 |
157 | /* Test 4: Check if the .data section of a module is executable */ | 157 | /* Test 4: Check if the .data section of a module is executable */ |
158 | if (test_address(&test_data)) { | 158 | if (test_address(&test_data)) { |
159 | printk(KERN_ERR "test_nx: .data section is executable\n"); | 159 | printk(KERN_ERR "test_nx: .data section is executable\n"); |
160 | ret = -ENODEV; | 160 | ret = -ENODEV; |
161 | } | 161 | } |
162 | 162 | ||
163 | #endif | 163 | #endif |
164 | return 0; | 164 | return ret; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void test_exit(void) | 167 | static void test_exit(void) |
168 | { | 168 | { |
169 | } | 169 | } |
170 | 170 | ||
171 | module_init(test_NX); | 171 | module_init(test_NX); |
172 | module_exit(test_exit); | 172 | module_exit(test_exit); |
173 | MODULE_LICENSE("GPL"); | 173 | MODULE_LICENSE("GPL"); |
174 | MODULE_DESCRIPTION("Testcase for the NX infrastructure"); | 174 | MODULE_DESCRIPTION("Testcase for the NX infrastructure"); |
175 | MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>"); | 175 | MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>"); |
176 | 176 |
arch/x86/mm/pf_in.c
1 | /* | 1 | /* |
2 | * Fault Injection Test harness (FI) | 2 | * Fault Injection Test harness (FI) |
3 | * Copyright (C) Intel Crop. | 3 | * Copyright (C) Intel Crop. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
7 | * as published by the Free Software Foundation; either version 2 | 7 | * as published by the Free Software Foundation; either version 2 |
8 | * of the License, or (at your option) any later version. | 8 | * of the License, or (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18 | * USA. | 18 | * USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* Id: pf_in.c,v 1.1.1.1 2002/11/12 05:56:32 brlock Exp | 22 | /* Id: pf_in.c,v 1.1.1.1 2002/11/12 05:56:32 brlock Exp |
23 | * Copyright by Intel Crop., 2002 | 23 | * Copyright by Intel Crop., 2002 |
24 | * Louis Zhuang (louis.zhuang@intel.com) | 24 | * Louis Zhuang (louis.zhuang@intel.com) |
25 | * | 25 | * |
26 | * Bjorn Steinbrink (B.Steinbrink@gmx.de), 2007 | 26 | * Bjorn Steinbrink (B.Steinbrink@gmx.de), 2007 |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/ptrace.h> /* struct pt_regs */ | 30 | #include <linux/ptrace.h> /* struct pt_regs */ |
31 | #include "pf_in.h" | 31 | #include "pf_in.h" |
32 | 32 | ||
33 | #ifdef __i386__ | 33 | #ifdef __i386__ |
34 | /* IA32 Manual 3, 2-1 */ | 34 | /* IA32 Manual 3, 2-1 */ |
35 | static unsigned char prefix_codes[] = { | 35 | static unsigned char prefix_codes[] = { |
36 | 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64, | 36 | 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64, |
37 | 0x65, 0x66, 0x67 | 37 | 0x65, 0x66, 0x67 |
38 | }; | 38 | }; |
39 | /* IA32 Manual 3, 3-432*/ | 39 | /* IA32 Manual 3, 3-432*/ |
40 | static unsigned int reg_rop[] = { | 40 | static unsigned int reg_rop[] = { |
41 | 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F | 41 | 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F |
42 | }; | 42 | }; |
43 | static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; | 43 | static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; |
44 | static unsigned int imm_wop[] = { 0xC6, 0xC7 }; | 44 | static unsigned int imm_wop[] = { 0xC6, 0xC7 }; |
45 | /* IA32 Manual 3, 3-432*/ | 45 | /* IA32 Manual 3, 3-432*/ |
46 | static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA }; | 46 | static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA }; |
47 | static unsigned int rw32[] = { | 47 | static unsigned int rw32[] = { |
48 | 0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB | 48 | 0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB |
49 | }; | 49 | }; |
50 | static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA }; | 50 | static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA }; |
51 | static unsigned int mw16[] = { 0xB70F, 0xBF0F }; | 51 | static unsigned int mw16[] = { 0xB70F, 0xBF0F }; |
52 | static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB }; | 52 | static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB }; |
53 | static unsigned int mw64[] = {}; | 53 | static unsigned int mw64[] = {}; |
54 | #else /* not __i386__ */ | 54 | #else /* not __i386__ */ |
55 | static unsigned char prefix_codes[] = { | 55 | static unsigned char prefix_codes[] = { |
56 | 0x66, 0x67, 0x2E, 0x3E, 0x26, 0x64, 0x65, 0x36, | 56 | 0x66, 0x67, 0x2E, 0x3E, 0x26, 0x64, 0x65, 0x36, |
57 | 0xF0, 0xF3, 0xF2, | 57 | 0xF0, 0xF3, 0xF2, |
58 | /* REX Prefixes */ | 58 | /* REX Prefixes */ |
59 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, | 59 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, |
60 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f | 60 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f |
61 | }; | 61 | }; |
62 | /* AMD64 Manual 3, Appendix A*/ | 62 | /* AMD64 Manual 3, Appendix A*/ |
63 | static unsigned int reg_rop[] = { | 63 | static unsigned int reg_rop[] = { |
64 | 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F | 64 | 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F |
65 | }; | 65 | }; |
66 | static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; | 66 | static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB }; |
67 | static unsigned int imm_wop[] = { 0xC6, 0xC7 }; | 67 | static unsigned int imm_wop[] = { 0xC6, 0xC7 }; |
68 | static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA }; | 68 | static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA }; |
69 | static unsigned int rw32[] = { | 69 | static unsigned int rw32[] = { |
70 | 0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB | 70 | 0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB |
71 | }; | 71 | }; |
72 | /* 8 bit only */ | 72 | /* 8 bit only */ |
73 | static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA }; | 73 | static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA }; |
74 | /* 16 bit only */ | 74 | /* 16 bit only */ |
75 | static unsigned int mw16[] = { 0xB70F, 0xBF0F }; | 75 | static unsigned int mw16[] = { 0xB70F, 0xBF0F }; |
76 | /* 16 or 32 bit */ | 76 | /* 16 or 32 bit */ |
77 | static unsigned int mw32[] = { 0xC7 }; | 77 | static unsigned int mw32[] = { 0xC7 }; |
78 | /* 16, 32 or 64 bit */ | 78 | /* 16, 32 or 64 bit */ |
79 | static unsigned int mw64[] = { 0x89, 0x8B, 0xAB }; | 79 | static unsigned int mw64[] = { 0x89, 0x8B, 0xAB }; |
80 | #endif /* not __i386__ */ | 80 | #endif /* not __i386__ */ |
81 | 81 | ||
82 | struct prefix_bits { | 82 | struct prefix_bits { |
83 | unsigned shorted:1; | 83 | unsigned shorted:1; |
84 | unsigned enlarged:1; | 84 | unsigned enlarged:1; |
85 | unsigned rexr:1; | 85 | unsigned rexr:1; |
86 | unsigned rex:1; | 86 | unsigned rex:1; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static int skip_prefix(unsigned char *addr, struct prefix_bits *prf) | 89 | static int skip_prefix(unsigned char *addr, struct prefix_bits *prf) |
90 | { | 90 | { |
91 | int i; | 91 | int i; |
92 | unsigned char *p = addr; | 92 | unsigned char *p = addr; |
93 | prf->shorted = 0; | 93 | prf->shorted = 0; |
94 | prf->enlarged = 0; | 94 | prf->enlarged = 0; |
95 | prf->rexr = 0; | 95 | prf->rexr = 0; |
96 | prf->rex = 0; | 96 | prf->rex = 0; |
97 | 97 | ||
98 | restart: | 98 | restart: |
99 | for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) { | 99 | for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) { |
100 | if (*p == prefix_codes[i]) { | 100 | if (*p == prefix_codes[i]) { |
101 | if (*p == 0x66) | 101 | if (*p == 0x66) |
102 | prf->shorted = 1; | 102 | prf->shorted = 1; |
103 | #ifdef __amd64__ | 103 | #ifdef __amd64__ |
104 | if ((*p & 0xf8) == 0x48) | 104 | if ((*p & 0xf8) == 0x48) |
105 | prf->enlarged = 1; | 105 | prf->enlarged = 1; |
106 | if ((*p & 0xf4) == 0x44) | 106 | if ((*p & 0xf4) == 0x44) |
107 | prf->rexr = 1; | 107 | prf->rexr = 1; |
108 | if ((*p & 0xf0) == 0x40) | 108 | if ((*p & 0xf0) == 0x40) |
109 | prf->rex = 1; | 109 | prf->rex = 1; |
110 | #endif | 110 | #endif |
111 | p++; | 111 | p++; |
112 | goto restart; | 112 | goto restart; |
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | return (p - addr); | 116 | return (p - addr); |
117 | } | 117 | } |
118 | 118 | ||
119 | static int get_opcode(unsigned char *addr, unsigned int *opcode) | 119 | static int get_opcode(unsigned char *addr, unsigned int *opcode) |
120 | { | 120 | { |
121 | int len; | 121 | int len; |
122 | 122 | ||
123 | if (*addr == 0x0F) { | 123 | if (*addr == 0x0F) { |
124 | /* 0x0F is extension instruction */ | 124 | /* 0x0F is extension instruction */ |
125 | *opcode = *(unsigned short *)addr; | 125 | *opcode = *(unsigned short *)addr; |
126 | len = 2; | 126 | len = 2; |
127 | } else { | 127 | } else { |
128 | *opcode = *addr; | 128 | *opcode = *addr; |
129 | len = 1; | 129 | len = 1; |
130 | } | 130 | } |
131 | 131 | ||
132 | return len; | 132 | return len; |
133 | } | 133 | } |
134 | 134 | ||
135 | #define CHECK_OP_TYPE(opcode, array, type) \ | 135 | #define CHECK_OP_TYPE(opcode, array, type) \ |
136 | for (i = 0; i < ARRAY_SIZE(array); i++) { \ | 136 | for (i = 0; i < ARRAY_SIZE(array); i++) { \ |
137 | if (array[i] == opcode) { \ | 137 | if (array[i] == opcode) { \ |
138 | rv = type; \ | 138 | rv = type; \ |
139 | goto exit; \ | 139 | goto exit; \ |
140 | } \ | 140 | } \ |
141 | } | 141 | } |
142 | 142 | ||
143 | enum reason_type get_ins_type(unsigned long ins_addr) | 143 | enum reason_type get_ins_type(unsigned long ins_addr) |
144 | { | 144 | { |
145 | unsigned int opcode; | 145 | unsigned int opcode; |
146 | unsigned char *p; | 146 | unsigned char *p; |
147 | struct prefix_bits prf; | 147 | struct prefix_bits prf; |
148 | int i; | 148 | int i; |
149 | enum reason_type rv = OTHERS; | 149 | enum reason_type rv = OTHERS; |
150 | 150 | ||
151 | p = (unsigned char *)ins_addr; | 151 | p = (unsigned char *)ins_addr; |
152 | p += skip_prefix(p, &prf); | 152 | p += skip_prefix(p, &prf); |
153 | p += get_opcode(p, &opcode); | 153 | p += get_opcode(p, &opcode); |
154 | 154 | ||
155 | CHECK_OP_TYPE(opcode, reg_rop, REG_READ); | 155 | CHECK_OP_TYPE(opcode, reg_rop, REG_READ); |
156 | CHECK_OP_TYPE(opcode, reg_wop, REG_WRITE); | 156 | CHECK_OP_TYPE(opcode, reg_wop, REG_WRITE); |
157 | CHECK_OP_TYPE(opcode, imm_wop, IMM_WRITE); | 157 | CHECK_OP_TYPE(opcode, imm_wop, IMM_WRITE); |
158 | 158 | ||
159 | exit: | 159 | exit: |
160 | return rv; | 160 | return rv; |
161 | } | 161 | } |
162 | #undef CHECK_OP_TYPE | 162 | #undef CHECK_OP_TYPE |
163 | 163 | ||
164 | static unsigned int get_ins_reg_width(unsigned long ins_addr) | 164 | static unsigned int get_ins_reg_width(unsigned long ins_addr) |
165 | { | 165 | { |
166 | unsigned int opcode; | 166 | unsigned int opcode; |
167 | unsigned char *p; | 167 | unsigned char *p; |
168 | struct prefix_bits prf; | 168 | struct prefix_bits prf; |
169 | int i; | 169 | int i; |
170 | 170 | ||
171 | p = (unsigned char *)ins_addr; | 171 | p = (unsigned char *)ins_addr; |
172 | p += skip_prefix(p, &prf); | 172 | p += skip_prefix(p, &prf); |
173 | p += get_opcode(p, &opcode); | 173 | p += get_opcode(p, &opcode); |
174 | 174 | ||
175 | for (i = 0; i < ARRAY_SIZE(rw8); i++) | 175 | for (i = 0; i < ARRAY_SIZE(rw8); i++) |
176 | if (rw8[i] == opcode) | 176 | if (rw8[i] == opcode) |
177 | return 1; | 177 | return 1; |
178 | 178 | ||
179 | for (i = 0; i < ARRAY_SIZE(rw32); i++) | 179 | for (i = 0; i < ARRAY_SIZE(rw32); i++) |
180 | if (rw32[i] == opcode) | 180 | if (rw32[i] == opcode) |
181 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); | 181 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); |
182 | 182 | ||
183 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); | 183 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); |
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | unsigned int get_ins_mem_width(unsigned long ins_addr) | 187 | unsigned int get_ins_mem_width(unsigned long ins_addr) |
188 | { | 188 | { |
189 | unsigned int opcode; | 189 | unsigned int opcode; |
190 | unsigned char *p; | 190 | unsigned char *p; |
191 | struct prefix_bits prf; | 191 | struct prefix_bits prf; |
192 | int i; | 192 | int i; |
193 | 193 | ||
194 | p = (unsigned char *)ins_addr; | 194 | p = (unsigned char *)ins_addr; |
195 | p += skip_prefix(p, &prf); | 195 | p += skip_prefix(p, &prf); |
196 | p += get_opcode(p, &opcode); | 196 | p += get_opcode(p, &opcode); |
197 | 197 | ||
198 | for (i = 0; i < ARRAY_SIZE(mw8); i++) | 198 | for (i = 0; i < ARRAY_SIZE(mw8); i++) |
199 | if (mw8[i] == opcode) | 199 | if (mw8[i] == opcode) |
200 | return 1; | 200 | return 1; |
201 | 201 | ||
202 | for (i = 0; i < ARRAY_SIZE(mw16); i++) | 202 | for (i = 0; i < ARRAY_SIZE(mw16); i++) |
203 | if (mw16[i] == opcode) | 203 | if (mw16[i] == opcode) |
204 | return 2; | 204 | return 2; |
205 | 205 | ||
206 | for (i = 0; i < ARRAY_SIZE(mw32); i++) | 206 | for (i = 0; i < ARRAY_SIZE(mw32); i++) |
207 | if (mw32[i] == opcode) | 207 | if (mw32[i] == opcode) |
208 | return prf.shorted ? 2 : 4; | 208 | return prf.shorted ? 2 : 4; |
209 | 209 | ||
210 | for (i = 0; i < ARRAY_SIZE(mw64); i++) | 210 | for (i = 0; i < ARRAY_SIZE(mw64); i++) |
211 | if (mw64[i] == opcode) | 211 | if (mw64[i] == opcode) |
212 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); | 212 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); |
213 | 213 | ||
214 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); | 214 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); |
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * Define register ident in mod/rm byte. | 219 | * Define register ident in mod/rm byte. |
220 | * Note: these are NOT the same as in ptrace-abi.h. | 220 | * Note: these are NOT the same as in ptrace-abi.h. |
221 | */ | 221 | */ |
222 | enum { | 222 | enum { |
223 | arg_AL = 0, | 223 | arg_AL = 0, |
224 | arg_CL = 1, | 224 | arg_CL = 1, |
225 | arg_DL = 2, | 225 | arg_DL = 2, |
226 | arg_BL = 3, | 226 | arg_BL = 3, |
227 | arg_AH = 4, | 227 | arg_AH = 4, |
228 | arg_CH = 5, | 228 | arg_CH = 5, |
229 | arg_DH = 6, | 229 | arg_DH = 6, |
230 | arg_BH = 7, | 230 | arg_BH = 7, |
231 | 231 | ||
232 | arg_AX = 0, | 232 | arg_AX = 0, |
233 | arg_CX = 1, | 233 | arg_CX = 1, |
234 | arg_DX = 2, | 234 | arg_DX = 2, |
235 | arg_BX = 3, | 235 | arg_BX = 3, |
236 | arg_SP = 4, | 236 | arg_SP = 4, |
237 | arg_BP = 5, | 237 | arg_BP = 5, |
238 | arg_SI = 6, | 238 | arg_SI = 6, |
239 | arg_DI = 7, | 239 | arg_DI = 7, |
240 | #ifdef __amd64__ | 240 | #ifdef __amd64__ |
241 | arg_R8 = 8, | 241 | arg_R8 = 8, |
242 | arg_R9 = 9, | 242 | arg_R9 = 9, |
243 | arg_R10 = 10, | 243 | arg_R10 = 10, |
244 | arg_R11 = 11, | 244 | arg_R11 = 11, |
245 | arg_R12 = 12, | 245 | arg_R12 = 12, |
246 | arg_R13 = 13, | 246 | arg_R13 = 13, |
247 | arg_R14 = 14, | 247 | arg_R14 = 14, |
248 | arg_R15 = 15 | 248 | arg_R15 = 15 |
249 | #endif | 249 | #endif |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs) | 252 | static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs) |
253 | { | 253 | { |
254 | unsigned char *rv = NULL; | 254 | unsigned char *rv = NULL; |
255 | 255 | ||
256 | switch (no) { | 256 | switch (no) { |
257 | case arg_AL: | 257 | case arg_AL: |
258 | rv = (unsigned char *)®s->ax; | 258 | rv = (unsigned char *)®s->ax; |
259 | break; | 259 | break; |
260 | case arg_BL: | 260 | case arg_BL: |
261 | rv = (unsigned char *)®s->bx; | 261 | rv = (unsigned char *)®s->bx; |
262 | break; | 262 | break; |
263 | case arg_CL: | 263 | case arg_CL: |
264 | rv = (unsigned char *)®s->cx; | 264 | rv = (unsigned char *)®s->cx; |
265 | break; | 265 | break; |
266 | case arg_DL: | 266 | case arg_DL: |
267 | rv = (unsigned char *)®s->dx; | 267 | rv = (unsigned char *)®s->dx; |
268 | break; | 268 | break; |
269 | #ifdef __amd64__ | 269 | #ifdef __amd64__ |
270 | case arg_R8: | 270 | case arg_R8: |
271 | rv = (unsigned char *)®s->r8; | 271 | rv = (unsigned char *)®s->r8; |
272 | break; | 272 | break; |
273 | case arg_R9: | 273 | case arg_R9: |
274 | rv = (unsigned char *)®s->r9; | 274 | rv = (unsigned char *)®s->r9; |
275 | break; | 275 | break; |
276 | case arg_R10: | 276 | case arg_R10: |
277 | rv = (unsigned char *)®s->r10; | 277 | rv = (unsigned char *)®s->r10; |
278 | break; | 278 | break; |
279 | case arg_R11: | 279 | case arg_R11: |
280 | rv = (unsigned char *)®s->r11; | 280 | rv = (unsigned char *)®s->r11; |
281 | break; | 281 | break; |
282 | case arg_R12: | 282 | case arg_R12: |
283 | rv = (unsigned char *)®s->r12; | 283 | rv = (unsigned char *)®s->r12; |
284 | break; | 284 | break; |
285 | case arg_R13: | 285 | case arg_R13: |
286 | rv = (unsigned char *)®s->r13; | 286 | rv = (unsigned char *)®s->r13; |
287 | break; | 287 | break; |
288 | case arg_R14: | 288 | case arg_R14: |
289 | rv = (unsigned char *)®s->r14; | 289 | rv = (unsigned char *)®s->r14; |
290 | break; | 290 | break; |
291 | case arg_R15: | 291 | case arg_R15: |
292 | rv = (unsigned char *)®s->r15; | 292 | rv = (unsigned char *)®s->r15; |
293 | break; | 293 | break; |
294 | #endif | 294 | #endif |
295 | default: | 295 | default: |
296 | break; | 296 | break; |
297 | } | 297 | } |
298 | 298 | ||
299 | if (rv) | 299 | if (rv) |
300 | return rv; | 300 | return rv; |
301 | 301 | ||
302 | if (rex) { | 302 | if (rex) { |
303 | /* | 303 | /* |
304 | * If REX prefix exists, access low bytes of SI etc. | 304 | * If REX prefix exists, access low bytes of SI etc. |
305 | * instead of AH etc. | 305 | * instead of AH etc. |
306 | */ | 306 | */ |
307 | switch (no) { | 307 | switch (no) { |
308 | case arg_SI: | 308 | case arg_SI: |
309 | rv = (unsigned char *)®s->si; | 309 | rv = (unsigned char *)®s->si; |
310 | break; | 310 | break; |
311 | case arg_DI: | 311 | case arg_DI: |
312 | rv = (unsigned char *)®s->di; | 312 | rv = (unsigned char *)®s->di; |
313 | break; | 313 | break; |
314 | case arg_BP: | 314 | case arg_BP: |
315 | rv = (unsigned char *)®s->bp; | 315 | rv = (unsigned char *)®s->bp; |
316 | break; | 316 | break; |
317 | case arg_SP: | 317 | case arg_SP: |
318 | rv = (unsigned char *)®s->sp; | 318 | rv = (unsigned char *)®s->sp; |
319 | break; | 319 | break; |
320 | default: | 320 | default: |
321 | break; | 321 | break; |
322 | } | 322 | } |
323 | } else { | 323 | } else { |
324 | switch (no) { | 324 | switch (no) { |
325 | case arg_AH: | 325 | case arg_AH: |
326 | rv = 1 + (unsigned char *)®s->ax; | 326 | rv = 1 + (unsigned char *)®s->ax; |
327 | break; | 327 | break; |
328 | case arg_BH: | 328 | case arg_BH: |
329 | rv = 1 + (unsigned char *)®s->bx; | 329 | rv = 1 + (unsigned char *)®s->bx; |
330 | break; | 330 | break; |
331 | case arg_CH: | 331 | case arg_CH: |
332 | rv = 1 + (unsigned char *)®s->cx; | 332 | rv = 1 + (unsigned char *)®s->cx; |
333 | break; | 333 | break; |
334 | case arg_DH: | 334 | case arg_DH: |
335 | rv = 1 + (unsigned char *)®s->dx; | 335 | rv = 1 + (unsigned char *)®s->dx; |
336 | break; | 336 | break; |
337 | default: | 337 | default: |
338 | break; | 338 | break; |
339 | } | 339 | } |
340 | } | 340 | } |
341 | 341 | ||
342 | if (!rv) | 342 | if (!rv) |
343 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); | 343 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); |
344 | 344 | ||
345 | return rv; | 345 | return rv; |
346 | } | 346 | } |
347 | 347 | ||
348 | static unsigned long *get_reg_w32(int no, struct pt_regs *regs) | 348 | static unsigned long *get_reg_w32(int no, struct pt_regs *regs) |
349 | { | 349 | { |
350 | unsigned long *rv = NULL; | 350 | unsigned long *rv = NULL; |
351 | 351 | ||
352 | switch (no) { | 352 | switch (no) { |
353 | case arg_AX: | 353 | case arg_AX: |
354 | rv = ®s->ax; | 354 | rv = ®s->ax; |
355 | break; | 355 | break; |
356 | case arg_BX: | 356 | case arg_BX: |
357 | rv = ®s->bx; | 357 | rv = ®s->bx; |
358 | break; | 358 | break; |
359 | case arg_CX: | 359 | case arg_CX: |
360 | rv = ®s->cx; | 360 | rv = ®s->cx; |
361 | break; | 361 | break; |
362 | case arg_DX: | 362 | case arg_DX: |
363 | rv = ®s->dx; | 363 | rv = ®s->dx; |
364 | break; | 364 | break; |
365 | case arg_SP: | 365 | case arg_SP: |
366 | rv = ®s->sp; | 366 | rv = ®s->sp; |
367 | break; | 367 | break; |
368 | case arg_BP: | 368 | case arg_BP: |
369 | rv = ®s->bp; | 369 | rv = ®s->bp; |
370 | break; | 370 | break; |
371 | case arg_SI: | 371 | case arg_SI: |
372 | rv = ®s->si; | 372 | rv = ®s->si; |
373 | break; | 373 | break; |
374 | case arg_DI: | 374 | case arg_DI: |
375 | rv = ®s->di; | 375 | rv = ®s->di; |
376 | break; | 376 | break; |
377 | #ifdef __amd64__ | 377 | #ifdef __amd64__ |
378 | case arg_R8: | 378 | case arg_R8: |
379 | rv = ®s->r8; | 379 | rv = ®s->r8; |
380 | break; | 380 | break; |
381 | case arg_R9: | 381 | case arg_R9: |
382 | rv = ®s->r9; | 382 | rv = ®s->r9; |
383 | break; | 383 | break; |
384 | case arg_R10: | 384 | case arg_R10: |
385 | rv = ®s->r10; | 385 | rv = ®s->r10; |
386 | break; | 386 | break; |
387 | case arg_R11: | 387 | case arg_R11: |
388 | rv = ®s->r11; | 388 | rv = ®s->r11; |
389 | break; | 389 | break; |
390 | case arg_R12: | 390 | case arg_R12: |
391 | rv = ®s->r12; | 391 | rv = ®s->r12; |
392 | break; | 392 | break; |
393 | case arg_R13: | 393 | case arg_R13: |
394 | rv = ®s->r13; | 394 | rv = ®s->r13; |
395 | break; | 395 | break; |
396 | case arg_R14: | 396 | case arg_R14: |
397 | rv = ®s->r14; | 397 | rv = ®s->r14; |
398 | break; | 398 | break; |
399 | case arg_R15: | 399 | case arg_R15: |
400 | rv = ®s->r15; | 400 | rv = ®s->r15; |
401 | break; | 401 | break; |
402 | #endif | 402 | #endif |
403 | default: | 403 | default: |
404 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); | 404 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); |
405 | } | 405 | } |
406 | 406 | ||
407 | return rv; | 407 | return rv; |
408 | } | 408 | } |
409 | 409 | ||
410 | unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs) | 410 | unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs) |
411 | { | 411 | { |
412 | unsigned int opcode; | 412 | unsigned int opcode; |
413 | int reg; | 413 | int reg; |
414 | unsigned char *p; | 414 | unsigned char *p; |
415 | struct prefix_bits prf; | 415 | struct prefix_bits prf; |
416 | int i; | 416 | int i; |
417 | unsigned long rv; | ||
418 | 417 | ||
419 | p = (unsigned char *)ins_addr; | 418 | p = (unsigned char *)ins_addr; |
420 | p += skip_prefix(p, &prf); | 419 | p += skip_prefix(p, &prf); |
421 | p += get_opcode(p, &opcode); | 420 | p += get_opcode(p, &opcode); |
422 | for (i = 0; i < ARRAY_SIZE(reg_rop); i++) | 421 | for (i = 0; i < ARRAY_SIZE(reg_rop); i++) |
423 | if (reg_rop[i] == opcode) { | 422 | if (reg_rop[i] == opcode) |
424 | rv = REG_READ; | ||
425 | goto do_work; | 423 | goto do_work; |
426 | } | ||
427 | 424 | ||
428 | for (i = 0; i < ARRAY_SIZE(reg_wop); i++) | 425 | for (i = 0; i < ARRAY_SIZE(reg_wop); i++) |
429 | if (reg_wop[i] == opcode) { | 426 | if (reg_wop[i] == opcode) |
430 | rv = REG_WRITE; | ||
431 | goto do_work; | 427 | goto do_work; |
432 | } | ||
433 | 428 | ||
434 | printk(KERN_ERR "mmiotrace: Not a register instruction, opcode " | 429 | printk(KERN_ERR "mmiotrace: Not a register instruction, opcode " |
435 | "0x%02x\n", opcode); | 430 | "0x%02x\n", opcode); |
436 | goto err; | 431 | goto err; |
437 | 432 | ||
438 | do_work: | 433 | do_work: |
439 | /* for STOS, source register is fixed */ | 434 | /* for STOS, source register is fixed */ |
440 | if (opcode == 0xAA || opcode == 0xAB) { | 435 | if (opcode == 0xAA || opcode == 0xAB) { |
441 | reg = arg_AX; | 436 | reg = arg_AX; |
442 | } else { | 437 | } else { |
443 | unsigned char mod_rm = *p; | 438 | unsigned char mod_rm = *p; |
444 | reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3); | 439 | reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3); |
445 | } | 440 | } |
446 | switch (get_ins_reg_width(ins_addr)) { | 441 | switch (get_ins_reg_width(ins_addr)) { |
447 | case 1: | 442 | case 1: |
448 | return *get_reg_w8(reg, prf.rex, regs); | 443 | return *get_reg_w8(reg, prf.rex, regs); |
449 | 444 | ||
450 | case 2: | 445 | case 2: |
451 | return *(unsigned short *)get_reg_w32(reg, regs); | 446 | return *(unsigned short *)get_reg_w32(reg, regs); |
452 | 447 | ||
453 | case 4: | 448 | case 4: |
454 | return *(unsigned int *)get_reg_w32(reg, regs); | 449 | return *(unsigned int *)get_reg_w32(reg, regs); |
455 | 450 | ||
456 | #ifdef __amd64__ | 451 | #ifdef __amd64__ |
457 | case 8: | 452 | case 8: |
458 | return *(unsigned long *)get_reg_w32(reg, regs); | 453 | return *(unsigned long *)get_reg_w32(reg, regs); |
459 | #endif | 454 | #endif |
460 | 455 | ||
461 | default: | 456 | default: |
462 | printk(KERN_ERR "mmiotrace: Error width# %d\n", reg); | 457 | printk(KERN_ERR "mmiotrace: Error width# %d\n", reg); |
463 | } | 458 | } |
464 | 459 | ||
465 | err: | 460 | err: |
466 | return 0; | 461 | return 0; |
467 | } | 462 | } |
468 | 463 | ||
469 | unsigned long get_ins_imm_val(unsigned long ins_addr) | 464 | unsigned long get_ins_imm_val(unsigned long ins_addr) |
470 | { | 465 | { |
471 | unsigned int opcode; | 466 | unsigned int opcode; |
472 | unsigned char mod_rm; | 467 | unsigned char mod_rm; |
473 | unsigned char mod; | 468 | unsigned char mod; |
474 | unsigned char *p; | 469 | unsigned char *p; |
475 | struct prefix_bits prf; | 470 | struct prefix_bits prf; |
476 | int i; | 471 | int i; |
477 | unsigned long rv; | ||
478 | 472 | ||
479 | p = (unsigned char *)ins_addr; | 473 | p = (unsigned char *)ins_addr; |
480 | p += skip_prefix(p, &prf); | 474 | p += skip_prefix(p, &prf); |
481 | p += get_opcode(p, &opcode); | 475 | p += get_opcode(p, &opcode); |
482 | for (i = 0; i < ARRAY_SIZE(imm_wop); i++) | 476 | for (i = 0; i < ARRAY_SIZE(imm_wop); i++) |
483 | if (imm_wop[i] == opcode) { | 477 | if (imm_wop[i] == opcode) |
484 | rv = IMM_WRITE; | ||
485 | goto do_work; | 478 | goto do_work; |
486 | } | ||
487 | 479 | ||
488 | printk(KERN_ERR "mmiotrace: Not an immediate instruction, opcode " | 480 | printk(KERN_ERR "mmiotrace: Not an immediate instruction, opcode " |
489 | "0x%02x\n", opcode); | 481 | "0x%02x\n", opcode); |
490 | goto err; | 482 | goto err; |
491 | 483 | ||
492 | do_work: | 484 | do_work: |
493 | mod_rm = *p; | 485 | mod_rm = *p; |
494 | mod = mod_rm >> 6; | 486 | mod = mod_rm >> 6; |
495 | p++; | 487 | p++; |
496 | switch (mod) { | 488 | switch (mod) { |
497 | case 0: | 489 | case 0: |
498 | /* if r/m is 5 we have a 32 disp (IA32 Manual 3, Table 2-2) */ | 490 | /* if r/m is 5 we have a 32 disp (IA32 Manual 3, Table 2-2) */ |
499 | /* AMD64: XXX Check for address size prefix? */ | 491 | /* AMD64: XXX Check for address size prefix? */ |
500 | if ((mod_rm & 0x7) == 0x5) | 492 | if ((mod_rm & 0x7) == 0x5) |
501 | p += 4; | 493 | p += 4; |
502 | break; | 494 | break; |
503 | 495 | ||
504 | case 1: | 496 | case 1: |
505 | p += 1; | 497 | p += 1; |
506 | break; | 498 | break; |
507 | 499 | ||
508 | case 2: | 500 | case 2: |
509 | p += 4; | 501 | p += 4; |
510 | break; | 502 | break; |
511 | 503 | ||
512 | case 3: | 504 | case 3: |
513 | default: | 505 | default: |
514 | printk(KERN_ERR "mmiotrace: not a memory access instruction " | 506 | printk(KERN_ERR "mmiotrace: not a memory access instruction " |
515 | "at 0x%lx, rm_mod=0x%02x\n", | 507 | "at 0x%lx, rm_mod=0x%02x\n", |
516 | ins_addr, mod_rm); | 508 | ins_addr, mod_rm); |
517 | } | 509 | } |
518 | 510 | ||
519 | switch (get_ins_reg_width(ins_addr)) { | 511 | switch (get_ins_reg_width(ins_addr)) { |
520 | case 1: | 512 | case 1: |
521 | return *(unsigned char *)p; | 513 | return *(unsigned char *)p; |
522 | 514 | ||
523 | case 2: | 515 | case 2: |
524 | return *(unsigned short *)p; | 516 | return *(unsigned short *)p; |
525 | 517 | ||
526 | case 4: | 518 | case 4: |
527 | return *(unsigned int *)p; | 519 | return *(unsigned int *)p; |
528 | 520 | ||
529 | #ifdef __amd64__ | 521 | #ifdef __amd64__ |
530 | case 8: | 522 | case 8: |
531 | return *(unsigned long *)p; | 523 | return *(unsigned long *)p; |
532 | #endif | 524 | #endif |
533 | 525 | ||
534 | default: | 526 | default: |
535 | printk(KERN_ERR "mmiotrace: Error: width.\n"); | 527 | printk(KERN_ERR "mmiotrace: Error: width.\n"); |
536 | } | 528 | } |
537 | 529 | ||
538 | err: | 530 | err: |
539 | return 0; | 531 | return 0; |
540 | } | 532 | } |
541 | 533 |