Re: [PATCH v8 2/7] dt-bindings: virtio: Add virtio-pci-iommu node
On Thu, May 30, 2019 at 06:09:24PM +0100, Jean-Philippe Brucker wrote: > Some systems implement virtio-iommu as a PCI endpoint. The operating > system needs to discover the relationship between IOMMU and masters long > before the PCI endpoint gets probed. Add a PCI child node to describe the > virtio-iommu device. > > The virtio-pci-iommu is conceptually split between a PCI programming > interface and a translation component on the parent bus. The latter > doesn't have a node in the device tree. The virtio-pci-iommu node > describes both, by linking the PCI endpoint to "iommus" property of DMA > master nodes and to "iommu-map" properties of bus nodes. > > Reviewed-by: Rob Herring > Reviewed-by: Eric Auger > Signed-off-by: Jean-Philippe Brucker So this is just an example right? We are not defining any new properties or anything like that. I think down the road for non dt platforms we want to put this info in the config space of the device. I do not think ACPI is the best option for this since not all systems have it. But that can wait. > --- > .../devicetree/bindings/virtio/iommu.txt | 66 +++ > 1 file changed, 66 insertions(+) > create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt > > diff --git a/Documentation/devicetree/bindings/virtio/iommu.txt > b/Documentation/devicetree/bindings/virtio/iommu.txt > new file mode 100644 > index ..2407fea0651c > --- /dev/null > +++ b/Documentation/devicetree/bindings/virtio/iommu.txt > @@ -0,0 +1,66 @@ > +* virtio IOMMU PCI device > + > +When virtio-iommu uses the PCI transport, its programming interface is > +discovered dynamically by the PCI probing infrastructure. However the > +device tree statically describes the relation between IOMMU and DMA > +masters. Therefore, the PCI root complex that hosts the virtio-iommu > +contains a child node representing the IOMMU device explicitly. > + > +Required properties: > + > +- compatible:Should be "virtio,pci-iommu" > +- reg: PCI address of the IOMMU. As defined in the PCI Bus > + Binding reference [1], the reg property is a five-cell > + address encoded as (phys.hi phys.mid phys.lo size.hi > + size.lo). phys.hi should contain the device's BDF as > + 0b dfff . The other cells > + should be zero. > +- #iommu-cells: Each platform DMA master managed by the IOMMU is > assigned > + an endpoint ID, described by the "iommus" property [2]. > + For virtio-iommu, #iommu-cells must be 1. > + > +Notes: > + > +- DMA from the IOMMU device isn't managed by another IOMMU. Therefore the > + virtio-iommu node doesn't have an "iommus" property, and is omitted from > + the iommu-map property of the root complex. > + > +Example: > + > +pcie@1000 { > + compatible = "pci-host-ecam-generic"; > + ... > + > + /* The IOMMU programming interface uses slot 00:01.0 */ > + iommu0: iommu@0008 { > + compatible = "virtio,pci-iommu"; > + reg = <0x0800 0 0 0 0>; > + #iommu-cells = <1>; > + }; > + > + /* > + * The IOMMU manages all functions in this PCI domain except > + * itself. Omit BDF 00:01.0. > + */ > + iommu-map = <0x0 0x0 0x8> > + <0x9 0x9 0xfff7>; > +}; > + > +pcie@2000 { > + compatible = "pci-host-ecam-generic"; > + ... > + /* > + * The IOMMU also manages all functions from this domain, > + * with endpoint IDs 0x1 - 0x1 > + */ > + iommu-map = <0x0 0x1 0x1>; > +}; > + > +ethernet@fe001000 { > + ... > + /* The IOMMU manages this platform device with endpoint ID 0x2 */ > + iommus = < 0x2>; > +}; > + > +[1] Documentation/devicetree/bindings/pci/pci.txt > +[2] Documentation/devicetree/bindings/iommu/iommu.txt > -- > 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 6/7] iommu/virtio: Add probe request
When the device offers the probe feature, send a probe request for each device managed by the IOMMU. Extract RESV_MEM information. When we encounter a MSI doorbell region, set it up as a IOMMU_RESV_MSI region. This will tell other subsystems that there is no need to map the MSI doorbell in the virtio-iommu, because MSIs bypass it. Acked-by: Joerg Roedel Reviewed-by: Eric Auger Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 157 -- include/uapi/linux/virtio_iommu.h | 36 +++ 2 files changed, 187 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index b2719a87c3c5..5d4947c47420 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -49,6 +49,7 @@ struct viommu_dev { u32 last_domain; /* Supported MAP flags */ u32 map_flags; + u32 probe_size; }; struct viommu_mapping { @@ -71,8 +72,10 @@ struct viommu_domain { }; struct viommu_endpoint { + struct device *dev; struct viommu_dev *viommu; struct viommu_domain*vdomain; + struct list_headresv_regions; }; struct viommu_request { @@ -125,6 +128,9 @@ static off_t viommu_get_write_desc_offset(struct viommu_dev *viommu, { size_t tail_size = sizeof(struct virtio_iommu_req_tail); + if (req->type == VIRTIO_IOMMU_T_PROBE) + return len - viommu->probe_size - tail_size; + return len - tail_size; } @@ -399,6 +405,110 @@ static int viommu_replay_mappings(struct viommu_domain *vdomain) return ret; } +static int viommu_add_resv_mem(struct viommu_endpoint *vdev, + struct virtio_iommu_probe_resv_mem *mem, + size_t len) +{ + size_t size; + u64 start64, end64; + phys_addr_t start, end; + struct iommu_resv_region *region = NULL; + unsigned long prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; + + start = start64 = le64_to_cpu(mem->start); + end = end64 = le64_to_cpu(mem->end); + size = end64 - start64 + 1; + + /* Catch any overflow, including the unlikely end64 - start64 + 1 = 0 */ + if (start != start64 || end != end64 || size < end64 - start64) + return -EOVERFLOW; + + if (len < sizeof(*mem)) + return -EINVAL; + + switch (mem->subtype) { + default: + dev_warn(vdev->dev, "unknown resv mem subtype 0x%x\n", +mem->subtype); + /* Fall-through */ + case VIRTIO_IOMMU_RESV_MEM_T_RESERVED: + region = iommu_alloc_resv_region(start, size, 0, +IOMMU_RESV_RESERVED); + break; + case VIRTIO_IOMMU_RESV_MEM_T_MSI: + region = iommu_alloc_resv_region(start, size, prot, +IOMMU_RESV_MSI); + break; + } + if (!region) + return -ENOMEM; + + list_add(>resv_regions, >list); + return 0; +} + +static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev) +{ + int ret; + u16 type, len; + size_t cur = 0; + size_t probe_len; + struct virtio_iommu_req_probe *probe; + struct virtio_iommu_probe_property *prop; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + struct viommu_endpoint *vdev = fwspec->iommu_priv; + + if (!fwspec->num_ids) + return -EINVAL; + + probe_len = sizeof(*probe) + viommu->probe_size + + sizeof(struct virtio_iommu_req_tail); + probe = kzalloc(probe_len, GFP_KERNEL); + if (!probe) + return -ENOMEM; + + probe->head.type = VIRTIO_IOMMU_T_PROBE; + /* +* For now, assume that properties of an endpoint that outputs multiple +* IDs are consistent. Only probe the first one. +*/ + probe->endpoint = cpu_to_le32(fwspec->ids[0]); + + ret = viommu_send_req_sync(viommu, probe, probe_len); + if (ret) + goto out_free; + + prop = (void *)probe->properties; + type = le16_to_cpu(prop->type) & VIRTIO_IOMMU_PROBE_T_MASK; + + while (type != VIRTIO_IOMMU_PROBE_T_NONE && + cur < viommu->probe_size) { + len = le16_to_cpu(prop->length) + sizeof(*prop); + + switch (type) { + case VIRTIO_IOMMU_PROBE_T_RESV_MEM: + ret = viommu_add_resv_mem(vdev, (void *)prop, len); + break; + default: + dev_err(dev, "unknown viommu prop 0x%x\n", type); + } + + if (ret) + dev_err(dev, "failed to parse viommu prop
[PATCH v8 5/7] iommu: Add virtio-iommu driver
The virtio IOMMU is a para-virtualized device, allowing to send IOMMU requests such as map/unmap over virtio transport without emulating page tables. This implementation handles ATTACH, DETACH, MAP and UNMAP requests. The bulk of the code transforms calls coming from the IOMMU API into corresponding virtio requests. Mappings are kept in an interval tree instead of page tables. A little more work is required for modular and x86 support, so for the moment the driver depends on CONFIG_VIRTIO=y and CONFIG_ARM64. Acked-by: Joerg Roedel Signed-off-by: Jean-Philippe Brucker --- MAINTAINERS | 7 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile| 1 + drivers/iommu/virtio-iommu.c | 934 ++ include/uapi/linux/virtio_ids.h | 1 + include/uapi/linux/virtio_iommu.h | 110 6 files changed, 1064 insertions(+) create mode 100644 drivers/iommu/virtio-iommu.c create mode 100644 include/uapi/linux/virtio_iommu.h diff --git a/MAINTAINERS b/MAINTAINERS index 429c6c624861..62bd1834d95a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16807,6 +16807,13 @@ S: Maintained F: drivers/virtio/virtio_input.c F: include/uapi/linux/virtio_input.h +VIRTIO IOMMU DRIVER +M: Jean-Philippe Brucker +L: virtualizat...@lists.linux-foundation.org +S: Maintained +F: drivers/iommu/virtio-iommu.c +F: include/uapi/linux/virtio_iommu.h + VIRTUAL BOX GUEST DEVICE DRIVER M: Hans de Goede M: Arnd Bergmann diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 83664db5221d..e15cdcd8cb3c 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -473,4 +473,15 @@ config HYPERV_IOMMU Stub IOMMU driver to handle IRQs as to allow Hyper-V Linux guests to run with x2APIC mode enabled. +config VIRTIO_IOMMU + bool "Virtio IOMMU driver" + depends on VIRTIO=y + depends on ARM64 + select IOMMU_API + select INTERVAL_TREE + help + Para-virtualised IOMMU driver with virtio. + + Say Y here if you intend to run this kernel as a guest. + endif # IOMMU_SUPPORT diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 8c71a15e986b..f13f36ae1af6 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -33,3 +33,4 @@ obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o obj-$(CONFIG_S390_IOMMU) += s390-iommu.o obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o +obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c new file mode 100644 index ..b2719a87c3c5 --- /dev/null +++ b/drivers/iommu/virtio-iommu.c @@ -0,0 +1,934 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Virtio driver for the paravirtualized IOMMU + * + * Copyright (C) 2019 Arm Limited + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MSI_IOVA_BASE 0x800 +#define MSI_IOVA_LENGTH0x10 + +#define VIOMMU_REQUEST_VQ 0 +#define VIOMMU_NR_VQS 1 + +struct viommu_dev { + struct iommu_device iommu; + struct device *dev; + struct virtio_device*vdev; + + struct ida domain_ids; + + struct virtqueue*vqs[VIOMMU_NR_VQS]; + spinlock_t request_lock; + struct list_headrequests; + + /* Device configuration */ + struct iommu_domain_geometrygeometry; + u64 pgsize_bitmap; + u32 first_domain; + u32 last_domain; + /* Supported MAP flags */ + u32 map_flags; +}; + +struct viommu_mapping { + phys_addr_t paddr; + struct interval_tree_node iova; + u32 flags; +}; + +struct viommu_domain { + struct iommu_domain domain; + struct viommu_dev *viommu; + struct mutexmutex; /* protects viommu pointer */ + unsigned intid; + u32 map_flags; + + spinlock_t mappings_lock; + struct rb_root_cached mappings; + + unsigned long nr_endpoints; +}; + +struct viommu_endpoint { + struct viommu_dev *viommu; + struct viommu_domain*vdomain; +}; + +struct viommu_request { + struct list_headlist; + void*writeback; + unsigned intwrite_offset; +
[PATCH v8 7/7] iommu/virtio: Add event queue
The event queue offers a way for the device to report access faults from endpoints. It is implemented on virtqueue #1. Whenever the host needs to signal a fault, it fills one of the buffers offered by the guest and interrupts it. Acked-by: Joerg Roedel Reviewed-by: Eric Auger Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 115 +++--- include/uapi/linux/virtio_iommu.h | 19 + 2 files changed, 125 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index 5d4947c47420..2688cdcac6e5 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -29,7 +29,8 @@ #define MSI_IOVA_LENGTH0x10 #define VIOMMU_REQUEST_VQ 0 -#define VIOMMU_NR_VQS 1 +#define VIOMMU_EVENT_VQ1 +#define VIOMMU_NR_VQS 2 struct viommu_dev { struct iommu_device iommu; @@ -41,6 +42,7 @@ struct viommu_dev { struct virtqueue*vqs[VIOMMU_NR_VQS]; spinlock_t request_lock; struct list_headrequests; + void*evts; /* Device configuration */ struct iommu_domain_geometrygeometry; @@ -86,6 +88,15 @@ struct viommu_request { charbuf[]; }; +#define VIOMMU_FAULT_RESV_MASK 0xff00 + +struct viommu_event { + union { + u32 head; + struct virtio_iommu_fault fault; + }; +}; + #define to_viommu_domain(domain) \ container_of(domain, struct viommu_domain, domain) @@ -509,6 +520,68 @@ static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev) return ret; } +static int viommu_fault_handler(struct viommu_dev *viommu, + struct virtio_iommu_fault *fault) +{ + char *reason_str; + + u8 reason = fault->reason; + u32 flags = le32_to_cpu(fault->flags); + u32 endpoint= le32_to_cpu(fault->endpoint); + u64 address = le64_to_cpu(fault->address); + + switch (reason) { + case VIRTIO_IOMMU_FAULT_R_DOMAIN: + reason_str = "domain"; + break; + case VIRTIO_IOMMU_FAULT_R_MAPPING: + reason_str = "page"; + break; + case VIRTIO_IOMMU_FAULT_R_UNKNOWN: + default: + reason_str = "unknown"; + break; + } + + /* TODO: find EP by ID and report_iommu_fault */ + if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS) + dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n", + reason_str, endpoint, address, + flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "", + flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "", + flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : ""); + else + dev_err_ratelimited(viommu->dev, "%s fault from EP %u\n", + reason_str, endpoint); + return 0; +} + +static void viommu_event_handler(struct virtqueue *vq) +{ + int ret; + unsigned int len; + struct scatterlist sg[1]; + struct viommu_event *evt; + struct viommu_dev *viommu = vq->vdev->priv; + + while ((evt = virtqueue_get_buf(vq, )) != NULL) { + if (len > sizeof(*evt)) { + dev_err(viommu->dev, + "invalid event buffer (len %u != %zu)\n", + len, sizeof(*evt)); + } else if (!(evt->head & VIOMMU_FAULT_RESV_MASK)) { + viommu_fault_handler(viommu, >fault); + } + + sg_init_one(sg, evt, sizeof(*evt)); + ret = virtqueue_add_inbuf(vq, sg, 1, evt, GFP_ATOMIC); + if (ret) + dev_err(viommu->dev, "could not add event buffer\n"); + } + + virtqueue_kick(vq); +} + /* IOMMU API */ static struct iommu_domain *viommu_domain_alloc(unsigned type) @@ -895,16 +968,35 @@ static struct iommu_ops viommu_ops = { static int viommu_init_vqs(struct viommu_dev *viommu) { struct virtio_device *vdev = dev_to_virtio(viommu->dev); - const char *name = "request"; - void *ret; + const char *names[] = { "request", "event" }; + vq_callback_t *callbacks[] = { + NULL, /* No async requests */ + viommu_event_handler, + }; - ret = virtio_find_single_vq(vdev, NULL, name); - if (IS_ERR(ret)) { - dev_err(viommu->dev, "cannot find VQ\n"); - return PTR_ERR(ret); - } + return virtio_find_vqs(vdev, VIOMMU_NR_VQS, viommu->vqs, callbacks, +
[PATCH v8 1/7] dt-bindings: virtio-mmio: Add IOMMU description
The nature of a virtio-mmio node is discovered by the virtio driver at probe time. However the DMA relation between devices must be described statically. When a virtio-mmio node is a virtio-iommu device, it needs an "#iommu-cells" property as specified by bindings/iommu/iommu.txt. Otherwise, the virtio-mmio device may perform DMA through an IOMMU, which requires an "iommus" property. Describe these requirements in the device-tree bindings documentation. Reviewed-by: Rob Herring Reviewed-by: Eric Auger Signed-off-by: Jean-Philippe Brucker --- .../devicetree/bindings/virtio/mmio.txt | 30 +++ 1 file changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt index 5069c1b8e193..21af30fbb81f 100644 --- a/Documentation/devicetree/bindings/virtio/mmio.txt +++ b/Documentation/devicetree/bindings/virtio/mmio.txt @@ -8,10 +8,40 @@ Required properties: - reg: control registers base address and size including configuration space - interrupts: interrupt generated by the device +Required properties for virtio-iommu: + +- #iommu-cells:When the node corresponds to a virtio-iommu device, it is + linked to DMA masters using the "iommus" or "iommu-map" + properties [1][2]. #iommu-cells specifies the size of the + "iommus" property. For virtio-iommu #iommu-cells must be + 1, each cell describing a single endpoint ID. + +Optional properties: + +- iommus: If the device accesses memory through an IOMMU, it should + have an "iommus" property [1]. Since virtio-iommu itself + does not access memory through an IOMMU, the "virtio,mmio" + node cannot have both an "#iommu-cells" and an "iommus" + property. + Example: virtio_block@3000 { compatible = "virtio,mmio"; reg = <0x3000 0x100>; interrupts = <41>; + + /* Device has endpoint ID 23 */ + iommus = < 23> } + + viommu: iommu@3100 { + compatible = "virtio,mmio"; + reg = <0x3100 0x100>; + interrupts = <42>; + + #iommu-cells = <1> + } + +[1] Documentation/devicetree/bindings/iommu/iommu.txt +[2] Documentation/devicetree/bindings/pci/pci-iommu.txt -- 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 4/7] PCI: OF: Initialize dev->fwnode appropriately
For PCI devices that have an OF node, set the fwnode as well. This way drivers that rely on fwnode don't need the special case described by commit f94277af03ea ("of/platform: Initialise dev->fwnode appropriately"). Acked-by: Bjorn Helgaas Signed-off-by: Jean-Philippe Brucker --- drivers/pci/of.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 73d5adec0a28..c4f1b5507b40 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -22,12 +22,15 @@ void pci_set_of_node(struct pci_dev *dev) return; dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn); + if (dev->dev.of_node) + dev->dev.fwnode = >dev.of_node->fwnode; } void pci_release_of_node(struct pci_dev *dev) { of_node_put(dev->dev.of_node); dev->dev.of_node = NULL; + dev->dev.fwnode = NULL; } void pci_set_bus_of_node(struct pci_bus *bus) @@ -42,12 +45,15 @@ void pci_set_bus_of_node(struct pci_bus *bus) bus->self->untrusted = true; } bus->dev.of_node = node; + if (node) + bus->dev.fwnode = >fwnode; } void pci_release_bus_of_node(struct pci_bus *bus) { of_node_put(bus->dev.of_node); bus->dev.of_node = NULL; + bus->dev.fwnode = NULL; } struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus) -- 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 3/7] of: Allow the iommu-map property to omit untranslated devices
In PCI root complex nodes, the iommu-map property describes the IOMMU that translates each endpoint. On some platforms, the IOMMU itself is presented as a PCI endpoint (e.g. AMD IOMMU and virtio-iommu). This isn't supported by the current OF driver, which expects all endpoints to have an IOMMU. Allow the iommu-map property to have gaps. Relaxing of_map_rid() also allows the msi-map property to have gaps, which is invalid since MSIs always reach an MSI controller. In that case pci_msi_setup_msi_irqs() will return an error when attempting to find the device's MSI domain. Reviewed-by: Rob Herring Signed-off-by: Jean-Philippe Brucker --- drivers/of/base.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 20e0e7ee4edf..55e7f5bb0549 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2294,8 +2294,12 @@ int of_map_rid(struct device_node *np, u32 rid, return 0; } - pr_err("%pOF: Invalid %s translation - no match for rid 0x%x on %pOF\n", - np, map_name, rid, target && *target ? *target : NULL); - return -EFAULT; + pr_info("%pOF: no %s translation for rid 0x%x on %pOF\n", np, map_name, + rid, target && *target ? *target : NULL); + + /* Bypasses translation */ + if (id_out) + *id_out = rid; + return 0; } EXPORT_SYMBOL_GPL(of_map_rid); -- 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 2/7] dt-bindings: virtio: Add virtio-pci-iommu node
Some systems implement virtio-iommu as a PCI endpoint. The operating system needs to discover the relationship between IOMMU and masters long before the PCI endpoint gets probed. Add a PCI child node to describe the virtio-iommu device. The virtio-pci-iommu is conceptually split between a PCI programming interface and a translation component on the parent bus. The latter doesn't have a node in the device tree. The virtio-pci-iommu node describes both, by linking the PCI endpoint to "iommus" property of DMA master nodes and to "iommu-map" properties of bus nodes. Reviewed-by: Rob Herring Reviewed-by: Eric Auger Signed-off-by: Jean-Philippe Brucker --- .../devicetree/bindings/virtio/iommu.txt | 66 +++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt diff --git a/Documentation/devicetree/bindings/virtio/iommu.txt b/Documentation/devicetree/bindings/virtio/iommu.txt new file mode 100644 index ..2407fea0651c --- /dev/null +++ b/Documentation/devicetree/bindings/virtio/iommu.txt @@ -0,0 +1,66 @@ +* virtio IOMMU PCI device + +When virtio-iommu uses the PCI transport, its programming interface is +discovered dynamically by the PCI probing infrastructure. However the +device tree statically describes the relation between IOMMU and DMA +masters. Therefore, the PCI root complex that hosts the virtio-iommu +contains a child node representing the IOMMU device explicitly. + +Required properties: + +- compatible: Should be "virtio,pci-iommu" +- reg: PCI address of the IOMMU. As defined in the PCI Bus + Binding reference [1], the reg property is a five-cell + address encoded as (phys.hi phys.mid phys.lo size.hi + size.lo). phys.hi should contain the device's BDF as + 0b dfff . The other cells + should be zero. +- #iommu-cells:Each platform DMA master managed by the IOMMU is assigned + an endpoint ID, described by the "iommus" property [2]. + For virtio-iommu, #iommu-cells must be 1. + +Notes: + +- DMA from the IOMMU device isn't managed by another IOMMU. Therefore the + virtio-iommu node doesn't have an "iommus" property, and is omitted from + the iommu-map property of the root complex. + +Example: + +pcie@1000 { + compatible = "pci-host-ecam-generic"; + ... + + /* The IOMMU programming interface uses slot 00:01.0 */ + iommu0: iommu@0008 { + compatible = "virtio,pci-iommu"; + reg = <0x0800 0 0 0 0>; + #iommu-cells = <1>; + }; + + /* +* The IOMMU manages all functions in this PCI domain except +* itself. Omit BDF 00:01.0. +*/ + iommu-map = <0x0 0x0 0x8> + <0x9 0x9 0xfff7>; +}; + +pcie@2000 { + compatible = "pci-host-ecam-generic"; + ... + /* +* The IOMMU also manages all functions from this domain, +* with endpoint IDs 0x1 - 0x1 +*/ + iommu-map = <0x0 0x1 0x1>; +}; + +ethernet@fe001000 { + ... + /* The IOMMU manages this platform device with endpoint ID 0x2 */ + iommus = < 0x2>; +}; + +[1] Documentation/devicetree/bindings/pci/pci.txt +[2] Documentation/devicetree/bindings/iommu/iommu.txt -- 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 0/7] Add virtio-iommu driver
Implement the virtio-iommu driver, following specification v0.12 [1]. Since last version [2] we've worked on improving the specification, which resulted in the following changes to the interface: * Remove the EXEC flag. * Add feature bit for the MMIO flag. * Change domain_bits to domain_range. Given that there were small changes to patch 5/7, I removed the review and test tags. Please find the code at [3]. [1] Virtio-iommu specification v0.12, sources and pdf git://linux-arm.org/virtio-iommu.git virtio-iommu/v0.12 http://jpbrucker.net/virtio-iommu/spec/v0.12/virtio-iommu-v0.12.pdf http://jpbrucker.net/virtio-iommu/spec/diffs/virtio-iommu-dev-diff-v0.11-v0.12.pdf [2] [PATCH v7 0/7] Add virtio-iommu driver https://lore.kernel.org/linux-pci/0ba215f5-e856-bf31-8dd9-a85710714...@arm.com/T/ [3] git://linux-arm.org/linux-jpb.git virtio-iommu/v0.12 git://linux-arm.org/kvmtool-jpb.git virtio-iommu/v0.12 Jean-Philippe Brucker (7): dt-bindings: virtio-mmio: Add IOMMU description dt-bindings: virtio: Add virtio-pci-iommu node of: Allow the iommu-map property to omit untranslated devices PCI: OF: Initialize dev->fwnode appropriately iommu: Add virtio-iommu driver iommu/virtio: Add probe request iommu/virtio: Add event queue .../devicetree/bindings/virtio/iommu.txt | 66 + .../devicetree/bindings/virtio/mmio.txt | 30 + MAINTAINERS |7 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile|1 + drivers/iommu/virtio-iommu.c | 1176 + drivers/of/base.c | 10 +- drivers/pci/of.c |6 + include/uapi/linux/virtio_ids.h |1 + include/uapi/linux/virtio_iommu.h | 165 +++ 10 files changed, 1470 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt create mode 100644 drivers/iommu/virtio-iommu.c create mode 100644 include/uapi/linux/virtio_iommu.h -- 2.21.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 8/9] arm64: Add SVE support
This patch adds --enable-sve/--disable-sve command line options to allow the user to control whether the Scalable Vector Extension is made available to the guest. This requires use of the new KVM_ARM_VCPU_FINALIZE ioctl before the vcpu is runnable, so a new hook kvm_cpu__configure_features() is added to provide an appropriate place to do this work. By default, SVE is enabled for the guest if the host supports it. Signed-off-by: Dave Martin --- arm/aarch32/include/kvm/kvm-cpu-arch.h| 4 +++ arm/aarch64/include/kvm/kvm-config-arch.h | 6 - arm/aarch64/include/kvm/kvm-cpu-arch.h| 1 + arm/aarch64/kvm-cpu.c | 41 +++ arm/include/arm-common/kvm-config-arch.h | 2 ++ arm/kvm-cpu.c | 3 +++ 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/arm/aarch32/include/kvm/kvm-cpu-arch.h b/arm/aarch32/include/kvm/kvm-cpu-arch.h index 01983f0..780e0e2 100644 --- a/arm/aarch32/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch32/include/kvm/kvm-cpu-arch.h @@ -15,5 +15,9 @@ static inline void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init) { } +static inline int kvm_cpu__configure_features(struct kvm_cpu *vcpu) +{ + return 0; +} #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h index fe1699d..41e9d05 100644 --- a/arm/aarch64/include/kvm/kvm-config-arch.h +++ b/arm/aarch64/include/kvm/kvm-config-arch.h @@ -12,7 +12,11 @@ OPT_BOOLEAN('\0', "enable-ptrauth", &(cfg)->enable_ptrauth, \ "Enable pointer authentication for the guest"), \ OPT_BOOLEAN('\0', "disable-ptrauth", &(cfg)->disable_ptrauth, \ - "Disable pointer authentication for the guest"), + "Disable pointer authentication for the guest"), \ + OPT_BOOLEAN('\0', "enable-sve", &(cfg)->enable_sve, \ + "Enable SVE for the guest"),\ + OPT_BOOLEAN('\0', "disable-sve", &(cfg)->disable_sve, \ + "Disable SVE for the guest"), #include "arm-common/kvm-config-arch.h" diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h index e6875fc..8dfb82e 100644 --- a/arm/aarch64/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h @@ -18,5 +18,6 @@ #define ARM_CPU_CTRL_SCTLR_EL1 0 void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init); +int kvm_cpu__configure_features(struct kvm_cpu *vcpu); #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c index 08e4fd5..cdfb22e 100644 --- a/arm/aarch64/kvm-cpu.c +++ b/arm/aarch64/kvm-cpu.c @@ -152,9 +152,50 @@ static void select_ptrauth_feature(struct kvm *kvm, struct kvm_vcpu_init *init) } } +static void select_sve_feature(struct kvm *kvm, struct kvm_vcpu_init *init) +{ + bool supported; + + if (kvm->cfg.arch.enable_sve && kvm->cfg.arch.disable_sve) + die("--enable-sve conflicts with --disable-sve"); + + supported = kvm__supports_extension(kvm, KVM_CAP_ARM_SVE); + + if (kvm->cfg.arch.enable_sve && !supported) + die("--enable-sve not supported on this host"); + + /* Default SVE to on if available and not explicitly disabled */ + if (supported && !kvm->cfg.arch.disable_sve) { + kvm->cfg.arch.enable_sve = true; + init->features[0] |= 1UL << KVM_ARM_VCPU_SVE; + } +} + void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init) { select_ptrauth_feature(kvm, init); + select_sve_feature(kvm, init); +} + +static int configure_sve(struct kvm_cpu *vcpu) +{ + int feature = KVM_ARM_VCPU_SVE; + + if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_FINALIZE, )) { + pr_err("KVM_ARM_VCPU_FINALIZE: %s", strerror(errno)); + return -1; + } + + return 0; +} + +int kvm_cpu__configure_features(struct kvm_cpu *vcpu) +{ + if (vcpu->kvm->cfg.arch.enable_sve) + if (configure_sve(vcpu)) + return -1; + + return 0; } void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu) diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h index 1b4287d..40e3d1f 100644 --- a/arm/include/arm-common/kvm-config-arch.h +++ b/arm/include/arm-common/kvm-config-arch.h @@ -10,6 +10,8 @@ struct kvm_config_arch { boolaarch32_guest; boolhas_pmuv3; u64 kaslr_seed; + boolenable_sve; + booldisable_sve; boolenable_ptrauth; booldisable_ptrauth; enum irqchip_type irqchip; diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c index 1652f6f..554414f
[PATCH kvmtool v3 6/9] arm/arm64: Factor out ptrauth vcpu feature setup
In the interest of readability, factor out the vcpu feature setup for ptrauth into a separate function. Also, because aarch32 doesn't have this feature or the related command line options anyway, move the actual code into aarch64/. Since ARM_VCPU_PTRAUTH_FEATURE is only there to make the ptrauth feature setup code compile on arm, it is no longer needed: inline and remove it. Signed-off-by: Dave Martin --- arm/aarch32/include/kvm/kvm-cpu-arch.h | 3 ++- arm/aarch64/include/kvm/kvm-cpu-arch.h | 3 +-- arm/aarch64/kvm-cpu.c | 22 ++ arm/kvm-cpu.c | 12 +--- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/arm/aarch32/include/kvm/kvm-cpu-arch.h b/arm/aarch32/include/kvm/kvm-cpu-arch.h index 3ec6f03..01983f0 100644 --- a/arm/aarch32/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch32/include/kvm/kvm-cpu-arch.h @@ -13,6 +13,7 @@ #define ARM_CPU_ID 0, 0, 0 #define ARM_CPU_ID_MPIDR 5 -#define ARM_VCPU_PTRAUTH_FEATURE 0 +static inline void kvm_cpu__select_features(struct kvm *kvm, + struct kvm_vcpu_init *init) { } #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h index 9fa99fb..e6875fc 100644 --- a/arm/aarch64/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h @@ -17,7 +17,6 @@ #define ARM_CPU_CTRL 3, 0, 1, 0 #define ARM_CPU_CTRL_SCTLR_EL1 0 -#define ARM_VCPU_PTRAUTH_FEATURE ((1UL << KVM_ARM_VCPU_PTRAUTH_ADDRESS) \ - | (1UL << KVM_ARM_VCPU_PTRAUTH_GENERIC)) +void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init); #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c index 0aaefaf..d3c32e0 100644 --- a/arm/aarch64/kvm-cpu.c +++ b/arm/aarch64/kvm-cpu.c @@ -128,6 +128,28 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu) } } +static void select_ptrauth_feature(struct kvm *kvm, struct kvm_vcpu_init *init) +{ + /* Check Pointer Authentication command line arguments. */ + if (kvm->cfg.arch.enable_ptrauth && kvm->cfg.arch.disable_ptrauth) + die("Both enable-ptrauth and disable-ptrauth option cannot be present"); + /* +* Always enable Pointer Authentication if system supports +* this extension unless disable-ptrauth option is present. +*/ + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) && + kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC) && + !kvm->cfg.arch.disable_ptrauth) { + init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_ADDRESS; + init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_GENERIC; + } +} + +void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init) +{ + select_ptrauth_feature(kvm, init); +} + void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu) { if (vcpu->kvm->cfg.arch.aarch32_guest) diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c index acd1d5f..764fb05 100644 --- a/arm/kvm-cpu.c +++ b/arm/kvm-cpu.c @@ -68,17 +68,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2); } - /* Check Pointer Authentication command line arguments. */ - if (kvm->cfg.arch.enable_ptrauth && kvm->cfg.arch.disable_ptrauth) - die("Both enable-ptrauth and disable-ptrauth option cannot be present"); - /* -* Always enable Pointer Authentication if system supports -* this extension unless disable-ptrauth option is present. -*/ - if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) && - kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC) && - !kvm->cfg.arch.disable_ptrauth) - vcpu_init.features[0] |= ARM_VCPU_PTRAUTH_FEATURE; + kvm_cpu__select_features(kvm, _init); /* * If the preferred target ioctl is successful then -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 9/9] arm64: Select SVE vector lengths via the command line
In order to support use cases such as migration, it may be important in some situations to restrict the set of SVE vector lengths available to the guest. It can also be useful to observe the behaviour of guest OSes with different vector lengths. To enable testing and experimentation for such configurations, this patch adds a command-line option to allow setting of the set of vector lengths to be made available to the guest. For now, the setting is global: no means is offered to configure individual guest vcpus independently of each other. By default all vector lengths that the host can support are given to the guest, as before. Signed-off-by: Dave Martin --- arm/aarch64/include/kvm/kvm-config-arch.h | 8 +++- arm/aarch64/kvm-cpu.c | 80 ++- arm/include/arm-common/kvm-config-arch.h | 1 + 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h index 41e9d05..a996612 100644 --- a/arm/aarch64/include/kvm/kvm-config-arch.h +++ b/arm/aarch64/include/kvm/kvm-config-arch.h @@ -1,6 +1,8 @@ #ifndef KVM__KVM_CONFIG_ARCH_H #define KVM__KVM_CONFIG_ARCH_H +int sve_vls_parser(const struct option *opt, const char *arg, int unset); + #define ARM_OPT_ARCH_RUN(cfg) \ OPT_BOOLEAN('\0', "aarch32", &(cfg)->aarch32_guest, \ "Run AArch32 guest"), \ @@ -16,7 +18,11 @@ OPT_BOOLEAN('\0', "enable-sve", &(cfg)->enable_sve, \ "Enable SVE for the guest"),\ OPT_BOOLEAN('\0', "disable-sve", &(cfg)->disable_sve, \ - "Disable SVE for the guest"), + "Disable SVE for the guest"), \ + OPT_CALLBACK('\0', "sve-vls", &(cfg)->sve_vqs, \ +"comma-separated list of vector lengths, in 128-bit units", \ +"Set of vector lengths to enable for the guest", \ +sve_vls_parser, NULL), #include "arm-common/kvm-config-arch.h" diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c index cdfb22e..2c624c3 100644 --- a/arm/aarch64/kvm-cpu.c +++ b/arm/aarch64/kvm-cpu.c @@ -1,8 +1,13 @@ +#include +#include +#include + #include "kvm/kvm-cpu.h" #include "kvm/kvm.h" #include "kvm/virtio.h" #include +#include #define COMPAT_PSR_F_BIT 0x0040 #define COMPAT_PSR_I_BIT 0x0080 @@ -12,6 +17,65 @@ #define SCTLR_EL1_E0E_MASK (1 << 24) #define SCTLR_EL1_EE_MASK (1 << 25) +/* + * Work around old kernel headers that lack these definitions in + * : + */ +#ifndef SVE_VQ_MIN +#define SVE_VQ_MIN 1 +#endif + +#ifndef SVE_VQ_MAX +#define SVE_VQ_MAX 512 +#endif + +int sve_vls_parser(const struct option *opt, const char *arg, int unset) +{ + size_t offset = 0; + int vq, n, t; + u64 (*vqs)[(SVE_VQ_MAX + 1 - SVE_VQ_MIN + 63) / 64]; + u64 **cfg_vqs = opt->value; + + if (*cfg_vqs) { + pr_err("sve-vls: SVE vector lengths set may only be specified once"); + return -1; + } + + vqs = calloc(1, sizeof *vqs); + if (!vqs) + die("%s", strerror(ENOMEM)); + + offset = 0; + while (arg[offset]) { + n = -1; + + t = sscanf(arg + offset, + offset == 0 ? "%i%n" : ",%i%n", + , ); + if (t == EOF || t < 1 || n <= 0) { + pr_err("sve-vls: Comma-separated list of vector lengths required"); + goto error; + } + + if (vq < SVE_VQ_MIN || vq > SVE_VQ_MAX) { + pr_err("sve-vls: Invalid vector length %d", vq); + goto error; + } + + vq -= SVE_VQ_MIN; + (*vqs)[vq / 64] |= (u64)1 << (vq % 64); + + offset += n; + } + + *cfg_vqs = *vqs; + return 0; + +error: + free(vqs); + return -1; +} + static __u64 __core_reg_id(__u64 offset) { __u64 id = KVM_REG_ARM64 | KVM_REG_ARM_CORE | offset; @@ -180,6 +244,16 @@ void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init *init) static int configure_sve(struct kvm_cpu *vcpu) { int feature = KVM_ARM_VCPU_SVE; + struct kvm_one_reg r = { + .id = KVM_REG_ARM64_SVE_VLS, + .addr = (u64)vcpu->kvm->cfg.arch.sve_vqs, + }; + + if (vcpu->kvm->cfg.arch.sve_vqs) + if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, )) { + pr_err("Cannot set requested SVE vector lengths"); + return -1; + } if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_FINALIZE, )) { pr_err("KVM_ARM_VCPU_FINALIZE: %s", strerror(errno)); @@
[PATCH kvmtool v3 7/9] arm64: Make ptrauth enable/disable diagnostics more user-friendly
To help the user understand what is going on, amend ptrauth configuration diagnostic messages to refer to command line options by the exact name used on the command line. Also, provide a clean diagnostic when ptrauth is requested, but not availble. The generic "Unable to initialise vcpu" message is rather cryptic for this case. Since we now don't attempt to enable ptrauth at all unless KVM reports the relevant capabilities, remove the error message for that case too: in any case, we can't diagnose precisely why KVM_ARM_VCPU_INIT failed, so the message may be misleading. Signed-off-by: Dave Martin --- arm/aarch64/include/kvm/kvm-config-arch.h | 4 ++-- arm/aarch64/kvm-cpu.c | 15 +++ arm/kvm-cpu.c | 8 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h index 0279b13..fe1699d 100644 --- a/arm/aarch64/include/kvm/kvm-config-arch.h +++ b/arm/aarch64/include/kvm/kvm-config-arch.h @@ -10,9 +10,9 @@ "Specify random seed for Kernel Address Space " \ "Layout Randomization (KASLR)"),\ OPT_BOOLEAN('\0', "enable-ptrauth", &(cfg)->enable_ptrauth, \ - "Enables pointer authentication"), \ + "Enable pointer authentication for the guest"), \ OPT_BOOLEAN('\0', "disable-ptrauth", &(cfg)->disable_ptrauth, \ - "Disables pointer authentication"), + "Disable pointer authentication for the guest"), #include "arm-common/kvm-config-arch.h" diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c index d3c32e0..08e4fd5 100644 --- a/arm/aarch64/kvm-cpu.c +++ b/arm/aarch64/kvm-cpu.c @@ -130,16 +130,23 @@ static void reset_vcpu_aarch64(struct kvm_cpu *vcpu) static void select_ptrauth_feature(struct kvm *kvm, struct kvm_vcpu_init *init) { + bool supported; + /* Check Pointer Authentication command line arguments. */ if (kvm->cfg.arch.enable_ptrauth && kvm->cfg.arch.disable_ptrauth) - die("Both enable-ptrauth and disable-ptrauth option cannot be present"); + die("--enable-ptrauth conflicts with --disable-ptrauth"); + + supported = kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) && + kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC); + + if (kvm->cfg.arch.enable_ptrauth && !supported) + die("--enable-ptrauth not supported on this host"); + /* * Always enable Pointer Authentication if system supports * this extension unless disable-ptrauth option is present. */ - if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) && - kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC) && - !kvm->cfg.arch.disable_ptrauth) { + if (supported && !kvm->cfg.arch.disable_ptrauth) { init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_ADDRESS; init->features[0] |= 1UL << KVM_ARM_VCPU_PTRAUTH_GENERIC; } diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c index 764fb05..1652f6f 100644 --- a/arm/kvm-cpu.c +++ b/arm/kvm-cpu.c @@ -108,12 +108,8 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) die("Unable to find matching target"); } - if (err || target->init(vcpu)) { - if (kvm->cfg.arch.enable_ptrauth) - die("Unable to initialise vcpu with pointer authentication feature"); - else - die("Unable to initialise vcpu"); - } + if (err || target->init(vcpu)) + die("Unable to initialise vcpu"); coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO); -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 5/9] KVM: arm/arm64: Add a vcpu feature for pointer authentication
From: Amit Daniel Kachhap This patch adds a runtime capabality for KVM tool to enable Arm64 8.3 Pointer Authentication in guest kernel. Two vcpu features KVM_ARM_VCPU_PTRAUTH_[ADDRESS/GENERIC] are supplied together to enable Pointer Authentication in KVM guest after checking the capability. Command line options --enable-ptrauth and --disable-ptrauth are added to use this feature. However, if those options are not provided then also this feature is enabled if host supports this capability. The macros defined in the headers are not in sync and should be replaced from the upstream. Signed-off-by: Amit Daniel Kachhap Signed-off-by: Dave Martin [merge new kernel heaers] --- arm/aarch32/include/kvm/kvm-cpu-arch.h| 2 ++ arm/aarch64/include/kvm/kvm-config-arch.h | 6 +- arm/aarch64/include/kvm/kvm-cpu-arch.h| 3 +++ arm/include/arm-common/kvm-config-arch.h | 2 ++ arm/kvm-cpu.c | 20 ++-- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/arm/aarch32/include/kvm/kvm-cpu-arch.h b/arm/aarch32/include/kvm/kvm-cpu-arch.h index d28ea67..3ec6f03 100644 --- a/arm/aarch32/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch32/include/kvm/kvm-cpu-arch.h @@ -13,4 +13,6 @@ #define ARM_CPU_ID 0, 0, 0 #define ARM_CPU_ID_MPIDR 5 +#define ARM_VCPU_PTRAUTH_FEATURE 0 + #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/aarch64/include/kvm/kvm-config-arch.h b/arm/aarch64/include/kvm/kvm-config-arch.h index 04be43d..0279b13 100644 --- a/arm/aarch64/include/kvm/kvm-config-arch.h +++ b/arm/aarch64/include/kvm/kvm-config-arch.h @@ -8,7 +8,11 @@ "Create PMUv3 device"), \ OPT_U64('\0', "kaslr-seed", &(cfg)->kaslr_seed, \ "Specify random seed for Kernel Address Space " \ - "Layout Randomization (KASLR)"), + "Layout Randomization (KASLR)"),\ + OPT_BOOLEAN('\0', "enable-ptrauth", &(cfg)->enable_ptrauth, \ + "Enables pointer authentication"), \ + OPT_BOOLEAN('\0', "disable-ptrauth", &(cfg)->disable_ptrauth, \ + "Disables pointer authentication"), #include "arm-common/kvm-config-arch.h" diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h b/arm/aarch64/include/kvm/kvm-cpu-arch.h index a9d8563..9fa99fb 100644 --- a/arm/aarch64/include/kvm/kvm-cpu-arch.h +++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h @@ -17,4 +17,7 @@ #define ARM_CPU_CTRL 3, 0, 1, 0 #define ARM_CPU_CTRL_SCTLR_EL1 0 +#define ARM_VCPU_PTRAUTH_FEATURE ((1UL << KVM_ARM_VCPU_PTRAUTH_ADDRESS) \ + | (1UL << KVM_ARM_VCPU_PTRAUTH_GENERIC)) + #endif /* KVM__KVM_CPU_ARCH_H */ diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h index 5734c46..1b4287d 100644 --- a/arm/include/arm-common/kvm-config-arch.h +++ b/arm/include/arm-common/kvm-config-arch.h @@ -10,6 +10,8 @@ struct kvm_config_arch { boolaarch32_guest; boolhas_pmuv3; u64 kaslr_seed; + boolenable_ptrauth; + booldisable_ptrauth; enum irqchip_type irqchip; u64 fw_addr; }; diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c index 7780251..acd1d5f 100644 --- a/arm/kvm-cpu.c +++ b/arm/kvm-cpu.c @@ -68,6 +68,18 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2); } + /* Check Pointer Authentication command line arguments. */ + if (kvm->cfg.arch.enable_ptrauth && kvm->cfg.arch.disable_ptrauth) + die("Both enable-ptrauth and disable-ptrauth option cannot be present"); + /* +* Always enable Pointer Authentication if system supports +* this extension unless disable-ptrauth option is present. +*/ + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_ADDRESS) && + kvm__supports_extension(kvm, KVM_CAP_ARM_PTRAUTH_GENERIC) && + !kvm->cfg.arch.disable_ptrauth) + vcpu_init.features[0] |= ARM_VCPU_PTRAUTH_FEATURE; + /* * If the preferred target ioctl is successful then * use preferred target else try each and every target type @@ -106,8 +118,12 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) die("Unable to find matching target"); } - if (err || target->init(vcpu)) - die("Unable to initialise vcpu"); + if (err || target->init(vcpu)) { + if (kvm->cfg.arch.enable_ptrauth) + die("Unable to initialise vcpu with pointer authentication feature"); + else + die("Unable to initialise vcpu"); + }
[PATCH kvmtool v3 3/9] update_headers.sh: arm64: Copy sve_context.h if available
The SVE KVM support for arm64 includes the additional backend header from . So update this header if it is available. To avoid creating a sudden dependency on a specific minimum kernel version, ignore the header if the source kernel tree doesn't have it. Signed-off-by: Dave Martin --- util/update_headers.sh | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/util/update_headers.sh b/util/update_headers.sh index a7e21b8..90d3ead 100755 --- a/util/update_headers.sh +++ b/util/update_headers.sh @@ -25,11 +25,22 @@ fi cp -- "$LINUX_ROOT/include/uapi/linux/kvm.h" include/linux +unset KVMTOOL_PATH + +copy_arm64 () { + local src=$LINUX_ROOT/arch/$arch/include/uapi/asm/sve_context.h + + if [ -e "$src" ] + then + cp -- "$src" "$KVMTOOL_PATH/include/asm" + fi +} + for arch in arm arm64 mips powerpc x86 do case "$arch" in arm) KVMTOOL_PATH=arm/aarch32 ;; - arm64) KVMTOOL_PATH=arm/aarch64 ;; + arm64) KVMTOOL_PATH=arm/aarch64; copy_arm64 ;; *) KVMTOOL_PATH=$arch ;; esac cp -- "$LINUX_ROOT/arch/$arch/include/uapi/asm/kvm.h" \ -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 4/9] update_headers: Sync kvm UAPI headers with linux v5.1-rc1
Pull in upstream UAPI headers, for subsequent arm64 SVE / ptrauth support (among other things). Signed-off-by: Dave Martin --- arm/aarch64/include/asm/kvm.h | 43 arm/aarch64/include/asm/sve_context.h | 53 +++ include/linux/kvm.h | 15 -- powerpc/include/asm/kvm.h | 48 +++ x86/include/asm/kvm.h | 1 + 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 arm/aarch64/include/asm/sve_context.h diff --git a/arm/aarch64/include/asm/kvm.h b/arm/aarch64/include/asm/kvm.h index 97c3478..7b7ac0f 100644 --- a/arm/aarch64/include/asm/kvm.h +++ b/arm/aarch64/include/asm/kvm.h @@ -35,6 +35,7 @@ #include #include #include +#include #define __KVM_HAVE_GUEST_DEBUG #define __KVM_HAVE_IRQ_LINE @@ -102,6 +103,9 @@ struct kvm_regs { #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ #define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */ #define KVM_ARM_VCPU_PMU_V33 /* Support guest PMUv3 */ +#define KVM_ARM_VCPU_SVE 4 /* enable SVE for this CPU */ +#define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5 /* VCPU uses address authentication */ +#define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication */ struct kvm_vcpu_init { __u32 target; @@ -226,6 +230,45 @@ struct kvm_vcpu_events { KVM_REG_ARM_FW | ((r) & 0x)) #define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0) +/* SVE registers */ +#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT) + +/* Z- and P-regs occupy blocks at the following offsets within this range: */ +#define KVM_REG_ARM64_SVE_ZREG_BASE0 +#define KVM_REG_ARM64_SVE_PREG_BASE0x400 +#define KVM_REG_ARM64_SVE_FFR_BASE 0x600 + +#define KVM_ARM64_SVE_NUM_ZREGS__SVE_NUM_ZREGS +#define KVM_ARM64_SVE_NUM_PREGS__SVE_NUM_PREGS + +#define KVM_ARM64_SVE_MAX_SLICES 32 + +#define KVM_REG_ARM64_SVE_ZREG(n, i) \ + (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_ZREG_BASE | \ +KVM_REG_SIZE_U2048 | \ +(((n) & (KVM_ARM64_SVE_NUM_ZREGS - 1)) << 5) | \ +((i) & (KVM_ARM64_SVE_MAX_SLICES - 1))) + +#define KVM_REG_ARM64_SVE_PREG(n, i) \ + (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_PREG_BASE | \ +KVM_REG_SIZE_U256 |\ +(((n) & (KVM_ARM64_SVE_NUM_PREGS - 1)) << 5) | \ +((i) & (KVM_ARM64_SVE_MAX_SLICES - 1))) + +#define KVM_REG_ARM64_SVE_FFR(i) \ + (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_FFR_BASE | \ +KVM_REG_SIZE_U256 |\ +((i) & (KVM_ARM64_SVE_MAX_SLICES - 1))) + +#define KVM_ARM64_SVE_VQ_MIN __SVE_VQ_MIN +#define KVM_ARM64_SVE_VQ_MAX __SVE_VQ_MAX + +/* Vector lengths pseudo-register: */ +#define KVM_REG_ARM64_SVE_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \ +KVM_REG_SIZE_U512 | 0x) +#define KVM_ARM64_SVE_VLS_WORDS\ + ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) + /* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 diff --git a/arm/aarch64/include/asm/sve_context.h b/arm/aarch64/include/asm/sve_context.h new file mode 100644 index 000..754ab75 --- /dev/null +++ b/arm/aarch64/include/asm/sve_context.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* Copyright (C) 2017-2018 ARM Limited */ + +/* + * For use by other UAPI headers only. + * Do not make direct use of header or its definitions. + */ + +#ifndef _UAPI__ASM_SVE_CONTEXT_H +#define _UAPI__ASM_SVE_CONTEXT_H + +#include + +#define __SVE_VQ_BYTES 16 /* number of bytes per quadword */ + +#define __SVE_VQ_MIN 1 +#define __SVE_VQ_MAX 512 + +#define __SVE_VL_MIN (__SVE_VQ_MIN * __SVE_VQ_BYTES) +#define __SVE_VL_MAX (__SVE_VQ_MAX * __SVE_VQ_BYTES) + +#define __SVE_NUM_ZREGS32 +#define __SVE_NUM_PREGS16 + +#define __sve_vl_valid(vl) \ + ((vl) % __SVE_VQ_BYTES == 0 && \ +(vl) >= __SVE_VL_MIN &&\ +(vl) <= __SVE_VL_MAX) + +#define __sve_vq_from_vl(vl) ((vl) / __SVE_VQ_BYTES) +#define __sve_vl_from_vq(vq) ((vq) * __SVE_VQ_BYTES) + +#define __SVE_ZREG_SIZE(vq)((__u32)(vq) * __SVE_VQ_BYTES) +#define __SVE_PREG_SIZE(vq)((__u32)(vq) * (__SVE_VQ_BYTES / 8)) +#define __SVE_FFR_SIZE(vq) __SVE_PREG_SIZE(vq) + +#define __SVE_ZREGS_OFFSET 0 +#define __SVE_ZREG_OFFSET(vq, n) \ +
[PATCH kvmtool v3 2/9] update_headers.sh: Cleanly report failure on error
If in intermediate step fails, update_headers.sh blindly continues and may return success status. To avoid errors going unnoticed when driving this script, exit and report failure status as soon as something goes wrong. For good measure, also fail on expansion of undefined shell variables to aid future maintainers. Signed-off-by: Dave Martin --- util/update_headers.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/update_headers.sh b/util/update_headers.sh index 4ba1b9f..a7e21b8 100755 --- a/util/update_headers.sh +++ b/util/update_headers.sh @@ -7,6 +7,8 @@ # using the lib/modules/`uname -r`/source link. +set -ue + if [ "$#" -ge 1 ] then LINUX_ROOT="$1" -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 1/9] update_headers.sh: Add missing shell quoting
update_headers.sh can break if the current working directory has a funny name or if something odd is passed for LINUX_ROOT. In the interest of cleanliness, quote where appropriate. Signed-off-by: Dave Martin --- util/update_headers.sh | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/util/update_headers.sh b/util/update_headers.sh index 2d93646..4ba1b9f 100755 --- a/util/update_headers.sh +++ b/util/update_headers.sh @@ -11,17 +11,17 @@ if [ "$#" -ge 1 ] then LINUX_ROOT="$1" else - LINUX_ROOT=/lib/modules/$(uname -r)/source + LINUX_ROOT="/lib/modules/$(uname -r)/source" fi -if [ ! -d $LINUX_ROOT/include/uapi/linux ] +if [ ! -d "$LINUX_ROOT/include/uapi/linux" ] then echo "$LINUX_ROOT does not seem to be valid Linux source tree." echo "usage: $0 [path-to-Linux-source-tree]" exit 1 fi -cp $LINUX_ROOT/include/uapi/linux/kvm.h include/linux +cp -- "$LINUX_ROOT/include/uapi/linux/kvm.h" include/linux for arch in arm arm64 mips powerpc x86 do @@ -30,6 +30,6 @@ do arm64) KVMTOOL_PATH=arm/aarch64 ;; *) KVMTOOL_PATH=$arch ;; esac - cp $LINUX_ROOT/arch/$arch/include/uapi/asm/kvm.h \ - $KVMTOOL_PATH/include/asm + cp -- "$LINUX_ROOT/arch/$arch/include/uapi/asm/kvm.h" \ + "$KVMTOOL_PATH/include/asm" done -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH kvmtool v3 0/9] arm64: Pointer Authentication and SVE support
This series, based on kvmtool master [1], implements basic support for pointer authentication and SVE for guests. A git tree is also available [2]. For pointer auth, I include Amit's v10 patch [3], with some additional refactoring to sit nicely alongside SVE, and some cosmetic / diagnostic tidyups discussed during review on-list. (I've kept the extra changes separate for easier review, but they could be folded if desired.) [Maintainer note: I'd like Amit to comment on my changes on top of his pointer auth patch, but the first 4 patches just re-sync headers and could be pulled earlier if you feel like it.] This series has been tested against Linux v5.2-rc1. If people have a strong view on the --sve-vls parameter, I'd be interested to discuss what that should look like. Since this is primarily a debug/experimentation option, the current implementation is probably good enough though. [1] git://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git master https://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git/log/ eaeaf60808d6 ("virtio/blk: Avoid taking pointer to packed struct") [2] [PATCH v10 3/5] KVM: arm64: Add userspace flag to enable pointer authentication https://lore.kernel.org/linux-arm-kernel/1555994558-26349-6-git-send-email-amit.kach...@arm.com/ [3] git://linux-arm.org/kvmtool-dm.git sve/v3/head http://linux-arm.org/git?p=kvmtool-dm.git;a=shortlog;h=refs/heads/sve/v3/head Amit Daniel Kachhap (1): KVM: arm/arm64: Add a vcpu feature for pointer authentication Dave Martin (8): update_headers.sh: Add missing shell quoting update_headers.sh: Cleanly report failure on error update_headers.sh: arm64: Copy sve_context.h if available update_headers: Sync kvm UAPI headers with linux v5.1-rc1 arm/arm64: Factor out ptrauth vcpu feature setup arm64: Make ptrauth enable/disable diagnostics more user-friendly arm64: Add SVE support arm64: Select SVE vector lengths via the command line arm/aarch32/include/kvm/kvm-cpu-arch.h| 7 ++ arm/aarch64/include/asm/kvm.h | 43 + arm/aarch64/include/asm/sve_context.h | 53 +++ arm/aarch64/include/kvm/kvm-config-arch.h | 16 +++- arm/aarch64/include/kvm/kvm-cpu-arch.h| 3 + arm/aarch64/kvm-cpu.c | 148 ++ arm/include/arm-common/kvm-config-arch.h | 5 + arm/kvm-cpu.c | 5 + include/linux/kvm.h | 15 ++- powerpc/include/asm/kvm.h | 48 ++ util/update_headers.sh| 25 +++-- x86/include/asm/kvm.h | 1 + 12 files changed, 360 insertions(+), 9 deletions(-) create mode 100644 arm/aarch64/include/asm/sve_context.h -- 2.1.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm