diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 261 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 42 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 9 |
3 files changed, 254 insertions, 58 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 45be9499c97..98f230f6a28 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -41,9 +41,13 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock); | |||
41 | static LIST_HEAD(iommu_pd_list); | 41 | static LIST_HEAD(iommu_pd_list); |
42 | static DEFINE_SPINLOCK(iommu_pd_list_lock); | 42 | static DEFINE_SPINLOCK(iommu_pd_list_lock); |
43 | 43 | ||
44 | #ifdef CONFIG_IOMMU_API | 44 | /* |
45 | * Domain for untranslated devices - only allocated | ||
46 | * if iommu=pt passed on kernel cmd line. | ||
47 | */ | ||
48 | static struct protection_domain *pt_domain; | ||
49 | |||
45 | static struct iommu_ops amd_iommu_ops; | 50 | static struct iommu_ops amd_iommu_ops; |
46 | #endif | ||
47 | 51 | ||
48 | /* | 52 | /* |
49 | * general struct to manage commands send to an IOMMU | 53 | * general struct to manage commands send to an IOMMU |
@@ -61,14 +65,11 @@ static u64 *alloc_pte(struct protection_domain *domain, | |||
61 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, | 65 | static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, |
62 | unsigned long start_page, | 66 | unsigned long start_page, |
63 | unsigned int pages); | 67 | unsigned int pages); |
68 | static void reset_iommu_command_buffer(struct amd_iommu *iommu); | ||
64 | static u64 *fetch_pte(struct protection_domain *domain, | 69 | static u64 *fetch_pte(struct protection_domain *domain, |
65 | unsigned long address, int map_size); | 70 | unsigned long address, int map_size); |
66 | static void update_domain(struct protection_domain *domain); | 71 | static void update_domain(struct protection_domain *domain); |
67 | 72 | ||
68 | #ifndef BUS_NOTIFY_UNBOUND_DRIVER | ||
69 | #define BUS_NOTIFY_UNBOUND_DRIVER 0x0005 | ||
70 | #endif | ||
71 | |||
72 | #ifdef CONFIG_AMD_IOMMU_STATS | 73 | #ifdef CONFIG_AMD_IOMMU_STATS |
73 | 74 | ||
74 | /* | 75 | /* |
@@ -141,7 +142,25 @@ static int iommu_has_npcache(struct amd_iommu *iommu) | |||
141 | * | 142 | * |
142 | ****************************************************************************/ | 143 | ****************************************************************************/ |
143 | 144 | ||
144 | static void iommu_print_event(void *__evt) | 145 | static void dump_dte_entry(u16 devid) |
146 | { | ||
147 | int i; | ||
148 | |||
149 | for (i = 0; i < 8; ++i) | ||
150 | pr_err("AMD-Vi: DTE[%d]: %08x\n", i, | ||
151 | amd_iommu_dev_table[devid].data[i]); | ||
152 | } | ||
153 | |||
154 | static void dump_command(unsigned long phys_addr) | ||
155 | { | ||
156 | struct iommu_cmd *cmd = phys_to_virt(phys_addr); | ||
157 | int i; | ||
158 | |||
159 | for (i = 0; i < 4; ++i) | ||
160 | pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); | ||
161 | } | ||
162 | |||
163 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) | ||
145 | { | 164 | { |
146 | u32 *event = __evt; | 165 | u32 *event = __evt; |
147 | int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; | 166 | int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; |
@@ -150,7 +169,7 @@ static void iommu_print_event(void *__evt) | |||
150 | int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; | 169 | int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; |
151 | u64 address = (u64)(((u64)event[3]) << 32) | event[2]; | 170 | u64 address = (u64)(((u64)event[3]) << 32) | event[2]; |
152 | 171 | ||
153 | printk(KERN_ERR "AMD IOMMU: Event logged ["); | 172 | printk(KERN_ERR "AMD-Vi: Event logged ["); |
154 | 173 | ||
155 | switch (type) { | 174 | switch (type) { |
156 | case EVENT_TYPE_ILL_DEV: | 175 | case EVENT_TYPE_ILL_DEV: |
@@ -158,6 +177,7 @@ static void iommu_print_event(void *__evt) | |||
158 | "address=0x%016llx flags=0x%04x]\n", | 177 | "address=0x%016llx flags=0x%04x]\n", |
159 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), | 178 | PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), |
160 | address, flags); | 179 | address, flags); |
180 | dump_dte_entry(devid); | ||
161 | break; | 181 | break; |
162 | case EVENT_TYPE_IO_FAULT: | 182 | case EVENT_TYPE_IO_FAULT: |
163 | printk("IO_PAGE_FAULT device=%02x:%02x.%x " | 183 | printk("IO_PAGE_FAULT device=%02x:%02x.%x " |
@@ -179,6 +199,8 @@ static void iommu_print_event(void *__evt) | |||
179 | break; | 199 | break; |
180 | case EVENT_TYPE_ILL_CMD: | 200 | case EVENT_TYPE_ILL_CMD: |
181 | printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); | 201 | printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); |
202 | reset_iommu_command_buffer(iommu); | ||
203 | dump_command(address); | ||
182 | break; | 204 | break; |
183 | case EVENT_TYPE_CMD_HARD_ERR: | 205 | case EVENT_TYPE_CMD_HARD_ERR: |
184 | printk("COMMAND_HARDWARE_ERROR address=0x%016llx " | 206 | printk("COMMAND_HARDWARE_ERROR address=0x%016llx " |
@@ -212,7 +234,7 @@ static void iommu_poll_events(struct amd_iommu *iommu) | |||
212 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); | 234 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); |
213 | 235 | ||
214 | while (head != tail) { | 236 | while (head != tail) { |
215 | iommu_print_event(iommu->evt_buf + head); | 237 | iommu_print_event(iommu, iommu->evt_buf + head); |
216 | head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; | 238 | head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; |
217 | } | 239 | } |
218 | 240 | ||
@@ -299,8 +321,11 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu) | |||
299 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; | 321 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; |
300 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); | 322 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); |
301 | 323 | ||
302 | if (unlikely(i == EXIT_LOOP_COUNT)) | 324 | if (unlikely(i == EXIT_LOOP_COUNT)) { |
303 | panic("AMD IOMMU: Completion wait loop failed\n"); | 325 | spin_unlock(&iommu->lock); |
326 | reset_iommu_command_buffer(iommu); | ||
327 | spin_lock(&iommu->lock); | ||
328 | } | ||
304 | } | 329 | } |
305 | 330 | ||
306 | /* | 331 | /* |
@@ -448,37 +473,67 @@ static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid) | |||
448 | } | 473 | } |
449 | 474 | ||
450 | /* | 475 | /* |
476 | * This function flushes one domain on one IOMMU | ||
477 | */ | ||
478 | static void flush_domain_on_iommu(struct amd_iommu *iommu, u16 domid) | ||
479 | { | ||
480 | struct iommu_cmd cmd; | ||
481 | unsigned long flags; | ||
482 | |||
483 | __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, | ||
484 | domid, 1, 1); | ||
485 | |||
486 | spin_lock_irqsave(&iommu->lock, flags); | ||
487 | __iommu_queue_command(iommu, &cmd); | ||
488 | __iommu_completion_wait(iommu); | ||
489 | __iommu_wait_for_completion(iommu); | ||
490 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
491 | } | ||
492 | |||
493 | static void flush_all_domains_on_iommu(struct amd_iommu *iommu) | ||
494 | { | ||
495 | int i; | ||
496 | |||
497 | for (i = 1; i < MAX_DOMAIN_ID; ++i) { | ||
498 | if (!test_bit(i, amd_iommu_pd_alloc_bitmap)) | ||
499 | continue; | ||
500 | flush_domain_on_iommu(iommu, i); | ||
501 | } | ||
502 | |||
503 | } | ||
504 | |||
505 | /* | ||
451 | * This function is used to flush the IO/TLB for a given protection domain | 506 | * This function is used to flush the IO/TLB for a given protection domain |
452 | * on every IOMMU in the system | 507 | * on every IOMMU in the system |
453 | */ | 508 | */ |
454 | static void iommu_flush_domain(u16 domid) | 509 | static void iommu_flush_domain(u16 domid) |
455 | { | 510 | { |
456 | unsigned long flags; | ||
457 | struct amd_iommu *iommu; | 511 | struct amd_iommu *iommu; |
458 | struct iommu_cmd cmd; | ||
459 | 512 | ||
460 | INC_STATS_COUNTER(domain_flush_all); | 513 | INC_STATS_COUNTER(domain_flush_all); |
461 | 514 | ||
462 | __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, | 515 | for_each_iommu(iommu) |
463 | domid, 1, 1); | 516 | flush_domain_on_iommu(iommu, domid); |
464 | |||
465 | for_each_iommu(iommu) { | ||
466 | spin_lock_irqsave(&iommu->lock, flags); | ||
467 | __iommu_queue_command(iommu, &cmd); | ||
468 | __iommu_completion_wait(iommu); | ||
469 | __iommu_wait_for_completion(iommu); | ||
470 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
471 | } | ||
472 | } | 517 | } |
473 | 518 | ||
474 | void amd_iommu_flush_all_domains(void) | 519 | void amd_iommu_flush_all_domains(void) |
475 | { | 520 | { |
521 | struct amd_iommu *iommu; | ||
522 | |||
523 | for_each_iommu(iommu) | ||
524 | flush_all_domains_on_iommu(iommu); | ||
525 | } | ||
526 | |||
527 | static void flush_all_devices_for_iommu(struct amd_iommu *iommu) | ||
528 | { | ||
476 | int i; | 529 | int i; |
477 | 530 | ||
478 | for (i = 1; i < MAX_DOMAIN_ID; ++i) { | 531 | for (i = 0; i <= amd_iommu_last_bdf; ++i) { |
479 | if (!test_bit(i, amd_iommu_pd_alloc_bitmap)) | 532 | if (iommu != amd_iommu_rlookup_table[i]) |
480 | continue; | 533 | continue; |
481 | iommu_flush_domain(i); | 534 | |
535 | iommu_queue_inv_dev_entry(iommu, i); | ||
536 | iommu_completion_wait(iommu); | ||
482 | } | 537 | } |
483 | } | 538 | } |
484 | 539 | ||
@@ -501,6 +556,22 @@ static void flush_devices_by_domain(struct protection_domain *domain) | |||
501 | } | 556 | } |
502 | } | 557 | } |
503 | 558 | ||
559 | static void reset_iommu_command_buffer(struct amd_iommu *iommu) | ||
560 | { | ||
561 | pr_err("AMD-Vi: Resetting IOMMU command buffer\n"); | ||
562 | |||
563 | if (iommu->reset_in_progress) | ||
564 | panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n"); | ||
565 | |||
566 | iommu->reset_in_progress = true; | ||
567 | |||
568 | amd_iommu_reset_cmd_buffer(iommu); | ||
569 | flush_all_devices_for_iommu(iommu); | ||
570 | flush_all_domains_on_iommu(iommu); | ||
571 | |||
572 | iommu->reset_in_progress = false; | ||
573 | } | ||
574 | |||
504 | void amd_iommu_flush_all_devices(void) | 575 | void amd_iommu_flush_all_devices(void) |
505 | { | 576 | { |
506 | flush_devices_by_domain(NULL); | 577 | flush_devices_by_domain(NULL); |
@@ -1077,19 +1148,36 @@ static struct protection_domain *domain_for_device(u16 devid) | |||
1077 | static void set_dte_entry(u16 devid, struct protection_domain *domain) | 1148 | static void set_dte_entry(u16 devid, struct protection_domain *domain) |
1078 | { | 1149 | { |
1079 | u64 pte_root = virt_to_phys(domain->pt_root); | 1150 | u64 pte_root = virt_to_phys(domain->pt_root); |
1080 | unsigned long flags; | ||
1081 | 1151 | ||
1082 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) | 1152 | pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK) |
1083 | << DEV_ENTRY_MODE_SHIFT; | 1153 | << DEV_ENTRY_MODE_SHIFT; |
1084 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; | 1154 | pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV; |
1085 | 1155 | ||
1086 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | ||
1087 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); | ||
1088 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); | ||
1089 | amd_iommu_dev_table[devid].data[2] = domain->id; | 1156 | amd_iommu_dev_table[devid].data[2] = domain->id; |
1157 | amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root); | ||
1158 | amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); | ||
1090 | 1159 | ||
1091 | amd_iommu_pd_table[devid] = domain; | 1160 | amd_iommu_pd_table[devid] = domain; |
1092 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 1161 | } |
1162 | |||
1163 | /* | ||
1164 | * If a device is not yet associated with a domain, this function does | ||
1165 | * assigns it visible for the hardware | ||
1166 | */ | ||
1167 | static void __attach_device(struct amd_iommu *iommu, | ||
1168 | struct protection_domain *domain, | ||
1169 | u16 devid) | ||
1170 | { | ||
1171 | /* lock domain */ | ||
1172 | spin_lock(&domain->lock); | ||
1173 | |||
1174 | /* update DTE entry */ | ||
1175 | set_dte_entry(devid, domain); | ||
1176 | |||
1177 | domain->dev_cnt += 1; | ||
1178 | |||
1179 | /* ready */ | ||
1180 | spin_unlock(&domain->lock); | ||
1093 | } | 1181 | } |
1094 | 1182 | ||
1095 | /* | 1183 | /* |
@@ -1100,17 +1188,17 @@ static void attach_device(struct amd_iommu *iommu, | |||
1100 | struct protection_domain *domain, | 1188 | struct protection_domain *domain, |
1101 | u16 devid) | 1189 | u16 devid) |
1102 | { | 1190 | { |
1103 | /* set the DTE entry */ | 1191 | unsigned long flags; |
1104 | set_dte_entry(devid, domain); | ||
1105 | 1192 | ||
1106 | /* increase reference counter */ | 1193 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
1107 | domain->dev_cnt += 1; | 1194 | __attach_device(iommu, domain, devid); |
1195 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | ||
1108 | 1196 | ||
1109 | /* | 1197 | /* |
1110 | * We might boot into a crash-kernel here. The crashed kernel | 1198 | * We might boot into a crash-kernel here. The crashed kernel |
1111 | * left the caches in the IOMMU dirty. So we have to flush | 1199 | * left the caches in the IOMMU dirty. So we have to flush |
1112 | * here to evict all dirty stuff. | 1200 | * here to evict all dirty stuff. |
1113 | */ | 1201 | */ |
1114 | iommu_queue_inv_dev_entry(iommu, devid); | 1202 | iommu_queue_inv_dev_entry(iommu, devid); |
1115 | iommu_flush_tlb_pde(iommu, domain->id); | 1203 | iommu_flush_tlb_pde(iommu, domain->id); |
1116 | } | 1204 | } |
@@ -1137,6 +1225,15 @@ static void __detach_device(struct protection_domain *domain, u16 devid) | |||
1137 | 1225 | ||
1138 | /* ready */ | 1226 | /* ready */ |
1139 | spin_unlock(&domain->lock); | 1227 | spin_unlock(&domain->lock); |
1228 | |||
1229 | /* | ||
1230 | * If we run in passthrough mode the device must be assigned to the | ||
1231 | * passthrough domain if it is detached from any other domain | ||
1232 | */ | ||
1233 | if (iommu_pass_through) { | ||
1234 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; | ||
1235 | __attach_device(iommu, pt_domain, devid); | ||
1236 | } | ||
1140 | } | 1237 | } |
1141 | 1238 | ||
1142 | /* | 1239 | /* |
@@ -1182,6 +1279,8 @@ static int device_change_notifier(struct notifier_block *nb, | |||
1182 | case BUS_NOTIFY_UNBOUND_DRIVER: | 1279 | case BUS_NOTIFY_UNBOUND_DRIVER: |
1183 | if (!domain) | 1280 | if (!domain) |
1184 | goto out; | 1281 | goto out; |
1282 | if (iommu_pass_through) | ||
1283 | break; | ||
1185 | detach_device(domain, devid); | 1284 | detach_device(domain, devid); |
1186 | break; | 1285 | break; |
1187 | case BUS_NOTIFY_ADD_DEVICE: | 1286 | case BUS_NOTIFY_ADD_DEVICE: |
@@ -1312,12 +1411,15 @@ static int get_device_resources(struct device *dev, | |||
1312 | 1411 | ||
1313 | static void update_device_table(struct protection_domain *domain) | 1412 | static void update_device_table(struct protection_domain *domain) |
1314 | { | 1413 | { |
1414 | unsigned long flags; | ||
1315 | int i; | 1415 | int i; |
1316 | 1416 | ||
1317 | for (i = 0; i <= amd_iommu_last_bdf; ++i) { | 1417 | for (i = 0; i <= amd_iommu_last_bdf; ++i) { |
1318 | if (amd_iommu_pd_table[i] != domain) | 1418 | if (amd_iommu_pd_table[i] != domain) |
1319 | continue; | 1419 | continue; |
1420 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | ||
1320 | set_dte_entry(i, domain); | 1421 | set_dte_entry(i, domain); |
1422 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | ||
1321 | } | 1423 | } |
1322 | } | 1424 | } |
1323 | 1425 | ||
@@ -2058,19 +2160,47 @@ static void cleanup_domain(struct protection_domain *domain) | |||
2058 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 2160 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
2059 | } | 2161 | } |
2060 | 2162 | ||
2061 | static int amd_iommu_domain_init(struct iommu_domain *dom) | 2163 | static void protection_domain_free(struct protection_domain *domain) |
2164 | { | ||
2165 | if (!domain) | ||
2166 | return; | ||
2167 | |||
2168 | if (domain->id) | ||
2169 | domain_id_free(domain->id); | ||
2170 | |||
2171 | kfree(domain); | ||
2172 | } | ||
2173 | |||
2174 | static struct protection_domain *protection_domain_alloc(void) | ||
2062 | { | 2175 | { |
2063 | struct protection_domain *domain; | 2176 | struct protection_domain *domain; |
2064 | 2177 | ||
2065 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | 2178 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); |
2066 | if (!domain) | 2179 | if (!domain) |
2067 | return -ENOMEM; | 2180 | return NULL; |
2068 | 2181 | ||
2069 | spin_lock_init(&domain->lock); | 2182 | spin_lock_init(&domain->lock); |
2070 | domain->mode = PAGE_MODE_3_LEVEL; | ||
2071 | domain->id = domain_id_alloc(); | 2183 | domain->id = domain_id_alloc(); |
2072 | if (!domain->id) | 2184 | if (!domain->id) |
2185 | goto out_err; | ||
2186 | |||
2187 | return domain; | ||
2188 | |||
2189 | out_err: | ||
2190 | kfree(domain); | ||
2191 | |||
2192 | return NULL; | ||
2193 | } | ||
2194 | |||
2195 | static int amd_iommu_domain_init(struct iommu_domain *dom) | ||
2196 | { | ||
2197 | struct protection_domain *domain; | ||
2198 | |||
2199 | domain = protection_domain_alloc(); | ||
2200 | if (!domain) | ||
2073 | goto out_free; | 2201 | goto out_free; |
2202 | |||
2203 | domain->mode = PAGE_MODE_3_LEVEL; | ||
2074 | domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL); | 2204 | domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL); |
2075 | if (!domain->pt_root) | 2205 | if (!domain->pt_root) |
2076 | goto out_free; | 2206 | goto out_free; |
@@ -2080,7 +2210,7 @@ static int amd_iommu_domain_init(struct iommu_domain *dom) | |||
2080 | return 0; | 2210 | return 0; |
2081 | 2211 | ||
2082 | out_free: | 2212 | out_free: |
2083 | kfree(domain); | 2213 | protection_domain_free(domain); |
2084 | 2214 | ||
2085 | return -ENOMEM; | 2215 | return -ENOMEM; |
2086 | } | 2216 | } |
@@ -2249,3 +2379,46 @@ static struct iommu_ops amd_iommu_ops = { | |||
2249 | .domain_has_cap = amd_iommu_domain_has_cap, | 2379 | .domain_has_cap = amd_iommu_domain_has_cap, |
2250 | }; | 2380 | }; |
2251 | 2381 | ||
2382 | /***************************************************************************** | ||
2383 | * | ||
2384 | * The next functions do a basic initialization of IOMMU for pass through | ||
2385 | * mode | ||
2386 | * | ||
2387 | * In passthrough mode the IOMMU is initialized and enabled but not used for | ||
2388 | * DMA-API translation. | ||
2389 | * | ||
2390 | *****************************************************************************/ | ||
2391 | |||
2392 | int __init amd_iommu_init_passthrough(void) | ||
2393 | { | ||
2394 | struct pci_dev *dev = NULL; | ||
2395 | u16 devid, devid2; | ||
2396 | |||
2397 | /* allocate passthroug domain */ | ||
2398 | pt_domain = protection_domain_alloc(); | ||
2399 | if (!pt_domain) | ||
2400 | return -ENOMEM; | ||
2401 | |||
2402 | pt_domain->mode |= PAGE_MODE_NONE; | ||
2403 | |||
2404 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
2405 | struct amd_iommu *iommu; | ||
2406 | |||
2407 | devid = calc_devid(dev->bus->number, dev->devfn); | ||
2408 | if (devid > amd_iommu_last_bdf) | ||
2409 | continue; | ||
2410 | |||
2411 | devid2 = amd_iommu_alias_table[devid]; | ||
2412 | |||
2413 | iommu = amd_iommu_rlookup_table[devid2]; | ||
2414 | if (!iommu) | ||
2415 | continue; | ||
2416 | |||
2417 | __attach_device(iommu, pt_domain, devid); | ||
2418 | __attach_device(iommu, pt_domain, devid2); | ||
2419 | } | ||
2420 | |||
2421 | pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); | ||
2422 | |||
2423 | return 0; | ||
2424 | } | ||
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index c1b17e97252..b4b61d462dc 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -252,7 +252,7 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) | |||
252 | /* Function to enable the hardware */ | 252 | /* Function to enable the hardware */ |
253 | static void iommu_enable(struct amd_iommu *iommu) | 253 | static void iommu_enable(struct amd_iommu *iommu) |
254 | { | 254 | { |
255 | printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at %s cap 0x%hx\n", | 255 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n", |
256 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | 256 | dev_name(&iommu->dev->dev), iommu->cap_ptr); |
257 | 257 | ||
258 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); | 258 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); |
@@ -435,6 +435,20 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu) | |||
435 | } | 435 | } |
436 | 436 | ||
437 | /* | 437 | /* |
438 | * This function resets the command buffer if the IOMMU stopped fetching | ||
439 | * commands from it. | ||
440 | */ | ||
441 | void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu) | ||
442 | { | ||
443 | iommu_feature_disable(iommu, CONTROL_CMDBUF_EN); | ||
444 | |||
445 | writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); | ||
446 | writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | ||
447 | |||
448 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); | ||
449 | } | ||
450 | |||
451 | /* | ||
438 | * This function writes the command buffer address to the hardware and | 452 | * This function writes the command buffer address to the hardware and |
439 | * enables it. | 453 | * enables it. |
440 | */ | 454 | */ |
@@ -450,11 +464,7 @@ static void iommu_enable_command_buffer(struct amd_iommu *iommu) | |||
450 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, | 464 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, |
451 | &entry, sizeof(entry)); | 465 | &entry, sizeof(entry)); |
452 | 466 | ||
453 | /* set head and tail to zero manually */ | 467 | amd_iommu_reset_cmd_buffer(iommu); |
454 | writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); | ||
455 | writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | ||
456 | |||
457 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); | ||
458 | } | 468 | } |
459 | 469 | ||
460 | static void __init free_command_buffer(struct amd_iommu *iommu) | 470 | static void __init free_command_buffer(struct amd_iommu *iommu) |
@@ -858,7 +868,7 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
858 | switch (*p) { | 868 | switch (*p) { |
859 | case ACPI_IVHD_TYPE: | 869 | case ACPI_IVHD_TYPE: |
860 | 870 | ||
861 | DUMP_printk("IOMMU: device: %02x:%02x.%01x cap: %04x " | 871 | DUMP_printk("device: %02x:%02x.%01x cap: %04x " |
862 | "seg: %d flags: %01x info %04x\n", | 872 | "seg: %d flags: %01x info %04x\n", |
863 | PCI_BUS(h->devid), PCI_SLOT(h->devid), | 873 | PCI_BUS(h->devid), PCI_SLOT(h->devid), |
864 | PCI_FUNC(h->devid), h->cap_ptr, | 874 | PCI_FUNC(h->devid), h->cap_ptr, |
@@ -902,7 +912,7 @@ static int __init iommu_setup_msi(struct amd_iommu *iommu) | |||
902 | 912 | ||
903 | r = request_irq(iommu->dev->irq, amd_iommu_int_handler, | 913 | r = request_irq(iommu->dev->irq, amd_iommu_int_handler, |
904 | IRQF_SAMPLE_RANDOM, | 914 | IRQF_SAMPLE_RANDOM, |
905 | "AMD IOMMU", | 915 | "AMD-Vi", |
906 | NULL); | 916 | NULL); |
907 | 917 | ||
908 | if (r) { | 918 | if (r) { |
@@ -1150,7 +1160,7 @@ int __init amd_iommu_init(void) | |||
1150 | 1160 | ||
1151 | 1161 | ||
1152 | if (no_iommu) { | 1162 | if (no_iommu) { |
1153 | printk(KERN_INFO "AMD IOMMU disabled by kernel command line\n"); | 1163 | printk(KERN_INFO "AMD-Vi disabled by kernel command line\n"); |
1154 | return 0; | 1164 | return 0; |
1155 | } | 1165 | } |
1156 | 1166 | ||
@@ -1242,22 +1252,28 @@ int __init amd_iommu_init(void) | |||
1242 | if (ret) | 1252 | if (ret) |
1243 | goto free; | 1253 | goto free; |
1244 | 1254 | ||
1245 | ret = amd_iommu_init_dma_ops(); | 1255 | if (iommu_pass_through) |
1256 | ret = amd_iommu_init_passthrough(); | ||
1257 | else | ||
1258 | ret = amd_iommu_init_dma_ops(); | ||
1246 | if (ret) | 1259 | if (ret) |
1247 | goto free; | 1260 | goto free; |
1248 | 1261 | ||
1249 | enable_iommus(); | 1262 | enable_iommus(); |
1250 | 1263 | ||
1251 | printk(KERN_INFO "AMD IOMMU: device isolation "); | 1264 | if (iommu_pass_through) |
1265 | goto out; | ||
1266 | |||
1267 | printk(KERN_INFO "AMD-Vi: device isolation "); | ||
1252 | if (amd_iommu_isolate) | 1268 | if (amd_iommu_isolate) |
1253 | printk("enabled\n"); | 1269 | printk("enabled\n"); |
1254 | else | 1270 | else |
1255 | printk("disabled\n"); | 1271 | printk("disabled\n"); |
1256 | 1272 | ||
1257 | if (amd_iommu_unmap_flush) | 1273 | if (amd_iommu_unmap_flush) |
1258 | printk(KERN_INFO "AMD IOMMU: IO/TLB flush on unmap enabled\n"); | 1274 | printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n"); |
1259 | else | 1275 | else |
1260 | printk(KERN_INFO "AMD IOMMU: Lazy IO/TLB flushing enabled\n"); | 1276 | printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); |
1261 | 1277 | ||
1262 | out: | 1278 | out: |
1263 | return ret; | 1279 | return ret; |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 1a041bcf506..873aa079d16 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -32,7 +32,14 @@ int no_iommu __read_mostly; | |||
32 | /* Set this to 1 if there is a HW IOMMU in the system */ | 32 | /* Set this to 1 if there is a HW IOMMU in the system */ |
33 | int iommu_detected __read_mostly = 0; | 33 | int iommu_detected __read_mostly = 0; |
34 | 34 | ||
35 | int iommu_pass_through; | 35 | /* |
36 | * This variable becomes 1 if iommu=pt is passed on the kernel command line. | ||
37 | * If this variable is 1, IOMMU implementations do no DMA ranslation for | ||
38 | * devices and allow every device to access to whole physical memory. This is | ||
39 | * useful if a user want to use an IOMMU only for KVM device assignment to | ||
40 | * guests and not for driver dma translation. | ||
41 | */ | ||
42 | int iommu_pass_through __read_mostly; | ||
36 | 43 | ||
37 | dma_addr_t bad_dma_address __read_mostly = 0; | 44 | dma_addr_t bad_dma_address __read_mostly = 0; |
38 | EXPORT_SYMBOL(bad_dma_address); | 45 | EXPORT_SYMBOL(bad_dma_address); |