···320320 amd_iommu= [HW,X86-84]321321 Pass parameters to the AMD IOMMU driver in the system.322322 Possible values are:323323- isolate - enable device isolation (each device, as far324324- as possible, will get its own protection325325- domain) [default]326326- share - put every device behind one IOMMU into the327327- same protection domain328323 fullflush - enable flushing of IO/TLB entries when329324 they are unmapped. Otherwise they are330325 flushed before they will be reused, which
+3
arch/x86/include/asm/amd_iommu_types.h
···2121#define _ASM_X86_AMD_IOMMU_TYPES_H22222323#include <linux/types.h>2424+#include <linux/mutex.h>2425#include <linux/list.h>2526#include <linux/spinlock.h>2627···141140142141/* constants to configure the command buffer */143142#define CMD_BUFFER_SIZE 8192143143+#define CMD_BUFFER_UNINITIALIZED 1144144#define CMD_BUFFER_ENTRIES 512145145#define MMIO_CMD_SIZE_SHIFT 56146146#define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT)···239237 struct list_head list; /* for list of all protection domains */240238 struct list_head dev_list; /* List of all devices in this domain */241239 spinlock_t lock; /* mostly used to lock the page table*/240240+ struct mutex api_lock; /* protect page tables in the iommu-api path */242241 u16 id; /* the domain id written to the device table */243242 int mode; /* paging mode (0-6 levels) */244243 u64 *pt_root; /* page table root pointer */
+14-6
arch/x86/kernel/amd_iommu.c
···118118 return false;119119120120 /* No device or no PCI device */121121- if (!dev || dev->bus != &pci_bus_type)121121+ if (dev->bus != &pci_bus_type)122122 return false;123123124124 devid = get_device_id(dev);···392392 u32 tail, head;393393 u8 *target;394394395395+ WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);395396 tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);396397 target = iommu->cmd_buf + tail;397398 memcpy_toio(target, cmd, sizeof(*cmd));···21872186 struct dma_ops_domain *dma_dom;21882187 u16 devid;2189218821902190- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {21892189+ for_each_pci_dev(dev) {2191219021922191 /* Do we handle this device? */21932192 if (!check_device(&dev->dev))···22992298 list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) {23002299 struct device *dev = dev_data->dev;2301230023022302- do_detach(dev);23012301+ __detach_device(dev);23032302 atomic_set(&dev_data->bind, 0);23042303 }23052304···23282327 return NULL;2329232823302329 spin_lock_init(&domain->lock);23302330+ mutex_init(&domain->api_lock);23312331 domain->id = domain_id_alloc();23322332 if (!domain->id)23332333 goto out_err;···2381237923822380 free_pagetable(domain);2383238123842384- domain_id_free(domain->id);23852385-23862386- kfree(domain);23822382+ protection_domain_free(domain);2387238323882384 dom->priv = NULL;23892385}···24562456 iova &= PAGE_MASK;24572457 paddr &= PAGE_MASK;2458245824592459+ mutex_lock(&domain->api_lock);24602460+24592461 for (i = 0; i < npages; ++i) {24602462 ret = iommu_map_page(domain, iova, paddr, prot, PM_MAP_4k);24612463 if (ret)···24662464 iova += PAGE_SIZE;24672465 paddr += PAGE_SIZE;24682466 }24672467+24682468+ mutex_unlock(&domain->api_lock);2469246924702470 return 0;24712471}···2481247724822478 iova &= PAGE_MASK;2483247924802480+ mutex_lock(&domain->api_lock);24812481+24842482 for (i = 0; i < npages; ++i) {24852483 iommu_unmap_page(domain, iova, PM_MAP_4k);24862484 iova += PAGE_SIZE;24872485 }2488248624892487 iommu_flush_tlb_pde(domain);24882488+24892489+ mutex_unlock(&domain->api_lock);24902490}2491249124922492static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
+33-15
arch/x86/kernel/amd_iommu_init.c
···138138bool amd_iommu_np_cache __read_mostly;139139140140/*141141- * Set to true if ACPI table parsing and hardware intialization went properly141141+ * The ACPI table parsing functions set this variable on an error142142 */143143-static bool amd_iommu_initialized;143143+static int __initdata amd_iommu_init_err;144144145145/*146146 * List of protection domains - used during resume···391391 */392392 for (i = 0; i < table->length; ++i)393393 checksum += p[i];394394- if (checksum != 0)394394+ if (checksum != 0) {395395 /* ACPI table corrupt */396396- return -ENODEV;396396+ amd_iommu_init_err = -ENODEV;397397+ return 0;398398+ }397399398400 p += IVRS_HEADER_LENGTH;399401···438436 if (cmd_buf == NULL)439437 return NULL;440438441441- iommu->cmd_buf_size = CMD_BUFFER_SIZE;439439+ iommu->cmd_buf_size = CMD_BUFFER_SIZE | CMD_BUFFER_UNINITIALIZED;442440443441 return cmd_buf;444442}···474472 &entry, sizeof(entry));475473476474 amd_iommu_reset_cmd_buffer(iommu);475475+ iommu->cmd_buf_size &= ~(CMD_BUFFER_UNINITIALIZED);477476}478477479478static void __init free_command_buffer(struct amd_iommu *iommu)480479{481480 free_pages((unsigned long)iommu->cmd_buf,482482- get_order(iommu->cmd_buf_size));481481+ get_order(iommu->cmd_buf_size & ~(CMD_BUFFER_UNINITIALIZED)));483482}484483485484/* allocates the memory where the IOMMU will log its events to */···923920 h->mmio_phys);924921925922 iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL);926926- if (iommu == NULL)927927- return -ENOMEM;923923+ if (iommu == NULL) {924924+ amd_iommu_init_err = -ENOMEM;925925+ return 0;926926+ }927927+928928 ret = init_iommu_one(iommu, h);929929- if (ret)930930- return ret;929929+ if (ret) {930930+ amd_iommu_init_err = ret;931931+ return 0;932932+ }931933 break;932934 default:933935 break;···941933942934 }943935 WARN_ON(p != end);944944-945945- amd_iommu_initialized = true;946936947937 return 0;948938}···12171211 if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0)12181212 return -ENODEV;1219121312141214+ ret = amd_iommu_init_err;12151215+ if (ret)12161216+ goto out;12171217+12201218 dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE);12211219 alias_table_size = tbl_size(ALIAS_TABLE_ENTRY_SIZE);12221220 rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE);···12801270 if (acpi_table_parse("IVRS", init_iommu_all) != 0)12811271 goto free;1282127212831283- if (!amd_iommu_initialized)12731273+ if (amd_iommu_init_err) {12741274+ ret = amd_iommu_init_err;12841275 goto free;12761276+ }1285127712861278 if (acpi_table_parse("IVRS", init_memory_definitions) != 0)12871279 goto free;12801280+12811281+ if (amd_iommu_init_err) {12821282+ ret = amd_iommu_init_err;12831283+ goto free;12841284+ }1288128512891286 ret = sysdev_class_register(&amd_iommu_sysdev_class);12901287 if (ret)···13051288 if (ret)13061289 goto free;1307129012911291+ enable_iommus();12921292+13081293 if (iommu_pass_through)13091294 ret = amd_iommu_init_passthrough();13101295 else···13181299 amd_iommu_init_api();1319130013201301 amd_iommu_init_notifier();13211321-13221322- enable_iommus();1323130213241303 if (iommu_pass_through)13251304 goto out;···13321315 return ret;1333131613341317free:13181318+ disable_iommus();1335131913361320 amd_iommu_uninit_devices();13371321
+14-1
arch/x86/kernel/aperture_64.c
···393393 for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {394394 int bus;395395 int dev_base, dev_limit;396396+ u32 ctl;396397397398 bus = bus_dev_ranges[i].bus;398399 dev_base = bus_dev_ranges[i].dev_base;···407406 gart_iommu_aperture = 1;408407 x86_init.iommu.iommu_init = gart_iommu_init;409408410410- aper_order = (read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL) >> 1) & 7;409409+ ctl = read_pci_config(bus, slot, 3,410410+ AMD64_GARTAPERTURECTL);411411+412412+ /*413413+ * Before we do anything else disable the GART. It may414414+ * still be enabled if we boot into a crash-kernel here.415415+ * Reconfiguring the GART while it is enabled could have416416+ * unknown side-effects.417417+ */418418+ ctl &= ~GARTEN;419419+ write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);420420+421421+ aper_order = (ctl >> 1) & 7;411422 aper_size = (32 * 1024 * 1024) << aper_order;412423 aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;413424 aper_base <<= 25;
···565565566566 enable_gart_translation(dev, __pa(agp_gatt_table));567567 }568568+569569+ /* Flush the GART-TLB to remove stale entries */570570+ k8_flush_garts();568571}569572570573/*
+1-1
lib/dma-debug.c
···570570 * Now parse out the first token and use it as the name for the571571 * driver to filter for.572572 */573573- for (i = 0; i < NAME_MAX_LEN; ++i) {573573+ for (i = 0; i < NAME_MAX_LEN - 1; ++i) {574574 current_driver_name[i] = buf[i];575575 if (isspace(buf[i]) || buf[i] == ' ' || buf[i] == 0)576576 break;