Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8de1481 authored by Arjan van de Ven's avatar Arjan van de Ven Committed by Jesse Barnes
Browse files

resource: allow MMIO exclusivity for device drivers



Device drivers that use pci_request_regions() (and similar APIs) have a
reasonable expectation that they are the only ones accessing their device.
As part of the e1000e hunt, we were afraid that some userland (X or some
bootsplash stuff) was mapping the MMIO region that the driver thought it
had exclusively via /dev/mem or via various sysfs resource mappings.

This patch adds the option for device drivers to cause their reserved
regions to the "banned from /dev/mem use" list, so now both kernel memory
and device-exclusive MMIO regions are banned.
NOTE: This is only active when CONFIG_STRICT_DEVMEM is set.

In addition to the config option, a kernel parameter iomem=relaxed is
provided for the cases where developers want to diagnose, in the field,
drivers issues from userspace.

Reviewed-by: default avatarMatthew Wilcox <willy@linux.intel.com>
Signed-off-by: default avatarArjan van de Ven <arjan@linux.intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 23616941
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -918,6 +918,10 @@ and is between 256 and 4096 characters. It is defined in the file

	inttest=	[IA64]

	iomem=		Disable strict checking of access to MMIO memory
		strict	regions from userspace.
		relaxed

	iommu=		[x86]
		off
		force
+2 −0
Original line number Diff line number Diff line
@@ -328,6 +328,8 @@ int devmem_is_allowed(unsigned long pagenr)
{
	if (pagenr <= 256)
		return 1;
	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
		return 0;
	if (!page_is_ram(pagenr))
		return 1;
	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -888,6 +888,8 @@ int devmem_is_allowed(unsigned long pagenr)
{
	if (pagenr <= 256)
		return 1;
	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
		return 0;
	if (!page_is_ram(pagenr))
		return 1;
	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -4807,7 +4807,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
		}
	}

	err = pci_request_selected_regions(pdev,
	err = pci_request_selected_regions_exclusive(pdev,
	                                  pci_select_bars(pdev, IORESOURCE_MEM),
	                                  e1000e_driver_name);
	if (err)
+3 −0
Original line number Diff line number Diff line
@@ -620,6 +620,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
	vma->vm_pgoff += start >> PAGE_SHIFT;
	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;

	if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(start))
		return -EINVAL;

	return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
}

Loading