Skip to content

Commit

Permalink
iommu/virtio: Update to most recent specification
Browse files Browse the repository at this point in the history
Following specification review a few things were changed in v8 of the
virtio-iommu series [1], but have been omitted when merging the base
driver. Add them now:

* Remove the EXEC flag.
* Add feature bit for the MMIO flag.
* Change domain_bits to domain_range.
* Add NOMEM status flag.

[1] https://lore.kernel.org/linux-iommu/20190530170929.19366-1-jean-philippe.brucker@arm.com/

Fixes: edcd69a ("iommu: Add virtio-iommu driver")
Reported-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Acked-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Jean-Philippe Brucker authored and Michael S. Tsirkin committed Jul 22, 2019
1 parent cfe6180 commit ae24fb4
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 25 deletions.
40 changes: 29 additions & 11 deletions drivers/iommu/virtio-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* Virtio driver for the paravirtualized IOMMU
*
* Copyright (C) 2018 Arm Limited
* Copyright (C) 2019 Arm Limited
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Expand Down Expand Up @@ -47,7 +47,10 @@ struct viommu_dev {
/* Device configuration */
struct iommu_domain_geometry geometry;
u64 pgsize_bitmap;
u8 domain_bits;
u32 first_domain;
u32 last_domain;
/* Supported MAP flags */
u32 map_flags;
u32 probe_size;
};

Expand All @@ -62,6 +65,7 @@ struct viommu_domain {
struct viommu_dev *viommu;
struct mutex mutex; /* protects viommu pointer */
unsigned int id;
u32 map_flags;

spinlock_t mappings_lock;
struct rb_root_cached mappings;
Expand Down Expand Up @@ -113,6 +117,8 @@ static int viommu_get_req_errno(void *buf, size_t len)
return -ENOENT;
case VIRTIO_IOMMU_S_FAULT:
return -EFAULT;
case VIRTIO_IOMMU_S_NOMEM:
return -ENOMEM;
case VIRTIO_IOMMU_S_IOERR:
case VIRTIO_IOMMU_S_DEVERR:
default:
Expand Down Expand Up @@ -607,15 +613,15 @@ static int viommu_domain_finalise(struct viommu_dev *viommu,
{
int ret;
struct viommu_domain *vdomain = to_viommu_domain(domain);
unsigned int max_domain = viommu->domain_bits > 31 ? ~0 :
(1U << viommu->domain_bits) - 1;

vdomain->viommu = viommu;
vdomain->map_flags = viommu->map_flags;

domain->pgsize_bitmap = viommu->pgsize_bitmap;
domain->geometry = viommu->geometry;

ret = ida_alloc_max(&viommu->domain_ids, max_domain, GFP_KERNEL);
ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
viommu->last_domain, GFP_KERNEL);
if (ret >= 0)
vdomain->id = (unsigned int)ret;

Expand Down Expand Up @@ -710,14 +716,17 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
{
int ret;
int flags;
u32 flags;
struct virtio_iommu_req_map map;
struct viommu_domain *vdomain = to_viommu_domain(domain);

flags = (prot & IOMMU_READ ? VIRTIO_IOMMU_MAP_F_READ : 0) |
(prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
(prot & IOMMU_MMIO ? VIRTIO_IOMMU_MAP_F_MMIO : 0);

if (flags & ~vdomain->map_flags)
return -EINVAL;

ret = viommu_add_mapping(vdomain, iova, paddr, size, flags);
if (ret)
return ret;
Expand Down Expand Up @@ -1027,7 +1036,8 @@ static int viommu_probe(struct virtio_device *vdev)
goto err_free_vqs;
}

viommu->domain_bits = 32;
viommu->map_flags = VIRTIO_IOMMU_MAP_F_READ | VIRTIO_IOMMU_MAP_F_WRITE;
viommu->last_domain = ~0U;

/* Optional features */
virtio_cread_feature(vdev, VIRTIO_IOMMU_F_INPUT_RANGE,
Expand All @@ -1038,9 +1048,13 @@ static int viommu_probe(struct virtio_device *vdev)
struct virtio_iommu_config, input_range.end,
&input_end);

virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_BITS,
struct virtio_iommu_config, domain_bits,
&viommu->domain_bits);
virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
struct virtio_iommu_config, domain_range.start,
&viommu->first_domain);

virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
struct virtio_iommu_config, domain_range.end,
&viommu->last_domain);

virtio_cread_feature(vdev, VIRTIO_IOMMU_F_PROBE,
struct virtio_iommu_config, probe_size,
Expand All @@ -1052,6 +1066,9 @@ static int viommu_probe(struct virtio_device *vdev)
.force_aperture = true,
};

if (virtio_has_feature(vdev, VIRTIO_IOMMU_F_MMIO))
viommu->map_flags |= VIRTIO_IOMMU_MAP_F_MMIO;

viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap;

virtio_device_ready(vdev);
Expand Down Expand Up @@ -1130,9 +1147,10 @@ static void viommu_config_changed(struct virtio_device *vdev)

static unsigned int features[] = {
VIRTIO_IOMMU_F_MAP_UNMAP,
VIRTIO_IOMMU_F_DOMAIN_BITS,
VIRTIO_IOMMU_F_INPUT_RANGE,
VIRTIO_IOMMU_F_DOMAIN_RANGE,
VIRTIO_IOMMU_F_PROBE,
VIRTIO_IOMMU_F_MMIO,
};

static struct virtio_device_id id_table[] = {
Expand Down
32 changes: 18 additions & 14 deletions include/uapi/linux/virtio_iommu.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Virtio-iommu definition v0.9
* Virtio-iommu definition v0.12
*
* Copyright (C) 2018 Arm Ltd.
* Copyright (C) 2019 Arm Ltd.
*/
#ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
#define _UAPI_LINUX_VIRTIO_IOMMU_H
Expand All @@ -11,26 +11,31 @@

/* Feature bits */
#define VIRTIO_IOMMU_F_INPUT_RANGE 0
#define VIRTIO_IOMMU_F_DOMAIN_BITS 1
#define VIRTIO_IOMMU_F_DOMAIN_RANGE 1
#define VIRTIO_IOMMU_F_MAP_UNMAP 2
#define VIRTIO_IOMMU_F_BYPASS 3
#define VIRTIO_IOMMU_F_PROBE 4
#define VIRTIO_IOMMU_F_MMIO 5

struct virtio_iommu_range {
__u64 start;
__u64 end;
struct virtio_iommu_range_64 {
__le64 start;
__le64 end;
};

struct virtio_iommu_range_32 {
__le32 start;
__le32 end;
};

struct virtio_iommu_config {
/* Supported page sizes */
__u64 page_size_mask;
__le64 page_size_mask;
/* Supported IOVA range */
struct virtio_iommu_range input_range;
struct virtio_iommu_range_64 input_range;
/* Max domain ID size */
__u8 domain_bits;
__u8 padding[3];
struct virtio_iommu_range_32 domain_range;
/* Probe buffer size */
__u32 probe_size;
__le32 probe_size;
};

/* Request types */
Expand All @@ -49,6 +54,7 @@ struct virtio_iommu_config {
#define VIRTIO_IOMMU_S_RANGE 0x05
#define VIRTIO_IOMMU_S_NOENT 0x06
#define VIRTIO_IOMMU_S_FAULT 0x07
#define VIRTIO_IOMMU_S_NOMEM 0x08

struct virtio_iommu_req_head {
__u8 type;
Expand Down Expand Up @@ -78,12 +84,10 @@ struct virtio_iommu_req_detach {

#define VIRTIO_IOMMU_MAP_F_READ (1 << 0)
#define VIRTIO_IOMMU_MAP_F_WRITE (1 << 1)
#define VIRTIO_IOMMU_MAP_F_EXEC (1 << 2)
#define VIRTIO_IOMMU_MAP_F_MMIO (1 << 3)
#define VIRTIO_IOMMU_MAP_F_MMIO (1 << 2)

#define VIRTIO_IOMMU_MAP_F_MASK (VIRTIO_IOMMU_MAP_F_READ | \
VIRTIO_IOMMU_MAP_F_WRITE | \
VIRTIO_IOMMU_MAP_F_EXEC | \
VIRTIO_IOMMU_MAP_F_MMIO)

struct virtio_iommu_req_map {
Expand Down

0 comments on commit ae24fb4

Please sign in to comment.