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

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
...@@ -307,17 +307,17 @@ static long vfio_platform_ioctl(void *device_data, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment