diff options
author | James Morse <james.morse@arm.com> | 2015-10-29 12:50:43 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-11-03 14:54:00 -0500 |
commit | 1b4bb2eaa9b2583521611b4aa978f9f499c92cd4 (patch) | |
tree | 30ce8bb09a0c5d957a12499fc8608d39c2eac008 | |
parent | 4644321fd3c119a819ab24fd2bc2d1f9bca4a695 (diff) |
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: 6e3f26456009 "vfio/platform: read and write support for the device fd"
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Tested-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r-- | drivers/vfio/platform/vfio_platform_common.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index e43efb5e92bf..8c216de883e3 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c | |||
@@ -307,17 +307,17 @@ static long vfio_platform_ioctl(void *device_data, | |||
307 | return -ENOTTY; | 307 | return -ENOTTY; |
308 | } | 308 | } |
309 | 309 | ||
310 | static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, | 310 | static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg, |
311 | char __user *buf, size_t count, | 311 | char __user *buf, size_t count, |
312 | loff_t off) | 312 | loff_t off) |
313 | { | 313 | { |
314 | unsigned int done = 0; | 314 | unsigned int done = 0; |
315 | 315 | ||
316 | if (!reg.ioaddr) { | 316 | if (!reg->ioaddr) { |
317 | reg.ioaddr = | 317 | reg->ioaddr = |
318 | ioremap_nocache(reg.addr, reg.size); | 318 | ioremap_nocache(reg->addr, reg->size); |
319 | 319 | ||
320 | if (!reg.ioaddr) | 320 | if (!reg->ioaddr) |
321 | return -ENOMEM; | 321 | return -ENOMEM; |
322 | } | 322 | } |
323 | 323 | ||
@@ -327,7 +327,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, | |||
327 | if (count >= 4 && !(off % 4)) { | 327 | if (count >= 4 && !(off % 4)) { |
328 | u32 val; | 328 | u32 val; |
329 | 329 | ||
330 | val = ioread32(reg.ioaddr + off); | 330 | val = ioread32(reg->ioaddr + off); |
331 | if (copy_to_user(buf, &val, 4)) | 331 | if (copy_to_user(buf, &val, 4)) |
332 | goto err; | 332 | goto err; |
333 | 333 | ||
@@ -335,7 +335,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, | |||
335 | } else if (count >= 2 && !(off % 2)) { | 335 | } else if (count >= 2 && !(off % 2)) { |
336 | u16 val; | 336 | u16 val; |
337 | 337 | ||
338 | val = ioread16(reg.ioaddr + off); | 338 | val = ioread16(reg->ioaddr + off); |
339 | if (copy_to_user(buf, &val, 2)) | 339 | if (copy_to_user(buf, &val, 2)) |
340 | goto err; | 340 | goto err; |
341 | 341 | ||
@@ -343,7 +343,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, | |||
343 | } else { | 343 | } else { |
344 | u8 val; | 344 | u8 val; |
345 | 345 | ||
346 | val = ioread8(reg.ioaddr + off); | 346 | val = ioread8(reg->ioaddr + off); |
347 | if (copy_to_user(buf, &val, 1)) | 347 | if (copy_to_user(buf, &val, 1)) |
348 | goto err; | 348 | goto err; |
349 | 349 | ||
@@ -376,7 +376,7 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf, | |||
376 | return -EINVAL; | 376 | return -EINVAL; |
377 | 377 | ||
378 | if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) | 378 | if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) |
379 | return vfio_platform_read_mmio(vdev->regions[index], | 379 | return vfio_platform_read_mmio(&vdev->regions[index], |
380 | buf, count, off); | 380 | buf, count, off); |
381 | else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) | 381 | else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) |
382 | return -EINVAL; /* not implemented */ | 382 | return -EINVAL; /* not implemented */ |
@@ -384,17 +384,17 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf, | |||
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | } | 385 | } |
386 | 386 | ||
387 | static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, | 387 | static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg, |
388 | const char __user *buf, size_t count, | 388 | const char __user *buf, size_t count, |
389 | loff_t off) | 389 | loff_t off) |
390 | { | 390 | { |
391 | unsigned int done = 0; | 391 | unsigned int done = 0; |
392 | 392 | ||
393 | if (!reg.ioaddr) { | 393 | if (!reg->ioaddr) { |
394 | reg.ioaddr = | 394 | reg->ioaddr = |
395 | ioremap_nocache(reg.addr, reg.size); | 395 | ioremap_nocache(reg->addr, reg->size); |
396 | 396 | ||
397 | if (!reg.ioaddr) | 397 | if (!reg->ioaddr) |
398 | return -ENOMEM; | 398 | return -ENOMEM; |
399 | } | 399 | } |
400 | 400 | ||
@@ -406,7 +406,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, | |||
406 | 406 | ||
407 | if (copy_from_user(&val, buf, 4)) | 407 | if (copy_from_user(&val, buf, 4)) |
408 | goto err; | 408 | goto err; |
409 | iowrite32(val, reg.ioaddr + off); | 409 | iowrite32(val, reg->ioaddr + off); |
410 | 410 | ||
411 | filled = 4; | 411 | filled = 4; |
412 | } else if (count >= 2 && !(off % 2)) { | 412 | } else if (count >= 2 && !(off % 2)) { |
@@ -414,7 +414,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, | |||
414 | 414 | ||
415 | if (copy_from_user(&val, buf, 2)) | 415 | if (copy_from_user(&val, buf, 2)) |
416 | goto err; | 416 | goto err; |
417 | iowrite16(val, reg.ioaddr + off); | 417 | iowrite16(val, reg->ioaddr + off); |
418 | 418 | ||
419 | filled = 2; | 419 | filled = 2; |
420 | } else { | 420 | } else { |
@@ -422,7 +422,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, | |||
422 | 422 | ||
423 | if (copy_from_user(&val, buf, 1)) | 423 | if (copy_from_user(&val, buf, 1)) |
424 | goto err; | 424 | goto err; |
425 | iowrite8(val, reg.ioaddr + off); | 425 | iowrite8(val, reg->ioaddr + off); |
426 | 426 | ||
427 | filled = 1; | 427 | filled = 1; |
428 | } | 428 | } |
@@ -452,7 +452,7 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf, | |||
452 | return -EINVAL; | 452 | return -EINVAL; |
453 | 453 | ||
454 | if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) | 454 | if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) |
455 | return vfio_platform_write_mmio(vdev->regions[index], | 455 | return vfio_platform_write_mmio(&vdev->regions[index], |
456 | buf, count, off); | 456 | buf, count, off); |
457 | else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) | 457 | else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) |
458 | return -EINVAL; /* not implemented */ | 458 | return -EINVAL; /* not implemented */ |