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

Commit 1b4bb2ea authored by James Morse's avatar James Morse Committed by Alex Williamson
Browse files

vfio/platform: store mapped memory in region, instead of an on-stack copy



vfio_platform_{read,write}_mmio() call ioremap_nocache() to map
a region of io memory, which they store in struct vfio_platform_region to
be eventually re-used, or unmapped by vfio_platform_regions_cleanup().

These functions receive a copy of their struct vfio_platform_region
argument on the stack - so these mapped areas are always allocated, and
always leaked.

Pass this argument as a pointer instead.

Fixes: 6e3f2645 "vfio/platform: read and write support for the device fd"
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Acked-by: default avatarBaptiste Reynal <b.reynal@virtualopensystems.com>
Tested-by: default avatarBaptiste Reynal <b.reynal@virtualopensystems.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 4644321f
Loading
Loading
Loading
Loading
+18 −18
Original line number Original line Diff line number Diff line
@@ -307,17 +307,17 @@ static long vfio_platform_ioctl(void *device_data,
	return -ENOTTY;
	return -ENOTTY;
}
}


static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg,
				       char __user *buf, size_t count,
				       char __user *buf, size_t count,
				       loff_t off)
				       loff_t off)
{
{
	unsigned int done = 0;
	unsigned int done = 0;


	if (!reg.ioaddr) {
	if (!reg->ioaddr) {
		reg.ioaddr =
		reg->ioaddr =
			ioremap_nocache(reg.addr, reg.size);
			ioremap_nocache(reg->addr, reg->size);


		if (!reg.ioaddr)
		if (!reg->ioaddr)
			return -ENOMEM;
			return -ENOMEM;
	}
	}


@@ -327,7 +327,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
		if (count >= 4 && !(off % 4)) {
		if (count >= 4 && !(off % 4)) {
			u32 val;
			u32 val;


			val = ioread32(reg.ioaddr + off);
			val = ioread32(reg->ioaddr + off);
			if (copy_to_user(buf, &val, 4))
			if (copy_to_user(buf, &val, 4))
				goto err;
				goto err;


@@ -335,7 +335,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
		} else if (count >= 2 && !(off % 2)) {
		} else if (count >= 2 && !(off % 2)) {
			u16 val;
			u16 val;


			val = ioread16(reg.ioaddr + off);
			val = ioread16(reg->ioaddr + off);
			if (copy_to_user(buf, &val, 2))
			if (copy_to_user(buf, &val, 2))
				goto err;
				goto err;


@@ -343,7 +343,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
		} else {
		} else {
			u8 val;
			u8 val;


			val = ioread8(reg.ioaddr + off);
			val = ioread8(reg->ioaddr + off);
			if (copy_to_user(buf, &val, 1))
			if (copy_to_user(buf, &val, 1))
				goto err;
				goto err;


@@ -376,7 +376,7 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
		return -EINVAL;
		return -EINVAL;


	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
		return vfio_platform_read_mmio(vdev->regions[index],
		return vfio_platform_read_mmio(&vdev->regions[index],
							buf, count, off);
							buf, count, off);
	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
		return -EINVAL; /* not implemented */
		return -EINVAL; /* not implemented */
@@ -384,17 +384,17 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
	return -EINVAL;
	return -EINVAL;
}
}


static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg,
					const char __user *buf, size_t count,
					const char __user *buf, size_t count,
					loff_t off)
					loff_t off)
{
{
	unsigned int done = 0;
	unsigned int done = 0;


	if (!reg.ioaddr) {
	if (!reg->ioaddr) {
		reg.ioaddr =
		reg->ioaddr =
			ioremap_nocache(reg.addr, reg.size);
			ioremap_nocache(reg->addr, reg->size);


		if (!reg.ioaddr)
		if (!reg->ioaddr)
			return -ENOMEM;
			return -ENOMEM;
	}
	}


@@ -406,7 +406,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,


			if (copy_from_user(&val, buf, 4))
			if (copy_from_user(&val, buf, 4))
				goto err;
				goto err;
			iowrite32(val, reg.ioaddr + off);
			iowrite32(val, reg->ioaddr + off);


			filled = 4;
			filled = 4;
		} else if (count >= 2 && !(off % 2)) {
		} else if (count >= 2 && !(off % 2)) {
@@ -414,7 +414,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,


			if (copy_from_user(&val, buf, 2))
			if (copy_from_user(&val, buf, 2))
				goto err;
				goto err;
			iowrite16(val, reg.ioaddr + off);
			iowrite16(val, reg->ioaddr + off);


			filled = 2;
			filled = 2;
		} else {
		} else {
@@ -422,7 +422,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,


			if (copy_from_user(&val, buf, 1))
			if (copy_from_user(&val, buf, 1))
				goto err;
				goto err;
			iowrite8(val, reg.ioaddr + off);
			iowrite8(val, reg->ioaddr + off);


			filled = 1;
			filled = 1;
		}
		}
@@ -452,7 +452,7 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
		return -EINVAL;
		return -EINVAL;


	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
	if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
		return vfio_platform_write_mmio(vdev->regions[index],
		return vfio_platform_write_mmio(&vdev->regions[index],
							buf, count, off);
							buf, count, off);
	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
	else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
		return -EINVAL; /* not implemented */
		return -EINVAL; /* not implemented */