cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

s390-iommu.c (9899B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * IOMMU API for s390 PCI devices
      4 *
      5 * Copyright IBM Corp. 2015
      6 * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
      7 */
      8
      9#include <linux/pci.h>
     10#include <linux/iommu.h>
     11#include <linux/iommu-helper.h>
     12#include <linux/sizes.h>
     13#include <asm/pci_dma.h>
     14
     15/*
     16 * Physically contiguous memory regions can be mapped with 4 KiB alignment,
     17 * we allow all page sizes that are an order of 4KiB (no special large page
     18 * support so far).
     19 */
     20#define S390_IOMMU_PGSIZES	(~0xFFFUL)
     21
     22static const struct iommu_ops s390_iommu_ops;
     23
     24struct s390_domain {
     25	struct iommu_domain	domain;
     26	struct list_head	devices;
     27	unsigned long		*dma_table;
     28	spinlock_t		dma_table_lock;
     29	spinlock_t		list_lock;
     30};
     31
     32struct s390_domain_device {
     33	struct list_head	list;
     34	struct zpci_dev		*zdev;
     35};
     36
     37static struct s390_domain *to_s390_domain(struct iommu_domain *dom)
     38{
     39	return container_of(dom, struct s390_domain, domain);
     40}
     41
     42static bool s390_iommu_capable(enum iommu_cap cap)
     43{
     44	switch (cap) {
     45	case IOMMU_CAP_CACHE_COHERENCY:
     46		return true;
     47	case IOMMU_CAP_INTR_REMAP:
     48		return true;
     49	default:
     50		return false;
     51	}
     52}
     53
     54static struct iommu_domain *s390_domain_alloc(unsigned domain_type)
     55{
     56	struct s390_domain *s390_domain;
     57
     58	if (domain_type != IOMMU_DOMAIN_UNMANAGED)
     59		return NULL;
     60
     61	s390_domain = kzalloc(sizeof(*s390_domain), GFP_KERNEL);
     62	if (!s390_domain)
     63		return NULL;
     64
     65	s390_domain->dma_table = dma_alloc_cpu_table();
     66	if (!s390_domain->dma_table) {
     67		kfree(s390_domain);
     68		return NULL;
     69	}
     70
     71	spin_lock_init(&s390_domain->dma_table_lock);
     72	spin_lock_init(&s390_domain->list_lock);
     73	INIT_LIST_HEAD(&s390_domain->devices);
     74
     75	return &s390_domain->domain;
     76}
     77
     78static void s390_domain_free(struct iommu_domain *domain)
     79{
     80	struct s390_domain *s390_domain = to_s390_domain(domain);
     81
     82	dma_cleanup_tables(s390_domain->dma_table);
     83	kfree(s390_domain);
     84}
     85
     86static int s390_iommu_attach_device(struct iommu_domain *domain,
     87				    struct device *dev)
     88{
     89	struct s390_domain *s390_domain = to_s390_domain(domain);
     90	struct zpci_dev *zdev = to_zpci_dev(dev);
     91	struct s390_domain_device *domain_device;
     92	unsigned long flags;
     93	int cc, rc;
     94
     95	if (!zdev)
     96		return -ENODEV;
     97
     98	domain_device = kzalloc(sizeof(*domain_device), GFP_KERNEL);
     99	if (!domain_device)
    100		return -ENOMEM;
    101
    102	if (zdev->dma_table && !zdev->s390_domain) {
    103		cc = zpci_dma_exit_device(zdev);
    104		if (cc) {
    105			rc = -EIO;
    106			goto out_free;
    107		}
    108	}
    109
    110	if (zdev->s390_domain)
    111		zpci_unregister_ioat(zdev, 0);
    112
    113	zdev->dma_table = s390_domain->dma_table;
    114	cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
    115				virt_to_phys(zdev->dma_table));
    116	if (cc) {
    117		rc = -EIO;
    118		goto out_restore;
    119	}
    120
    121	spin_lock_irqsave(&s390_domain->list_lock, flags);
    122	/* First device defines the DMA range limits */
    123	if (list_empty(&s390_domain->devices)) {
    124		domain->geometry.aperture_start = zdev->start_dma;
    125		domain->geometry.aperture_end = zdev->end_dma;
    126		domain->geometry.force_aperture = true;
    127	/* Allow only devices with identical DMA range limits */
    128	} else if (domain->geometry.aperture_start != zdev->start_dma ||
    129		   domain->geometry.aperture_end != zdev->end_dma) {
    130		rc = -EINVAL;
    131		spin_unlock_irqrestore(&s390_domain->list_lock, flags);
    132		goto out_restore;
    133	}
    134	domain_device->zdev = zdev;
    135	zdev->s390_domain = s390_domain;
    136	list_add(&domain_device->list, &s390_domain->devices);
    137	spin_unlock_irqrestore(&s390_domain->list_lock, flags);
    138
    139	return 0;
    140
    141out_restore:
    142	if (!zdev->s390_domain) {
    143		zpci_dma_init_device(zdev);
    144	} else {
    145		zdev->dma_table = zdev->s390_domain->dma_table;
    146		zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma,
    147				   virt_to_phys(zdev->dma_table));
    148	}
    149out_free:
    150	kfree(domain_device);
    151
    152	return rc;
    153}
    154
    155static void s390_iommu_detach_device(struct iommu_domain *domain,
    156				     struct device *dev)
    157{
    158	struct s390_domain *s390_domain = to_s390_domain(domain);
    159	struct zpci_dev *zdev = to_zpci_dev(dev);
    160	struct s390_domain_device *domain_device, *tmp;
    161	unsigned long flags;
    162	int found = 0;
    163
    164	if (!zdev)
    165		return;
    166
    167	spin_lock_irqsave(&s390_domain->list_lock, flags);
    168	list_for_each_entry_safe(domain_device, tmp, &s390_domain->devices,
    169				 list) {
    170		if (domain_device->zdev == zdev) {
    171			list_del(&domain_device->list);
    172			kfree(domain_device);
    173			found = 1;
    174			break;
    175		}
    176	}
    177	spin_unlock_irqrestore(&s390_domain->list_lock, flags);
    178
    179	if (found && (zdev->s390_domain == s390_domain)) {
    180		zdev->s390_domain = NULL;
    181		zpci_unregister_ioat(zdev, 0);
    182		zpci_dma_init_device(zdev);
    183	}
    184}
    185
    186static struct iommu_device *s390_iommu_probe_device(struct device *dev)
    187{
    188	struct zpci_dev *zdev = to_zpci_dev(dev);
    189
    190	return &zdev->iommu_dev;
    191}
    192
    193static void s390_iommu_release_device(struct device *dev)
    194{
    195	struct zpci_dev *zdev = to_zpci_dev(dev);
    196	struct iommu_domain *domain;
    197
    198	/*
    199	 * This is a workaround for a scenario where the IOMMU API common code
    200	 * "forgets" to call the detach_dev callback: After binding a device
    201	 * to vfio-pci and completing the VFIO_SET_IOMMU ioctl (which triggers
    202	 * the attach_dev), removing the device via
    203	 * "echo 1 > /sys/bus/pci/devices/.../remove" won't trigger detach_dev,
    204	 * only release_device will be called via the BUS_NOTIFY_REMOVED_DEVICE
    205	 * notifier.
    206	 *
    207	 * So let's call detach_dev from here if it hasn't been called before.
    208	 */
    209	if (zdev && zdev->s390_domain) {
    210		domain = iommu_get_domain_for_dev(dev);
    211		if (domain)
    212			s390_iommu_detach_device(domain, dev);
    213	}
    214}
    215
    216static int s390_iommu_update_trans(struct s390_domain *s390_domain,
    217				   phys_addr_t pa, dma_addr_t dma_addr,
    218				   size_t size, int flags)
    219{
    220	struct s390_domain_device *domain_device;
    221	phys_addr_t page_addr = pa & PAGE_MASK;
    222	dma_addr_t start_dma_addr = dma_addr;
    223	unsigned long irq_flags, nr_pages, i;
    224	unsigned long *entry;
    225	int rc = 0;
    226
    227	if (dma_addr < s390_domain->domain.geometry.aperture_start ||
    228	    dma_addr + size > s390_domain->domain.geometry.aperture_end)
    229		return -EINVAL;
    230
    231	nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
    232	if (!nr_pages)
    233		return 0;
    234
    235	spin_lock_irqsave(&s390_domain->dma_table_lock, irq_flags);
    236	for (i = 0; i < nr_pages; i++) {
    237		entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr);
    238		if (!entry) {
    239			rc = -ENOMEM;
    240			goto undo_cpu_trans;
    241		}
    242		dma_update_cpu_trans(entry, page_addr, flags);
    243		page_addr += PAGE_SIZE;
    244		dma_addr += PAGE_SIZE;
    245	}
    246
    247	spin_lock(&s390_domain->list_lock);
    248	list_for_each_entry(domain_device, &s390_domain->devices, list) {
    249		rc = zpci_refresh_trans((u64) domain_device->zdev->fh << 32,
    250					start_dma_addr, nr_pages * PAGE_SIZE);
    251		if (rc)
    252			break;
    253	}
    254	spin_unlock(&s390_domain->list_lock);
    255
    256undo_cpu_trans:
    257	if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)) {
    258		flags = ZPCI_PTE_INVALID;
    259		while (i-- > 0) {
    260			page_addr -= PAGE_SIZE;
    261			dma_addr -= PAGE_SIZE;
    262			entry = dma_walk_cpu_trans(s390_domain->dma_table,
    263						   dma_addr);
    264			if (!entry)
    265				break;
    266			dma_update_cpu_trans(entry, page_addr, flags);
    267		}
    268	}
    269	spin_unlock_irqrestore(&s390_domain->dma_table_lock, irq_flags);
    270
    271	return rc;
    272}
    273
    274static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova,
    275			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
    276{
    277	struct s390_domain *s390_domain = to_s390_domain(domain);
    278	int flags = ZPCI_PTE_VALID, rc = 0;
    279
    280	if (!(prot & IOMMU_READ))
    281		return -EINVAL;
    282
    283	if (!(prot & IOMMU_WRITE))
    284		flags |= ZPCI_TABLE_PROTECTED;
    285
    286	rc = s390_iommu_update_trans(s390_domain, paddr, iova,
    287				     size, flags);
    288
    289	return rc;
    290}
    291
    292static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
    293					   dma_addr_t iova)
    294{
    295	struct s390_domain *s390_domain = to_s390_domain(domain);
    296	unsigned long *sto, *pto, *rto, flags;
    297	unsigned int rtx, sx, px;
    298	phys_addr_t phys = 0;
    299
    300	if (iova < domain->geometry.aperture_start ||
    301	    iova > domain->geometry.aperture_end)
    302		return 0;
    303
    304	rtx = calc_rtx(iova);
    305	sx = calc_sx(iova);
    306	px = calc_px(iova);
    307	rto = s390_domain->dma_table;
    308
    309	spin_lock_irqsave(&s390_domain->dma_table_lock, flags);
    310	if (rto && reg_entry_isvalid(rto[rtx])) {
    311		sto = get_rt_sto(rto[rtx]);
    312		if (sto && reg_entry_isvalid(sto[sx])) {
    313			pto = get_st_pto(sto[sx]);
    314			if (pto && pt_entry_isvalid(pto[px]))
    315				phys = pto[px] & ZPCI_PTE_ADDR_MASK;
    316		}
    317	}
    318	spin_unlock_irqrestore(&s390_domain->dma_table_lock, flags);
    319
    320	return phys;
    321}
    322
    323static size_t s390_iommu_unmap(struct iommu_domain *domain,
    324			       unsigned long iova, size_t size,
    325			       struct iommu_iotlb_gather *gather)
    326{
    327	struct s390_domain *s390_domain = to_s390_domain(domain);
    328	int flags = ZPCI_PTE_INVALID;
    329	phys_addr_t paddr;
    330	int rc;
    331
    332	paddr = s390_iommu_iova_to_phys(domain, iova);
    333	if (!paddr)
    334		return 0;
    335
    336	rc = s390_iommu_update_trans(s390_domain, paddr, iova,
    337				     size, flags);
    338	if (rc)
    339		return 0;
    340
    341	return size;
    342}
    343
    344int zpci_init_iommu(struct zpci_dev *zdev)
    345{
    346	int rc = 0;
    347
    348	rc = iommu_device_sysfs_add(&zdev->iommu_dev, NULL, NULL,
    349				    "s390-iommu.%08x", zdev->fid);
    350	if (rc)
    351		goto out_err;
    352
    353	rc = iommu_device_register(&zdev->iommu_dev, &s390_iommu_ops, NULL);
    354	if (rc)
    355		goto out_sysfs;
    356
    357	return 0;
    358
    359out_sysfs:
    360	iommu_device_sysfs_remove(&zdev->iommu_dev);
    361
    362out_err:
    363	return rc;
    364}
    365
    366void zpci_destroy_iommu(struct zpci_dev *zdev)
    367{
    368	iommu_device_unregister(&zdev->iommu_dev);
    369	iommu_device_sysfs_remove(&zdev->iommu_dev);
    370}
    371
    372static const struct iommu_ops s390_iommu_ops = {
    373	.capable = s390_iommu_capable,
    374	.domain_alloc = s390_domain_alloc,
    375	.probe_device = s390_iommu_probe_device,
    376	.release_device = s390_iommu_release_device,
    377	.device_group = generic_device_group,
    378	.pgsize_bitmap = S390_IOMMU_PGSIZES,
    379	.default_domain_ops = &(const struct iommu_domain_ops) {
    380		.attach_dev	= s390_iommu_attach_device,
    381		.detach_dev	= s390_iommu_detach_device,
    382		.map		= s390_iommu_map,
    383		.unmap		= s390_iommu_unmap,
    384		.iova_to_phys	= s390_iommu_iova_to_phys,
    385		.free		= s390_domain_free,
    386	}
    387};
    388
    389static int __init s390_iommu_init(void)
    390{
    391	return bus_set_iommu(&pci_bus_type, &s390_iommu_ops);
    392}
    393subsys_initcall(s390_iommu_init);