Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756942AbaKTOLq (ORCPT ); Thu, 20 Nov 2014 09:11:46 -0500 Received: from mail-pa0-f53.google.com ([209.85.220.53]:38279 "EHLO mail-pa0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751139AbaKTOLo (ORCPT ); Thu, 20 Nov 2014 09:11:44 -0500 MIME-Version: 1.0 X-Originating-IP: [2a01:e35:2434:4600:224:8cff:fe66:7f7e] In-Reply-To: <546380DD.8000802@linaro.org> References: <1414433284-31719-1-git-send-email-a.motakis@virtualopensystems.com> <1414433284-31719-9-git-send-email-a.motakis@virtualopensystems.com> <546380DD.8000802@linaro.org> From: Antonios Motakis Date: Thu, 20 Nov 2014 15:11:23 +0100 Message-ID: Subject: Re: [PATCH v9 08/19] vfio/platform: read and write support for the device fd To: Eric Auger Cc: kvm-arm , Linux IOMMU , Alex Williamson , Will Deacon , VirtualOpenSystems Technical Team , Christoffer Dall , Kim Phillips , Marc Zyngier , "open list:VFIO DRIVER , open list" Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Nov 12, 2014 at 4:46 PM, Eric Auger wrote: > On 10/27/2014 07:07 PM, Antonios Motakis wrote: >> VFIO returns a file descriptor which we can use to manipulate the memory >> regions of the device. Usually, the user will mmap memory regions that are >> addressable on page boundaries, however for memory regions where this is >> not the case we cannot provide mmap functionality due to security concerns. >> For this reason we also need allow to read and write to the memory regions > some rewording needed here >> via the file descriptor. Implement this funcionality > typo > Ack! > Regards > > Eric > only for MMIO regions >> of platform devices; PIO regions are not being handled at this point. >> >> Signed-off-by: Antonios Motakis >> --- >> drivers/vfio/platform/vfio_platform_common.c | 150 ++++++++++++++++++++++++++ >> drivers/vfio/platform/vfio_platform_private.h | 1 + >> 2 files changed, 151 insertions(+) >> >> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c >> index 82de752..e10a8d0 100644 >> --- a/drivers/vfio/platform/vfio_platform_common.c >> +++ b/drivers/vfio/platform/vfio_platform_common.c >> @@ -55,6 +55,10 @@ static int vfio_platform_regions_init(struct vfio_platform_device *vdev) >> switch (resource_type(res)) { >> case IORESOURCE_MEM: >> vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO; >> + vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ; >> + if (!(res->flags & IORESOURCE_READONLY)) >> + vdev->regions[i].flags |= >> + VFIO_REGION_INFO_FLAG_WRITE; >> break; >> case IORESOURCE_IO: >> vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO; >> @@ -74,6 +78,11 @@ err: >> >> static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev) >> { >> + int i; >> + >> + for (i = 0; i < vdev->num_regions; i++) >> + iounmap(vdev->regions[i].ioaddr); >> + >> vdev->num_regions = 0; >> kfree(vdev->regions); >> } >> @@ -176,15 +185,156 @@ static long vfio_platform_ioctl(void *device_data, >> return -ENOTTY; >> } >> >> +static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, >> + char __user *buf, size_t count, >> + loff_t off) >> +{ >> + unsigned int done = 0; >> + >> + if (!reg.ioaddr) { >> + reg.ioaddr = >> + ioremap_nocache(reg.addr, reg.size); >> + >> + if (!reg.ioaddr) >> + return -ENOMEM; >> + } >> + >> + while (count) { >> + size_t filled; >> + >> + if (count >= 4 && !(off % 4)) { >> + u32 val; >> + >> + val = ioread32(reg.ioaddr + off); >> + if (copy_to_user(buf, &val, 4)) >> + goto err; >> + >> + filled = 4; >> + } else if (count >= 2 && !(off % 2)) { >> + u16 val; >> + >> + val = ioread16(reg.ioaddr + off); >> + if (copy_to_user(buf, &val, 2)) >> + goto err; >> + >> + filled = 2; >> + } else { >> + u8 val; >> + >> + val = ioread8(reg.ioaddr + off); >> + if (copy_to_user(buf, &val, 1)) >> + goto err; >> + >> + filled = 1; >> + } >> + >> + >> + count -= filled; >> + done += filled; >> + off += filled; >> + buf += filled; >> + } >> + >> + return done; >> +err: >> + return -EFAULT; >> +} >> + >> static ssize_t vfio_platform_read(void *device_data, char __user *buf, >> size_t count, loff_t *ppos) >> { >> + struct vfio_platform_device *vdev = device_data; >> + unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos); >> + loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK; >> + >> + if (index >= vdev->num_regions) >> + return -EINVAL; >> + >> + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)) >> + return -EINVAL; >> + >> + if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) >> + return vfio_platform_read_mmio(vdev->regions[index], >> + buf, count, off); >> + else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) >> + return -EINVAL; /* not implemented */ >> + >> return -EINVAL; >> } >> >> +static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, >> + const char __user *buf, size_t count, >> + loff_t off) >> +{ >> + unsigned int done = 0; >> + >> + if (!reg.ioaddr) { >> + reg.ioaddr = >> + ioremap_nocache(reg.addr, reg.size); >> + >> + if (!reg.ioaddr) >> + return -ENOMEM; >> + } >> + >> + while (count) { >> + size_t filled; >> + >> + if (count >= 4 && !(off % 4)) { >> + u32 val; >> + >> + if (copy_from_user(&val, buf, 4)) >> + goto err; >> + iowrite32(val, reg.ioaddr + off); >> + >> + filled = 4; >> + } else if (count >= 2 && !(off % 2)) { >> + u16 val; >> + >> + if (copy_from_user(&val, buf, 2)) >> + goto err; >> + iowrite16(val, reg.ioaddr + off); >> + >> + filled = 2; >> + } else { >> + u8 val; >> + >> + if (copy_from_user(&val, buf, 1)) >> + goto err; >> + iowrite8(val, reg.ioaddr + off); >> + >> + filled = 1; >> + } >> + >> + count -= filled; >> + done += filled; >> + off += filled; >> + buf += filled; >> + } >> + >> + return done; >> +err: >> + return -EFAULT; >> +} >> + >> static ssize_t vfio_platform_write(void *device_data, const char __user *buf, >> size_t count, loff_t *ppos) >> { >> + struct vfio_platform_device *vdev = device_data; >> + unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos); >> + loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK; >> + >> + if (index >= vdev->num_regions) >> + return -EINVAL; >> + >> + if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)) >> + return -EINVAL; >> + >> + if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) >> + return vfio_platform_write_mmio(vdev->regions[index], >> + buf, count, off); >> + else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) >> + return -EINVAL; /* not implemented */ >> + >> return -EINVAL; >> } >> >> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h >> index b24729f..1f251b2 100644 >> --- a/drivers/vfio/platform/vfio_platform_private.h >> +++ b/drivers/vfio/platform/vfio_platform_private.h >> @@ -31,6 +31,7 @@ struct vfio_platform_region { >> u32 type; >> #define VFIO_PLATFORM_REGION_TYPE_MMIO 1 >> #define VFIO_PLATFORM_REGION_TYPE_PIO 2 >> + void __iomem *ioaddr; >> }; >> >> struct vfio_platform_device { >> > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/