From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687216615659.47542341627; Fri, 14 Feb 2020 05:33:36 -0800 (PST) Received: from localhost ([::1]:38970 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b67-0000R7-9a for importer@patchew.org; Fri, 14 Feb 2020 08:33:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51911) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b13-0000UL-63 for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b10-0006PI-7t for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:21 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:29512 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b0z-0006HF-8j for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:17 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-110-3uUTq2XBNv6945AzjoE6ZQ-1; Fri, 14 Feb 2020 08:28:12 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BFD0313E6; Fri, 14 Feb 2020 13:28:10 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2FBC35DA7D; Fri, 14 Feb 2020 13:28:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686896; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hXCJyr128+NX3FlIhAqfjz96XLQURryC229SK/tTxwY=; b=SPu/+SZARqvGjLPQozJ0kNh64Z2lvxnFcfxtyCozhCR6y7RUBRVsbVy7lYPp+oItNryeyv kBbTthIk7ZaKzUopi557Sy6FuKt781bWl23Yo46WiCdiRKsYYIZlkKRH/AnFbIhpxCeeyw umFBH5Tq3wXSn6E1s11o4R7agrNFIhU= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 01/10] virtio-iommu: Add skeleton Date: Fri, 14 Feb 2020 14:27:36 +0100 Message-Id: <20200214132745.23392-2-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: 3uUTq2XBNv6945AzjoE6ZQ-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patchs adds the skeleton for the virtio-iommu device. Signed-off-by: Eric Auger Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin --- v13 -> v14: - use device_class_set_props - updated copyright's year v12 -> v13 - removed IOMMU_PCI_BUS_MAX and IOMMU_PCI_DEVFN_MAX v11 -> v12: - remove s_by_bus_num - drop set_features (rely on default implementation) and acked_features v9 -> v10: - mutex initialized here - initialize tail - included hw/qdev-properties.h - removed g_memdup - removed s->config.domain_range.start =3D 0; v9 -> v10: - expose VIRTIO_IOMMU_F_MMIO feature - s/domain_bits/domain_range struct - change error codes - enforce unmigratable - Kconfig v7 -> v8: - expose VIRTIO_IOMMU_F_BYPASS and VIRTIO_F_VERSION_1 features - set_config dummy implementation + tracing - add trace in get_features - set the features on realize() and store the acked ones - remove inclusion of linux/virtio_iommu.h v6 -> v7: - removed qapi-event.h include - add primary_bus and associated property v4 -> v5: - use the new v0.5 terminology (domain, endpoint) - add the event virtqueue v3 -> v4: - use page_size_mask instead of page_sizes - added set_features() - added some traces (reset, set_status, set_features) - empty virtio_iommu_set_config() as the driver MUST NOT write to device configuration fields - add get_config trace v2 -> v3: - rebase on 2.10-rc0, ie. use IOMMUMemoryRegion and remove iommu_ops. - advertise VIRTIO_IOMMU_F_MAP_UNMAP feature - page_sizes set to TARGET_PAGE_SIZE Conflicts: hw/virtio/trace-events --- hw/virtio/Kconfig | 5 + hw/virtio/Makefile.objs | 1 + hw/virtio/trace-events | 7 + hw/virtio/virtio-iommu.c | 265 +++++++++++++++++++++++++++++++ include/hw/virtio/virtio-iommu.h | 57 +++++++ 5 files changed, 335 insertions(+) create mode 100644 hw/virtio/virtio-iommu.c create mode 100644 include/hw/virtio/virtio-iommu.h diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index f87def27a6..d29525b36f 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -9,6 +9,11 @@ config VIRTIO_RNG default y depends on VIRTIO =20 +config VIRTIO_IOMMU + bool + default y + depends on VIRTIO + config VIRTIO_PCI bool default y if PCI_DEVICES diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index de0f5fc39b..2fd9da7410 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -16,6 +16,7 @@ obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_P= CI)) +=3D virtio-crypto-p obj-$(CONFIG_VIRTIO_PMEM) +=3D virtio-pmem.o common-obj-$(call land,$(CONFIG_VIRTIO_PMEM),$(CONFIG_VIRTIO_PCI)) +=3D vi= rtio-pmem-pci.o obj-$(call land,$(CONFIG_VHOST_USER_FS),$(CONFIG_VIRTIO_PCI)) +=3D vhost-u= ser-fs-pci.o +obj-$(CONFIG_VIRTIO_IOMMU) +=3D virtio-iommu.o obj-$(CONFIG_VHOST_VSOCK) +=3D vhost-vsock.o =20 ifeq ($(CONFIG_VIRTIO_PCI),y) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index e28ba48da6..02d93d7f63 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -53,3 +53,10 @@ virtio_mmio_write_offset(uint64_t offset, uint64_t value= ) "virtio_mmio_write off virtio_mmio_guest_page(uint64_t size, int shift) "guest page size 0x%" PRI= x64 " shift %d" virtio_mmio_queue_write(uint64_t value, int max_size) "mmio_queue write 0x= %" PRIx64 " max %d" virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d" + +# hw/virtio/virtio-iommu.c +virtio_iommu_device_reset(void) "reset!" +virtio_iommu_get_features(uint64_t features) "device supports features=3D0= x%"PRIx64 +virtio_iommu_device_status(uint8_t status) "driver status =3D %d" +virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t = end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=3D0x%"PRIx= 64" start=3D0x%"PRIx64" end=3D0x%"PRIx64" domain_range=3D%d probe_size=3D0x= %x" +virtio_iommu_set_config(uint64_t page_size_mask, uint64_t start, uint64_t = end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=3D0x%"PRIx= 64" start=3D0x%"PRIx64" end=3D0x%"PRIx64" domain_bits=3D%d probe_size=3D0x%= x" diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c new file mode 100644 index 0000000000..30579267d5 --- /dev/null +++ b/hw/virtio/virtio-iommu.c @@ -0,0 +1,265 @@ +/* + * virtio-iommu device + * + * Copyright (c) 2020 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + * + */ + +#include "qemu/osdep.h" +#include "qemu/iov.h" +#include "qemu-common.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/virtio.h" +#include "sysemu/kvm.h" +#include "trace.h" + +#include "standard-headers/linux/virtio_ids.h" + +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/virtio-access.h" +#include "hw/virtio/virtio-iommu.h" + +/* Max size */ +#define VIOMMU_DEFAULT_QUEUE_SIZE 256 + +static int virtio_iommu_handle_attach(VirtIOIOMMU *s, + struct iovec *iov, + unsigned int iov_cnt) +{ + return VIRTIO_IOMMU_S_UNSUPP; +} +static int virtio_iommu_handle_detach(VirtIOIOMMU *s, + struct iovec *iov, + unsigned int iov_cnt) +{ + return VIRTIO_IOMMU_S_UNSUPP; +} +static int virtio_iommu_handle_map(VirtIOIOMMU *s, + struct iovec *iov, + unsigned int iov_cnt) +{ + return VIRTIO_IOMMU_S_UNSUPP; +} +static int virtio_iommu_handle_unmap(VirtIOIOMMU *s, + struct iovec *iov, + unsigned int iov_cnt) +{ + return VIRTIO_IOMMU_S_UNSUPP; +} + +static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOIOMMU *s =3D VIRTIO_IOMMU(vdev); + struct virtio_iommu_req_head head; + struct virtio_iommu_req_tail tail =3D {}; + VirtQueueElement *elem; + unsigned int iov_cnt; + struct iovec *iov; + size_t sz; + + for (;;) { + elem =3D virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + return; + } + + if (iov_size(elem->in_sg, elem->in_num) < sizeof(tail) || + iov_size(elem->out_sg, elem->out_num) < sizeof(head)) { + virtio_error(vdev, "virtio-iommu bad head/tail size"); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + break; + } + + iov_cnt =3D elem->out_num; + iov =3D elem->out_sg; + sz =3D iov_to_buf(iov, iov_cnt, 0, &head, sizeof(head)); + if (unlikely(sz !=3D sizeof(head))) { + tail.status =3D VIRTIO_IOMMU_S_DEVERR; + goto out; + } + qemu_mutex_lock(&s->mutex); + switch (head.type) { + case VIRTIO_IOMMU_T_ATTACH: + tail.status =3D virtio_iommu_handle_attach(s, iov, iov_cnt); + break; + case VIRTIO_IOMMU_T_DETACH: + tail.status =3D virtio_iommu_handle_detach(s, iov, iov_cnt); + break; + case VIRTIO_IOMMU_T_MAP: + tail.status =3D virtio_iommu_handle_map(s, iov, iov_cnt); + break; + case VIRTIO_IOMMU_T_UNMAP: + tail.status =3D virtio_iommu_handle_unmap(s, iov, iov_cnt); + break; + default: + tail.status =3D VIRTIO_IOMMU_S_UNSUPP; + } + qemu_mutex_unlock(&s->mutex); + +out: + sz =3D iov_from_buf(elem->in_sg, elem->in_num, 0, + &tail, sizeof(tail)); + assert(sz =3D=3D sizeof(tail)); + + virtqueue_push(vq, elem, sizeof(tail)); + virtio_notify(vdev, vq); + g_free(elem); + } +} + +static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_da= ta) +{ + VirtIOIOMMU *dev =3D VIRTIO_IOMMU(vdev); + struct virtio_iommu_config *config =3D &dev->config; + + trace_virtio_iommu_get_config(config->page_size_mask, + config->input_range.start, + config->input_range.end, + config->domain_range.end, + config->probe_size); + memcpy(config_data, &dev->config, sizeof(struct virtio_iommu_config)); +} + +static void virtio_iommu_set_config(VirtIODevice *vdev, + const uint8_t *config_data) +{ + struct virtio_iommu_config config; + + memcpy(&config, config_data, sizeof(struct virtio_iommu_config)); + trace_virtio_iommu_set_config(config.page_size_mask, + config.input_range.start, + config.input_range.end, + config.domain_range.end, + config.probe_size); +} + +static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f, + Error **errp) +{ + VirtIOIOMMU *dev =3D VIRTIO_IOMMU(vdev); + + f |=3D dev->features; + trace_virtio_iommu_get_features(f); + return f; +} + +/* + * Migration is not yet supported: most of the state consists + * of balanced binary trees which are not yet ready for getting + * migrated + */ +static const VMStateDescription vmstate_virtio_iommu_device =3D { + .name =3D "virtio-iommu-device", + .unmigratable =3D 1, +}; + +static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VirtIOIOMMU *s =3D VIRTIO_IOMMU(dev); + + virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU, + sizeof(struct virtio_iommu_config)); + + s->req_vq =3D virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, + virtio_iommu_handle_command); + s->event_vq =3D virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, NULL= ); + + s->config.page_size_mask =3D TARGET_PAGE_MASK; + s->config.input_range.end =3D -1UL; + s->config.domain_range.end =3D 32; + + virtio_add_feature(&s->features, VIRTIO_RING_F_EVENT_IDX); + virtio_add_feature(&s->features, VIRTIO_RING_F_INDIRECT_DESC); + virtio_add_feature(&s->features, VIRTIO_F_VERSION_1); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_INPUT_RANGE); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_DOMAIN_RANGE); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MAP_UNMAP); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS); + virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MMIO); + + qemu_mutex_init(&s->mutex); +} + +static void virtio_iommu_device_unrealize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + + virtio_cleanup(vdev); +} + +static void virtio_iommu_device_reset(VirtIODevice *vdev) +{ + trace_virtio_iommu_device_reset(); +} + +static void virtio_iommu_set_status(VirtIODevice *vdev, uint8_t status) +{ + trace_virtio_iommu_device_status(status); +} + +static void virtio_iommu_instance_init(Object *obj) +{ +} + +static const VMStateDescription vmstate_virtio_iommu =3D { + .name =3D "virtio-iommu", + .minimum_version_id =3D 1, + .version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, +}; + +static Property virtio_iommu_properties[] =3D { + DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, "PCI", PCIBu= s *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_iommu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); + + device_class_set_props(dc, virtio_iommu_properties); + dc->vmsd =3D &vmstate_virtio_iommu; + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->realize =3D virtio_iommu_device_realize; + vdc->unrealize =3D virtio_iommu_device_unrealize; + vdc->reset =3D virtio_iommu_device_reset; + vdc->get_config =3D virtio_iommu_get_config; + vdc->set_config =3D virtio_iommu_set_config; + vdc->get_features =3D virtio_iommu_get_features; + vdc->set_status =3D virtio_iommu_set_status; + vdc->vmsd =3D &vmstate_virtio_iommu_device; +} + +static const TypeInfo virtio_iommu_info =3D { + .name =3D TYPE_VIRTIO_IOMMU, + .parent =3D TYPE_VIRTIO_DEVICE, + .instance_size =3D sizeof(VirtIOIOMMU), + .instance_init =3D virtio_iommu_instance_init, + .class_init =3D virtio_iommu_class_init, +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_iommu_info); +} + +type_init(virtio_register_types) diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-io= mmu.h new file mode 100644 index 0000000000..d24ba63305 --- /dev/null +++ b/include/hw/virtio/virtio-iommu.h @@ -0,0 +1,57 @@ +/* + * virtio-iommu device + * + * Copyright (c) 2020 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + * + */ + +#ifndef QEMU_VIRTIO_IOMMU_H +#define QEMU_VIRTIO_IOMMU_H + +#include "standard-headers/linux/virtio_iommu.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#define TYPE_VIRTIO_IOMMU "virtio-iommu-device" +#define VIRTIO_IOMMU(obj) \ + OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU) + +typedef struct IOMMUDevice { + void *viommu; + PCIBus *bus; + int devfn; + IOMMUMemoryRegion iommu_mr; + AddressSpace as; +} IOMMUDevice; + +typedef struct IOMMUPciBus { + PCIBus *bus; + IOMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically allo= c */ +} IOMMUPciBus; + +typedef struct VirtIOIOMMU { + VirtIODevice parent_obj; + VirtQueue *req_vq; + VirtQueue *event_vq; + struct virtio_iommu_config config; + uint64_t features; + GHashTable *as_by_busptr; + PCIBus *primary_bus; + GTree *domains; + QemuMutex mutex; + GTree *endpoints; +} VirtIOIOMMU; + +#endif --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687003453296.24242196822945; Fri, 14 Feb 2020 05:30:03 -0800 (PST) Received: from localhost ([::1]:38876 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b2f-0002nj-OZ for importer@patchew.org; Fri, 14 Feb 2020 08:30:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51959) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b1B-0000en-BK for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b19-0006fV-Oo for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:29 -0500 Received: from us-smtp-2.mimecast.com ([205.139.110.61]:34789 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b19-0006eJ-Ke for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:27 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-324-zsNjojosO-W1sB_5W7lX9A-1; Fri, 14 Feb 2020 08:28:25 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F020D8017DF; Fri, 14 Feb 2020 13:28:23 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 73EE45DA7D; Fri, 14 Feb 2020 13:28:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686907; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BwAR3Enly+FAnDDYRZk73Iai37vFg1SYx0I/yo3BkVg=; b=NTCDpeq5FEERV+4snpPSoa379YWjx660aDHvSAcQOUC5Dw/AcfIYheb2cbrV7+39XWzpFZ GC7qqWJ19Hu2CKbgjNNKwb1NCH5+pEXNRDNcDUMwuH+wfERbskJRuYmeU42IPMB20QRBLC FPvIXXr9AJdXO0BGpjkVXMWyOhcX7Dk= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 02/10] virtio-iommu: Decode the command payload Date: Fri, 14 Feb 2020 14:27:37 +0100 Message-Id: <20200214132745.23392-3-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: zsNjojosO-W1sB_5W7lX9A-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patch adds the command payload decoding and introduces the functions that will do the actual command handling. Those functions are not yet implemented. Signed-off-by: Eric Auger Reviewed-by: Jean-Philippe Brucker Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin --- v11 -> v12: - ADded Jean and Peter's R-b v10 -> v11: - use a macro for handle command functions v9 -> v10: - make virtio_iommu_handle_* more compact and remove get_payload_size v7 -> v8: - handle new domain parameter in detach - remove reserved checks v5 -> v6: - change map/unmap semantics (remove size) v4 -> v5: - adopt new v0.5 terminology v3 -> v4: - no flags field anymore in struct virtio_iommu_req_unmap - test reserved on attach/detach, change trace proto - rebase on v2.10.0. --- hw/virtio/trace-events | 4 +++ hw/virtio/virtio-iommu.c | 76 +++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 02d93d7f63..f7141aa2f6 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -60,3 +60,7 @@ virtio_iommu_get_features(uint64_t features) "device supp= orts features=3D0x%"PRIx6 virtio_iommu_device_status(uint8_t status) "driver status =3D %d" virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t = end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=3D0x%"PRIx= 64" start=3D0x%"PRIx64" end=3D0x%"PRIx64" domain_range=3D%d probe_size=3D0x= %x" virtio_iommu_set_config(uint64_t page_size_mask, uint64_t start, uint64_t = end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=3D0x%"PRIx= 64" start=3D0x%"PRIx64" end=3D0x%"PRIx64" domain_bits=3D%d probe_size=3D0x%= x" +virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "domain=3D%d endpo= int=3D%d" +virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=3D%d endpo= int=3D%d" +virtio_iommu_map(uint32_t domain_id, uint64_t virt_start, uint64_t virt_en= d, uint64_t phys_start, uint32_t flags) "domain=3D%d virt_start=3D0x%"PRIx6= 4" virt_end=3D0x%"PRIx64 " phys_start=3D0x%"PRIx64" flags=3D%d" +virtio_iommu_unmap(uint32_t domain_id, uint64_t virt_start, uint64_t virt_= end) "domain=3D%d virt_start=3D0x%"PRIx64" virt_end=3D0x%"PRIx64 diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 30579267d5..86dcdc09a1 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -34,31 +34,83 @@ /* Max size */ #define VIOMMU_DEFAULT_QUEUE_SIZE 256 =20 -static int virtio_iommu_handle_attach(VirtIOIOMMU *s, - struct iovec *iov, - unsigned int iov_cnt) +static int virtio_iommu_attach(VirtIOIOMMU *s, + struct virtio_iommu_req_attach *req) { + uint32_t domain_id =3D le32_to_cpu(req->domain); + uint32_t ep_id =3D le32_to_cpu(req->endpoint); + + trace_virtio_iommu_attach(domain_id, ep_id); + return VIRTIO_IOMMU_S_UNSUPP; } -static int virtio_iommu_handle_detach(VirtIOIOMMU *s, - struct iovec *iov, - unsigned int iov_cnt) + +static int virtio_iommu_detach(VirtIOIOMMU *s, + struct virtio_iommu_req_detach *req) { + uint32_t domain_id =3D le32_to_cpu(req->domain); + uint32_t ep_id =3D le32_to_cpu(req->endpoint); + + trace_virtio_iommu_detach(domain_id, ep_id); + return VIRTIO_IOMMU_S_UNSUPP; } -static int virtio_iommu_handle_map(VirtIOIOMMU *s, - struct iovec *iov, - unsigned int iov_cnt) + +static int virtio_iommu_map(VirtIOIOMMU *s, + struct virtio_iommu_req_map *req) { + uint32_t domain_id =3D le32_to_cpu(req->domain); + uint64_t phys_start =3D le64_to_cpu(req->phys_start); + uint64_t virt_start =3D le64_to_cpu(req->virt_start); + uint64_t virt_end =3D le64_to_cpu(req->virt_end); + uint32_t flags =3D le32_to_cpu(req->flags); + + trace_virtio_iommu_map(domain_id, virt_start, virt_end, phys_start, fl= ags); + return VIRTIO_IOMMU_S_UNSUPP; } -static int virtio_iommu_handle_unmap(VirtIOIOMMU *s, - struct iovec *iov, - unsigned int iov_cnt) + +static int virtio_iommu_unmap(VirtIOIOMMU *s, + struct virtio_iommu_req_unmap *req) { + uint32_t domain_id =3D le32_to_cpu(req->domain); + uint64_t virt_start =3D le64_to_cpu(req->virt_start); + uint64_t virt_end =3D le64_to_cpu(req->virt_end); + + trace_virtio_iommu_unmap(domain_id, virt_start, virt_end); + return VIRTIO_IOMMU_S_UNSUPP; } =20 +static int virtio_iommu_iov_to_req(struct iovec *iov, + unsigned int iov_cnt, + void *req, size_t req_sz) +{ + size_t sz, payload_sz =3D req_sz - sizeof(struct virtio_iommu_req_tail= ); + + sz =3D iov_to_buf(iov, iov_cnt, 0, req, payload_sz); + if (unlikely(sz !=3D payload_sz)) { + return VIRTIO_IOMMU_S_INVAL; + } + return 0; +} + +#define virtio_iommu_handle_req(__req) \ +static int virtio_iommu_handle_ ## __req(VirtIOIOMMU *s, \ + struct iovec *iov, \ + unsigned int iov_cnt) \ +{ \ + struct virtio_iommu_req_ ## __req req; \ + int ret =3D virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req)); \ + \ + return ret ? ret : virtio_iommu_ ## __req(s, &req); \ +} + +virtio_iommu_handle_req(attach) +virtio_iommu_handle_req(detach) +virtio_iommu_handle_req(map) +virtio_iommu_handle_req(unmap) + static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) { VirtIOIOMMU *s =3D VIRTIO_IOMMU(vdev); --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 158168715550146.783270345230335; Fri, 14 Feb 2020 05:32:35 -0800 (PST) Received: from localhost ([::1]:38948 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b57-0006nb-PK for importer@patchew.org; Fri, 14 Feb 2020 08:32:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52005) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b1J-0000uL-6a for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b1G-0006yR-LD for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:37 -0500 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:47219 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b1G-0006xW-Gf for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:34 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-147-JZY9_L35MeaCwq_1eJeGjQ-1; Fri, 14 Feb 2020 08:28:32 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BCEEF18A6EC2; Fri, 14 Feb 2020 13:28:30 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9BBC95DA7D; Fri, 14 Feb 2020 13:28:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686913; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XNjQS0Af8brbd6r04SZCvop5jHlP82qHcdGsxEfH15M=; b=dr5Iyel+OFjsUgrm5g8k8Kpg4kykuHs1AKMLNO9qyW+BIA3uR9QUzgo19PfpiiGFRlPSXq tPZuXWeScrsjRO5NrpkoCUI1OleLVfsYXkabkHD+9vF08I0WzY/Du5NQCTZwc2boIhTmuN lZf6hoSPxRvOVNHre3Y9QrBwDQfiqWw= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 03/10] virtio-iommu: Implement attach/detach command Date: Fri, 14 Feb 2020 14:27:38 +0100 Message-Id: <20200214132745.23392-4-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: JZY9_L35MeaCwq_1eJeGjQ-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.81 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patch implements the endpoint attach/detach to/from a domain. Domain and endpoint internal datatypes are introduced. Both are stored in RB trees. The domain owns a list of endpoints attached to it. Also helpers to get/put end points and domains are introduced. As for the IOMMU memory regions, a callback is called on PCI bus enumeration that initializes for a given device on the bus hierarchy an IOMMU memory region. The PCI bus hierarchy is stored locally in IOMMUPciBus and IOMMUDevice objects. At the time of the enumeration, the bus number may not be computed yet. So operations that will need to retrieve the IOMMUdevice and its IOMMU memory region from the bus number and devfn, once the bus number is garanteed to be frozen, use an array of IOMMUPciBus, lazily populated. Signed-off-by: Eric Auger Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin --- v14 -> v15: - destroy mappings in put_domain and remove g_tree_destroy(domain->mappings) in virtio_iommu_detach v13 -> v14: - in virtio_iommu_put_endpoint, if the EP is attached to a domain, call virtio_iommu_detach_endpoint_from_domain() - remove domain ref counting and simply delete the mappings gtree when the last EP is detached from the domain - in virtio_iommu_detach_endpoint_from_domain(), return if the ep's domain is unset. v12 -> v13: - squashed v12 4, 5, 6 into this patch - rename virtio_iommu_get_sid into virtio_iommu_get_bdf v11 -> v12: - check the device is protected by the iommu on attach - on detach, check the domain id the device is attached to matches the one used in the detach command - fix mapping ref counter and destroy the domain when no end-points are attached anymore --- hw/virtio/trace-events | 6 + hw/virtio/virtio-iommu.c | 311 ++++++++++++++++++++++++++++++- include/hw/virtio/virtio-iommu.h | 3 + 3 files changed, 318 insertions(+), 2 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index f7141aa2f6..15595f8cd7 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -64,3 +64,9 @@ virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "= domain=3D%d endpoint=3D%d" virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=3D%d endpo= int=3D%d" virtio_iommu_map(uint32_t domain_id, uint64_t virt_start, uint64_t virt_en= d, uint64_t phys_start, uint32_t flags) "domain=3D%d virt_start=3D0x%"PRIx6= 4" virt_end=3D0x%"PRIx64 " phys_start=3D0x%"PRIx64" flags=3D%d" virtio_iommu_unmap(uint32_t domain_id, uint64_t virt_start, uint64_t virt_= end) "domain=3D%d virt_start=3D0x%"PRIx64" virt_end=3D0x%"PRIx64 +virtio_iommu_translate(const char *name, uint32_t rid, uint64_t iova, int = flag) "mr=3D%s rid=3D%d addr=3D0x%"PRIx64" flag=3D%d" +virtio_iommu_init_iommu_mr(char *iommu_mr) "init %s" +virtio_iommu_get_endpoint(uint32_t ep_id) "Alloc endpoint=3D%d" +virtio_iommu_put_endpoint(uint32_t ep_id) "Free endpoint=3D%d" +virtio_iommu_get_domain(uint32_t domain_id) "Alloc domain=3D%d" +virtio_iommu_put_domain(uint32_t domain_id) "Free domain=3D%d" diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 86dcdc09a1..d9fe83f530 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -23,6 +23,8 @@ #include "hw/qdev-properties.h" #include "hw/virtio/virtio.h" #include "sysemu/kvm.h" +#include "qapi/error.h" +#include "qemu/error-report.h" #include "trace.h" =20 #include "standard-headers/linux/virtio_ids.h" @@ -30,19 +32,236 @@ #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-iommu.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci/pci.h" =20 /* Max size */ #define VIOMMU_DEFAULT_QUEUE_SIZE 256 =20 +typedef struct VirtIOIOMMUDomain { + uint32_t id; + GTree *mappings; + QLIST_HEAD(, VirtIOIOMMUEndpoint) endpoint_list; +} VirtIOIOMMUDomain; + +typedef struct VirtIOIOMMUEndpoint { + uint32_t id; + VirtIOIOMMUDomain *domain; + QLIST_ENTRY(VirtIOIOMMUEndpoint) next; +} VirtIOIOMMUEndpoint; + +typedef struct VirtIOIOMMUInterval { + uint64_t low; + uint64_t high; +} VirtIOIOMMUInterval; + +static inline uint16_t virtio_iommu_get_bdf(IOMMUDevice *dev) +{ + return PCI_BUILD_BDF(pci_bus_num(dev->bus), dev->devfn); +} + +/** + * The bus number is used for lookup when SID based operations occur. + * In that case we lazily populate the IOMMUPciBus array from the bus hash + * table. At the time the IOMMUPciBus is created (iommu_find_add_as), the = bus + * numbers may not be always initialized yet. + */ +static IOMMUPciBus *iommu_find_iommu_pcibus(VirtIOIOMMU *s, uint8_t bus_nu= m) +{ + IOMMUPciBus *iommu_pci_bus =3D s->iommu_pcibus_by_bus_num[bus_num]; + + if (!iommu_pci_bus) { + GHashTableIter iter; + + g_hash_table_iter_init(&iter, s->as_by_busptr); + while (g_hash_table_iter_next(&iter, NULL, (void **)&iommu_pci_bus= )) { + if (pci_bus_num(iommu_pci_bus->bus) =3D=3D bus_num) { + s->iommu_pcibus_by_bus_num[bus_num] =3D iommu_pci_bus; + return iommu_pci_bus; + } + } + return NULL; + } + return iommu_pci_bus; +} + +static IOMMUMemoryRegion *virtio_iommu_mr(VirtIOIOMMU *s, uint32_t sid) +{ + uint8_t bus_n, devfn; + IOMMUPciBus *iommu_pci_bus; + IOMMUDevice *dev; + + bus_n =3D PCI_BUS_NUM(sid); + iommu_pci_bus =3D iommu_find_iommu_pcibus(s, bus_n); + if (iommu_pci_bus) { + devfn =3D sid & PCI_DEVFN_MAX; + dev =3D iommu_pci_bus->pbdev[devfn]; + if (dev) { + return &dev->iommu_mr; + } + } + return NULL; +} + +static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_d= ata) +{ + VirtIOIOMMUInterval *inta =3D (VirtIOIOMMUInterval *)a; + VirtIOIOMMUInterval *intb =3D (VirtIOIOMMUInterval *)b; + + if (inta->high < intb->low) { + return -1; + } else if (intb->high < inta->low) { + return 1; + } else { + return 0; + } +} + +static void virtio_iommu_detach_endpoint_from_domain(VirtIOIOMMUEndpoint *= ep) +{ + if (!ep->domain) { + return; + } + QLIST_REMOVE(ep, next); + ep->domain =3D NULL; +} + +static VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s, + uint32_t ep_id) +{ + VirtIOIOMMUEndpoint *ep; + + ep =3D g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id)); + if (ep) { + return ep; + } + if (!virtio_iommu_mr(s, ep_id)) { + return NULL; + } + ep =3D g_malloc0(sizeof(*ep)); + ep->id =3D ep_id; + trace_virtio_iommu_get_endpoint(ep_id); + g_tree_insert(s->endpoints, GUINT_TO_POINTER(ep_id), ep); + return ep; +} + +static void virtio_iommu_put_endpoint(gpointer data) +{ + VirtIOIOMMUEndpoint *ep =3D (VirtIOIOMMUEndpoint *)data; + + if (ep->domain) { + virtio_iommu_detach_endpoint_from_domain(ep); + } + + trace_virtio_iommu_put_endpoint(ep->id); + g_free(ep); +} + +static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s, + uint32_t domain_id) +{ + VirtIOIOMMUDomain *domain; + + domain =3D g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id)); + if (domain) { + return domain; + } + domain =3D g_malloc0(sizeof(*domain)); + domain->id =3D domain_id; + domain->mappings =3D g_tree_new_full((GCompareDataFunc)interval_cmp, + NULL, (GDestroyNotify)g_free, + (GDestroyNotify)g_free); + g_tree_insert(s->domains, GUINT_TO_POINTER(domain_id), domain); + QLIST_INIT(&domain->endpoint_list); + trace_virtio_iommu_get_domain(domain_id); + return domain; +} + +static void virtio_iommu_put_domain(gpointer data) +{ + VirtIOIOMMUDomain *domain =3D (VirtIOIOMMUDomain *)data; + VirtIOIOMMUEndpoint *iter, *tmp; + + QLIST_FOREACH_SAFE(iter, &domain->endpoint_list, next, tmp) { + virtio_iommu_detach_endpoint_from_domain(iter); + } + g_tree_destroy(domain->mappings); + trace_virtio_iommu_put_domain(domain->id); + g_free(domain); +} + +static AddressSpace *virtio_iommu_find_add_as(PCIBus *bus, void *opaque, + int devfn) +{ + VirtIOIOMMU *s =3D opaque; + IOMMUPciBus *sbus =3D g_hash_table_lookup(s->as_by_busptr, bus); + static uint32_t mr_index; + IOMMUDevice *sdev; + + if (!sbus) { + sbus =3D g_malloc0(sizeof(IOMMUPciBus) + + sizeof(IOMMUDevice *) * PCI_DEVFN_MAX); + sbus->bus =3D bus; + g_hash_table_insert(s->as_by_busptr, bus, sbus); + } + + sdev =3D sbus->pbdev[devfn]; + if (!sdev) { + char *name =3D g_strdup_printf("%s-%d-%d", + TYPE_VIRTIO_IOMMU_MEMORY_REGION, + mr_index++, devfn); + sdev =3D sbus->pbdev[devfn] =3D g_malloc0(sizeof(IOMMUDevice)); + + sdev->viommu =3D s; + sdev->bus =3D bus; + sdev->devfn =3D devfn; + + trace_virtio_iommu_init_iommu_mr(name); + + memory_region_init_iommu(&sdev->iommu_mr, sizeof(sdev->iommu_mr), + TYPE_VIRTIO_IOMMU_MEMORY_REGION, + OBJECT(s), name, + UINT64_MAX); + address_space_init(&sdev->as, + MEMORY_REGION(&sdev->iommu_mr), TYPE_VIRTIO_IOM= MU); + g_free(name); + } + return &sdev->as; +} + static int virtio_iommu_attach(VirtIOIOMMU *s, struct virtio_iommu_req_attach *req) { uint32_t domain_id =3D le32_to_cpu(req->domain); uint32_t ep_id =3D le32_to_cpu(req->endpoint); + VirtIOIOMMUDomain *domain; + VirtIOIOMMUEndpoint *ep; =20 trace_virtio_iommu_attach(domain_id, ep_id); =20 - return VIRTIO_IOMMU_S_UNSUPP; + ep =3D virtio_iommu_get_endpoint(s, ep_id); + if (!ep) { + return VIRTIO_IOMMU_S_NOENT; + } + + if (ep->domain) { + VirtIOIOMMUDomain *previous_domain =3D ep->domain; + /* + * the device is already attached to a domain, + * detach it first + */ + virtio_iommu_detach_endpoint_from_domain(ep); + if (QLIST_EMPTY(&previous_domain->endpoint_list)) { + g_tree_remove(s->domains, GUINT_TO_POINTER(previous_domain->id= )); + } + } + + domain =3D virtio_iommu_get_domain(s, domain_id); + QLIST_INSERT_HEAD(&domain->endpoint_list, ep, next); + + ep->domain =3D domain; + + return VIRTIO_IOMMU_S_OK; } =20 static int virtio_iommu_detach(VirtIOIOMMU *s, @@ -50,10 +269,28 @@ static int virtio_iommu_detach(VirtIOIOMMU *s, { uint32_t domain_id =3D le32_to_cpu(req->domain); uint32_t ep_id =3D le32_to_cpu(req->endpoint); + VirtIOIOMMUDomain *domain; + VirtIOIOMMUEndpoint *ep; =20 trace_virtio_iommu_detach(domain_id, ep_id); =20 - return VIRTIO_IOMMU_S_UNSUPP; + ep =3D g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id)); + if (!ep) { + return VIRTIO_IOMMU_S_NOENT; + } + + domain =3D ep->domain; + + if (!domain || domain->id !=3D domain_id) { + return VIRTIO_IOMMU_S_INVAL; + } + + virtio_iommu_detach_endpoint_from_domain(ep); + + if (QLIST_EMPTY(&domain->endpoint_list)) { + g_tree_remove(s->domains, GUINT_TO_POINTER(domain->id)); + } + return VIRTIO_IOMMU_S_OK; } =20 static int virtio_iommu_map(VirtIOIOMMU *s, @@ -172,6 +409,27 @@ out: } } =20 +static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr = addr, + IOMMUAccessFlags flag, + int iommu_idx) +{ + IOMMUDevice *sdev =3D container_of(mr, IOMMUDevice, iommu_mr); + uint32_t sid; + + IOMMUTLBEntry entry =3D { + .target_as =3D &address_space_memory, + .iova =3D addr, + .translated_addr =3D addr, + .addr_mask =3D ~(hwaddr)0, + .perm =3D IOMMU_NONE, + }; + + sid =3D virtio_iommu_get_bdf(sdev); + + trace_virtio_iommu_translate(mr->parent_obj.name, sid, addr, flag); + return entry; +} + static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_da= ta) { VirtIOIOMMU *dev =3D VIRTIO_IOMMU(vdev); @@ -218,6 +476,13 @@ static const VMStateDescription vmstate_virtio_iommu_d= evice =3D { .unmigratable =3D 1, }; =20 +static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + guint ua =3D GPOINTER_TO_UINT(a); + guint ub =3D GPOINTER_TO_UINT(b); + return (ua > ub) - (ua < ub); +} + static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); @@ -226,6 +491,8 @@ static void virtio_iommu_device_realize(DeviceState *de= v, Error **errp) virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU, sizeof(struct virtio_iommu_config)); =20 + memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_nu= m)); + s->req_vq =3D virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, virtio_iommu_handle_command); s->event_vq =3D virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE, NULL= ); @@ -244,18 +511,43 @@ static void virtio_iommu_device_realize(DeviceState *= dev, Error **errp) virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MMIO); =20 qemu_mutex_init(&s->mutex); + + s->as_by_busptr =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); + + if (s->primary_bus) { + pci_setup_iommu(s->primary_bus, virtio_iommu_find_add_as, s); + } else { + error_setg(errp, "VIRTIO-IOMMU is not attached to any PCI bus!"); + } } =20 static void virtio_iommu_device_unrealize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VirtIOIOMMU *s =3D VIRTIO_IOMMU(dev); + + g_tree_destroy(s->domains); + g_tree_destroy(s->endpoints); =20 virtio_cleanup(vdev); } =20 static void virtio_iommu_device_reset(VirtIODevice *vdev) { + VirtIOIOMMU *s =3D VIRTIO_IOMMU(vdev); + trace_virtio_iommu_device_reset(); + + if (s->domains) { + g_tree_destroy(s->domains); + } + if (s->endpoints) { + g_tree_destroy(s->endpoints); + } + s->domains =3D g_tree_new_full((GCompareDataFunc)int_cmp, + NULL, NULL, virtio_iommu_put_domain); + s->endpoints =3D g_tree_new_full((GCompareDataFunc)int_cmp, + NULL, NULL, virtio_iommu_put_endpoint); } =20 static void virtio_iommu_set_status(VirtIODevice *vdev, uint8_t status) @@ -301,6 +593,14 @@ static void virtio_iommu_class_init(ObjectClass *klass= , void *data) vdc->vmsd =3D &vmstate_virtio_iommu_device; } =20 +static void virtio_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D virtio_iommu_translate; +} + static const TypeInfo virtio_iommu_info =3D { .name =3D TYPE_VIRTIO_IOMMU, .parent =3D TYPE_VIRTIO_DEVICE, @@ -309,9 +609,16 @@ static const TypeInfo virtio_iommu_info =3D { .class_init =3D virtio_iommu_class_init, }; =20 +static const TypeInfo virtio_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_VIRTIO_IOMMU_MEMORY_REGION, + .class_init =3D virtio_iommu_memory_region_class_init, +}; + static void virtio_register_types(void) { type_register_static(&virtio_iommu_info); + type_register_static(&virtio_iommu_memory_region_info); } =20 type_init(virtio_register_types) diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-io= mmu.h index d24ba63305..ae88f730cf 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -28,6 +28,8 @@ #define VIRTIO_IOMMU(obj) \ OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU) =20 +#define TYPE_VIRTIO_IOMMU_MEMORY_REGION "virtio-iommu-memory-region" + typedef struct IOMMUDevice { void *viommu; PCIBus *bus; @@ -48,6 +50,7 @@ typedef struct VirtIOIOMMU { struct virtio_iommu_config config; uint64_t features; GHashTable *as_by_busptr; + IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX]; PCIBus *primary_bus; GTree *domains; QemuMutex mutex; --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687215076308.40527228778694; Fri, 14 Feb 2020 05:33:35 -0800 (PST) Received: from localhost ([::1]:38968 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b65-0000Lk-Nv for importer@patchew.org; Fri, 14 Feb 2020 08:33:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52104) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b1X-0001Fe-Ux for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b1W-0007o3-Hr for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:51 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:39900 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b1W-0007jw-C1 for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:50 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-232-sA4FoMqIMWCg_CT2jL7cJw-1; Fri, 14 Feb 2020 08:28:48 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 81E8818A6EC3; Fri, 14 Feb 2020 13:28:44 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7EB985DA7D; Fri, 14 Feb 2020 13:28:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686930; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1LirlY2hiNQE5OdFGRUpttOcqMzEe2dgN7vuotOCoeE=; b=OUo418uonazWIORzO73BaK383hxlXtyXtgr6+WqSGucYfGHdE1eKewQe31MgbisgllSrL/ qs2U3oQ97eFZOU9d61Bk0CqcWmBphO2XVRjuml3TwII+2a4OROCokaZwesJcmt/IsQnbb5 lhBqHu8xJxfShw89mlSWxVG+53euUBE= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 04/10] virtio-iommu: Implement map/unmap Date: Fri, 14 Feb 2020 14:27:39 +0100 Message-Id: <20200214132745.23392-5-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: sA4FoMqIMWCg_CT2jL7cJw-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patch implements virtio_iommu_map/unmap. Signed-off-by: Eric Auger Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin --- v11 -> v12: - check unmanaged managed flags on map - removed 2 qemu_log_mask in unmap() - fix leak v10 -> v11: - revisit the implementation of unmap according to Peter's suggestion - removed virt_addr and size from viommu_mapping struct - use g_tree_lookup_extended() - return VIRTIO_IOMMU_S_RANGE in case a mapping were to be split on unmap (instead of INVAL) v5 -> v6: - use new v0.6 fields - replace error_report by qemu_log_mask v3 -> v4: - implement unmap semantics as specified in v0.4 --- hw/virtio/trace-events | 1 + hw/virtio/virtio-iommu.c | 63 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 15595f8cd7..22162d6583 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -64,6 +64,7 @@ virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "= domain=3D%d endpoint=3D%d" virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=3D%d endpo= int=3D%d" virtio_iommu_map(uint32_t domain_id, uint64_t virt_start, uint64_t virt_en= d, uint64_t phys_start, uint32_t flags) "domain=3D%d virt_start=3D0x%"PRIx6= 4" virt_end=3D0x%"PRIx64 " phys_start=3D0x%"PRIx64" flags=3D%d" virtio_iommu_unmap(uint32_t domain_id, uint64_t virt_start, uint64_t virt_= end) "domain=3D%d virt_start=3D0x%"PRIx64" virt_end=3D0x%"PRIx64 +virtio_iommu_unmap_done(uint32_t domain_id, uint64_t virt_start, uint64_t = virt_end) "domain=3D%d virt_start=3D0x%"PRIx64" virt_end=3D0x%"PRIx64 virtio_iommu_translate(const char *name, uint32_t rid, uint64_t iova, int = flag) "mr=3D%s rid=3D%d addr=3D0x%"PRIx64" flag=3D%d" virtio_iommu_init_iommu_mr(char *iommu_mr) "init %s" virtio_iommu_get_endpoint(uint32_t ep_id) "Alloc endpoint=3D%d" diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index d9fe83f530..844d34c270 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -18,6 +18,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/log.h" #include "qemu/iov.h" #include "qemu-common.h" #include "hw/qdev-properties.h" @@ -55,6 +56,11 @@ typedef struct VirtIOIOMMUInterval { uint64_t high; } VirtIOIOMMUInterval; =20 +typedef struct VirtIOIOMMUMapping { + uint64_t phys_addr; + uint32_t flags; +} VirtIOIOMMUMapping; + static inline uint16_t virtio_iommu_get_bdf(IOMMUDevice *dev) { return PCI_BUILD_BDF(pci_bus_num(dev->bus), dev->devfn); @@ -301,10 +307,39 @@ static int virtio_iommu_map(VirtIOIOMMU *s, uint64_t virt_start =3D le64_to_cpu(req->virt_start); uint64_t virt_end =3D le64_to_cpu(req->virt_end); uint32_t flags =3D le32_to_cpu(req->flags); + VirtIOIOMMUDomain *domain; + VirtIOIOMMUInterval *interval; + VirtIOIOMMUMapping *mapping; + + if (flags & ~VIRTIO_IOMMU_MAP_F_MASK) { + return VIRTIO_IOMMU_S_INVAL; + } + + domain =3D g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id)); + if (!domain) { + return VIRTIO_IOMMU_S_NOENT; + } + + interval =3D g_malloc0(sizeof(*interval)); + + interval->low =3D virt_start; + interval->high =3D virt_end; + + mapping =3D g_tree_lookup(domain->mappings, (gpointer)interval); + if (mapping) { + g_free(interval); + return VIRTIO_IOMMU_S_INVAL; + } =20 trace_virtio_iommu_map(domain_id, virt_start, virt_end, phys_start, fl= ags); =20 - return VIRTIO_IOMMU_S_UNSUPP; + mapping =3D g_malloc0(sizeof(*mapping)); + mapping->phys_addr =3D phys_start; + mapping->flags =3D flags; + + g_tree_insert(domain->mappings, interval, mapping); + + return VIRTIO_IOMMU_S_OK; } =20 static int virtio_iommu_unmap(VirtIOIOMMU *s, @@ -313,10 +348,34 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, uint32_t domain_id =3D le32_to_cpu(req->domain); uint64_t virt_start =3D le64_to_cpu(req->virt_start); uint64_t virt_end =3D le64_to_cpu(req->virt_end); + VirtIOIOMMUMapping *iter_val; + VirtIOIOMMUInterval interval, *iter_key; + VirtIOIOMMUDomain *domain; + int ret =3D VIRTIO_IOMMU_S_OK; =20 trace_virtio_iommu_unmap(domain_id, virt_start, virt_end); =20 - return VIRTIO_IOMMU_S_UNSUPP; + domain =3D g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id)); + if (!domain) { + return VIRTIO_IOMMU_S_NOENT; + } + interval.low =3D virt_start; + interval.high =3D virt_end; + + while (g_tree_lookup_extended(domain->mappings, &interval, + (void **)&iter_key, (void**)&iter_val)) { + uint64_t current_low =3D iter_key->low; + uint64_t current_high =3D iter_key->high; + + if (interval.low <=3D current_low && interval.high >=3D current_hi= gh) { + g_tree_remove(domain->mappings, iter_key); + trace_virtio_iommu_unmap_done(domain_id, current_low, current_= high); + } else { + ret =3D VIRTIO_IOMMU_S_RANGE; + break; + } + } + return ret; } =20 static int virtio_iommu_iov_to_req(struct iovec *iov, --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687028287674.8001279485886; Fri, 14 Feb 2020 05:30:28 -0800 (PST) Received: from localhost ([::1]:38896 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b34-0003fN-Qu for importer@patchew.org; Fri, 14 Feb 2020 08:30:26 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52165) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b1d-0001ab-IP for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b1c-0008Ak-2B for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:57 -0500 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:52603 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b1b-00088Z-Tr for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:28:56 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-212-PELZ7BcMND-Q5cnwvymkLA-1; Fri, 14 Feb 2020 08:28:54 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BF719100550E; Fri, 14 Feb 2020 13:28:52 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1614D5DA7D; Fri, 14 Feb 2020 13:28:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686935; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7XfbrPqq3Dt9SyCTxhSyVra/GnCrepGKOQlPZdwqAe4=; b=LekoJZPRcsmp3mjUtojNS+sfBILnV1lGSwQzkCnXENTteedY1iNjraOUWjSpjz2Aq6b7t0 u3neeq/Hfjp1K+G/CzJ0PY5vr8nf4x3ZdW7Xu530pOHRToFhgzoACHBHDsCSkmEMI4s14j 053i44QqeUgyR+szUnPOVtoUJpJPYV4= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 05/10] virtio-iommu: Implement translate Date: Fri, 14 Feb 2020 14:27:40 +0100 Message-Id: <20200214132745.23392-6-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: PELZ7BcMND-Q5cnwvymkLA-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patch implements the translate callback Signed-off-by: Eric Auger Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin --- v11 -> v12: - Added Jean's R-b - s/qemu_log_mask/error_report_once v10 -> v11: - take into account the new value struct and use g_tree_lookup_extended - switched to error_report_once v6 -> v7: - implemented bypass-mode v5 -> v6: - replace error_report by qemu_log_mask v4 -> v5: - check the device domain is not NULL - s/printf/error_report - set flags to IOMMU_NONE in case of all translation faults --- hw/virtio/trace-events | 1 + hw/virtio/virtio-iommu.c | 60 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 22162d6583..095aa8b509 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -71,3 +71,4 @@ virtio_iommu_get_endpoint(uint32_t ep_id) "Alloc endpoint= =3D%d" virtio_iommu_put_endpoint(uint32_t ep_id) "Free endpoint=3D%d" virtio_iommu_get_domain(uint32_t domain_id) "Alloc domain=3D%d" virtio_iommu_put_domain(uint32_t domain_id) "Free domain=3D%d" +virtio_iommu_translate_out(uint64_t virt_addr, uint64_t phys_addr, uint32_= t sid) "0x%"PRIx64" -> 0x%"PRIx64 " for sid=3D%d" diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 844d34c270..59e9cd3d9a 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -473,19 +473,77 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemo= ryRegion *mr, hwaddr addr, int iommu_idx) { IOMMUDevice *sdev =3D container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMUInterval interval, *mapping_key; + VirtIOIOMMUMapping *mapping_value; + VirtIOIOMMU *s =3D sdev->viommu; + VirtIOIOMMUEndpoint *ep; + bool bypass_allowed; uint32_t sid; + bool found; + + interval.low =3D addr; + interval.high =3D addr + 1; =20 IOMMUTLBEntry entry =3D { .target_as =3D &address_space_memory, .iova =3D addr, .translated_addr =3D addr, - .addr_mask =3D ~(hwaddr)0, + .addr_mask =3D (1 << ctz32(s->config.page_size_mask)) - 1, .perm =3D IOMMU_NONE, }; =20 + bypass_allowed =3D virtio_vdev_has_feature(&s->parent_obj, + VIRTIO_IOMMU_F_BYPASS); + sid =3D virtio_iommu_get_bdf(sdev); =20 trace_virtio_iommu_translate(mr->parent_obj.name, sid, addr, flag); + qemu_mutex_lock(&s->mutex); + + ep =3D g_tree_lookup(s->endpoints, GUINT_TO_POINTER(sid)); + if (!ep) { + if (!bypass_allowed) { + error_report_once("%s sid=3D%d is not known!!", __func__, sid); + } else { + entry.perm =3D flag; + } + goto unlock; + } + + if (!ep->domain) { + if (!bypass_allowed) { + error_report_once("%s %02x:%02x.%01x not attached to any domai= n", + __func__, PCI_BUS_NUM(sid), + PCI_SLOT(sid), PCI_FUNC(sid)); + } else { + entry.perm =3D flag; + } + goto unlock; + } + + found =3D g_tree_lookup_extended(ep->domain->mappings, (gpointer)(&int= erval), + (void **)&mapping_key, + (void **)&mapping_value); + if (!found) { + error_report_once("%s no mapping for 0x%"PRIx64" for sid=3D%d", + __func__, addr, sid); + goto unlock; + } + + if (((flag & IOMMU_RO) && + !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_READ)) || + ((flag & IOMMU_WO) && + !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_WRITE))) { + error_report_once("%s permission error on 0x%"PRIx64"(%d): allowed= =3D%d", + __func__, addr, flag, mapping_value->flags); + goto unlock; + } + entry.translated_addr =3D addr - mapping_key->low + mapping_value->phy= s_addr; + entry.perm =3D flag; + trace_virtio_iommu_translate_out(addr, entry.translated_addr, sid); + +unlock: + qemu_mutex_unlock(&s->mutex); return entry; } =20 --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687180844707.8498343815065; Fri, 14 Feb 2020 05:33:00 -0800 (PST) Received: from localhost ([::1]:38958 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b5X-0007ew-DX for importer@patchew.org; Fri, 14 Feb 2020 08:32:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52251) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b1t-00027Y-BW for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b1s-0000lK-2q for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:13 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:51875 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b1r-0000j3-TF for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:11 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-94-S4Hk2gloO1SRh8gRVYrrdw-1; Fri, 14 Feb 2020 08:29:09 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7EBB413E2; Fri, 14 Feb 2020 13:29:08 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 846F75DA7D; Fri, 14 Feb 2020 13:28:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686951; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+AHmGJwOmpJRCQlSbnae4XHqGpIzunQCrq4ckbqRz6E=; b=InyMsthH9UNAL0dAUFstZ1rX0pQK/MJRI3LVz0B4FPgLQPed1ACa4O0OzpJ3KnkVKhrw/F q1LQ0cT1/eC3ssJ/hwt5TqDjgSm/jjPJmY+fq4JnxkExf5kmCisjYeveyoF1KZ4ZWbyV6d aR89+T8oMy4Zq2dO/GQeT71E2UhTOtc= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 06/10] virtio-iommu: Implement fault reporting Date: Fri, 14 Feb 2020 14:27:41 +0100 Message-Id: <20200214132745.23392-7-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: S4Hk2gloO1SRh8gRVYrrdw-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" The event queue allows to report asynchronous errors. The translate function now injects faults when relevant. Signed-off-by: Eric Auger Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin --- v13 -> v14: - remove loop - add Peter's R-b v12 -> v13: - return on virtio_error() v11 -> v12: - reporting the addr associated with the fault and set the VIRTIO_IOMMU_FAULT_F_ADDRESS flag. - added cpu_to_le v10 -> v11: - change a virtio_error into an error_report_once (no buffer available for output faults) --- hw/virtio/trace-events | 1 + hw/virtio/virtio-iommu.c | 70 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 095aa8b509..e83500bee9 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -72,3 +72,4 @@ virtio_iommu_put_endpoint(uint32_t ep_id) "Free endpoint= =3D%d" virtio_iommu_get_domain(uint32_t domain_id) "Alloc domain=3D%d" virtio_iommu_put_domain(uint32_t domain_id) "Free domain=3D%d" virtio_iommu_translate_out(uint64_t virt_addr, uint64_t phys_addr, uint32_= t sid) "0x%"PRIx64" -> 0x%"PRIx64 " for sid=3D%d" +virtio_iommu_report_fault(uint8_t reason, uint32_t flags, uint32_t endpoin= t, uint64_t addr) "FAULT reason=3D%d flags=3D%d endpoint=3D%d address =3D0x= %"PRIx64 diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 59e9cd3d9a..8509f64004 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -468,6 +468,48 @@ out: } } =20 +static void virtio_iommu_report_fault(VirtIOIOMMU *viommu, uint8_t reason, + int flags, uint32_t endpoint, + uint64_t address) +{ + VirtIODevice *vdev =3D &viommu->parent_obj; + VirtQueue *vq =3D viommu->event_vq; + struct virtio_iommu_fault fault; + VirtQueueElement *elem; + size_t sz; + + memset(&fault, 0, sizeof(fault)); + fault.reason =3D reason; + fault.flags =3D cpu_to_le32(flags); + fault.endpoint =3D cpu_to_le32(endpoint); + fault.address =3D cpu_to_le64(address); + + elem =3D virtqueue_pop(vq, sizeof(VirtQueueElement)); + + if (!elem) { + error_report_once( + "no buffer available in event queue to report event"); + return; + } + + if (iov_size(elem->in_sg, elem->in_num) < sizeof(fault)) { + virtio_error(vdev, "error buffer of wrong size"); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + return; + } + + sz =3D iov_from_buf(elem->in_sg, elem->in_num, 0, + &fault, sizeof(fault)); + assert(sz =3D=3D sizeof(fault)); + + trace_virtio_iommu_report_fault(reason, flags, endpoint, address); + virtqueue_push(vq, elem, sz); + virtio_notify(vdev, vq); + g_free(elem); + +} + static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr = addr, IOMMUAccessFlags flag, int iommu_idx) @@ -476,9 +518,10 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemor= yRegion *mr, hwaddr addr, VirtIOIOMMUInterval interval, *mapping_key; VirtIOIOMMUMapping *mapping_value; VirtIOIOMMU *s =3D sdev->viommu; + bool read_fault, write_fault; VirtIOIOMMUEndpoint *ep; + uint32_t sid, flags; bool bypass_allowed; - uint32_t sid; bool found; =20 interval.low =3D addr; @@ -504,6 +547,9 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemory= Region *mr, hwaddr addr, if (!ep) { if (!bypass_allowed) { error_report_once("%s sid=3D%d is not known!!", __func__, sid); + virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_UNKNOWN, + VIRTIO_IOMMU_FAULT_F_ADDRESS, + sid, addr); } else { entry.perm =3D flag; } @@ -515,6 +561,9 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemory= Region *mr, hwaddr addr, error_report_once("%s %02x:%02x.%01x not attached to any domai= n", __func__, PCI_BUS_NUM(sid), PCI_SLOT(sid), PCI_FUNC(sid)); + virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_DOMAIN, + VIRTIO_IOMMU_FAULT_F_ADDRESS, + sid, addr); } else { entry.perm =3D flag; } @@ -527,15 +576,26 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemo= ryRegion *mr, hwaddr addr, if (!found) { error_report_once("%s no mapping for 0x%"PRIx64" for sid=3D%d", __func__, addr, sid); + virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING, + VIRTIO_IOMMU_FAULT_F_ADDRESS, + sid, addr); goto unlock; } =20 - if (((flag & IOMMU_RO) && - !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_READ)) || - ((flag & IOMMU_WO) && - !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_WRITE))) { + read_fault =3D (flag & IOMMU_RO) && + !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_READ); + write_fault =3D (flag & IOMMU_WO) && + !(mapping_value->flags & VIRTIO_IOMMU_MAP_F_WRITE); + + flags =3D read_fault ? VIRTIO_IOMMU_FAULT_F_READ : 0; + flags |=3D write_fault ? VIRTIO_IOMMU_FAULT_F_WRITE : 0; + if (flags) { error_report_once("%s permission error on 0x%"PRIx64"(%d): allowed= =3D%d", __func__, addr, flag, mapping_value->flags); + flags |=3D VIRTIO_IOMMU_FAULT_F_ADDRESS; + virtio_iommu_report_fault(s, VIRTIO_IOMMU_FAULT_R_MAPPING, + flags | VIRTIO_IOMMU_FAULT_F_ADDRESS, + sid, addr); goto unlock; } entry.translated_addr =3D addr - mapping_key->low + mapping_value->phy= s_addr; --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687275566965.2801240672063; Fri, 14 Feb 2020 05:34:35 -0800 (PST) Received: from localhost ([::1]:38990 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b74-0002kX-7H for importer@patchew.org; Fri, 14 Feb 2020 08:34:34 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52332) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b21-0002Ts-7Z for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b1z-0001gF-Vy for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:21 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:20724 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b1z-0001cS-RT for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:19 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-138-Rf3VF2uKMaKTomoKTmcCTg-1; Fri, 14 Feb 2020 08:29:18 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BDE3A13E2; Fri, 14 Feb 2020 13:29:16 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 422795DA7D; Fri, 14 Feb 2020 13:29:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686959; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fKb/k/H6t86c+BChvVQp4PRkxyDaZan+CeZGDVdZXdc=; b=bzJiI/GhtFd2uKCyQEKycsMRfvFsFdq6aWaaX3SyCgwvoRDV0zLg1KcYraUUMXVQqgX0Mn bYLThSfj+dOvoZm/OlG4lTCFDOdvszOB5eDrXrLYMgI1ibNC84dx/anwXIAKw/0NkeTLZA vwyv/car9zF0eVRHdr8u7SJcDIQc+dk= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 07/10] virtio-iommu: Support migration Date: Fri, 14 Feb 2020 14:27:42 +0100 Message-Id: <20200214132745.23392-8-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: Rf3VF2uKMaKTomoKTmcCTg-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Add Migration support. We rely on recently added gtree and qlist migration. We only migrate the domain gtree. The endpoint gtree is re-constructed in a post-load operation. Signed-off-by: Eric Auger Acked-by: Peter Xu Reviewed-by: Juan Quintela Reviewed-by: Michael S. Tsirkin --- v15 -> v16: - added Juan's R-b v11 -> v12: - do not migrate the endpoint gtree but reconstruct it from the domain gtree (Peter's suggestion) - add MIG_PRI_IOMMU --- hw/virtio/virtio-iommu.c | 109 +++++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 10 deletions(-) diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 8509f64004..4cee8083bc 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -643,16 +643,6 @@ static uint64_t virtio_iommu_get_features(VirtIODevice= *vdev, uint64_t f, return f; } =20 -/* - * Migration is not yet supported: most of the state consists - * of balanced binary trees which are not yet ready for getting - * migrated - */ -static const VMStateDescription vmstate_virtio_iommu_device =3D { - .name =3D "virtio-iommu-device", - .unmigratable =3D 1, -}; - static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) { guint ua =3D GPOINTER_TO_UINT(a); @@ -736,9 +726,108 @@ static void virtio_iommu_instance_init(Object *obj) { } =20 +#define VMSTATE_INTERVAL \ +{ \ + .name =3D "interval", \ + .version_id =3D 1, \ + .minimum_version_id =3D 1, \ + .fields =3D (VMStateField[]) { \ + VMSTATE_UINT64(low, VirtIOIOMMUInterval), \ + VMSTATE_UINT64(high, VirtIOIOMMUInterval), \ + VMSTATE_END_OF_LIST() \ + } \ +} + +#define VMSTATE_MAPPING \ +{ \ + .name =3D "mapping", \ + .version_id =3D 1, \ + .minimum_version_id =3D 1, \ + .fields =3D (VMStateField[]) { \ + VMSTATE_UINT64(phys_addr, VirtIOIOMMUMapping),\ + VMSTATE_UINT32(flags, VirtIOIOMMUMapping), \ + VMSTATE_END_OF_LIST() \ + }, \ +} + +static const VMStateDescription vmstate_interval_mapping[2] =3D { + VMSTATE_MAPPING, /* value */ + VMSTATE_INTERVAL /* key */ +}; + +static int domain_preload(void *opaque) +{ + VirtIOIOMMUDomain *domain =3D opaque; + + domain->mappings =3D g_tree_new_full((GCompareDataFunc)interval_cmp, + NULL, g_free, g_free); + return 0; +} + +static const VMStateDescription vmstate_endpoint =3D { + .name =3D "endpoint", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(id, VirtIOIOMMUEndpoint), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_domain =3D { + .name =3D "domain", + .version_id =3D 1, + .minimum_version_id =3D 1, + .pre_load =3D domain_preload, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(id, VirtIOIOMMUDomain), + VMSTATE_GTREE_V(mappings, VirtIOIOMMUDomain, 1, + vmstate_interval_mapping, + VirtIOIOMMUInterval, VirtIOIOMMUMapping), + VMSTATE_QLIST_V(endpoint_list, VirtIOIOMMUDomain, 1, + vmstate_endpoint, VirtIOIOMMUEndpoint, next), + VMSTATE_END_OF_LIST() + } +}; + +static gboolean reconstruct_endpoints(gpointer key, gpointer value, + gpointer data) +{ + VirtIOIOMMU *s =3D (VirtIOIOMMU *)data; + VirtIOIOMMUDomain *d =3D (VirtIOIOMMUDomain *)value; + VirtIOIOMMUEndpoint *iter; + + QLIST_FOREACH(iter, &d->endpoint_list, next) { + iter->domain =3D d; + g_tree_insert(s->endpoints, GUINT_TO_POINTER(iter->id), iter); + } + return false; /* continue the domain traversal */ +} + +static int iommu_post_load(void *opaque, int version_id) +{ + VirtIOIOMMU *s =3D opaque; + + g_tree_foreach(s->domains, reconstruct_endpoints, s); + return 0; +} + +static const VMStateDescription vmstate_virtio_iommu_device =3D { + .name =3D "virtio-iommu-device", + .minimum_version_id =3D 1, + .version_id =3D 1, + .post_load =3D iommu_post_load, + .fields =3D (VMStateField[]) { + VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 1, + &vmstate_domain, VirtIOIOMMUDomain), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_virtio_iommu =3D { .name =3D "virtio-iommu", .minimum_version_id =3D 1, + .priority =3D MIG_PRI_IOMMU, .version_id =3D 1, .fields =3D (VMStateField[]) { VMSTATE_VIRTIO_DEVICE, --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687350696604.6475155900729; Fri, 14 Feb 2020 05:35:50 -0800 (PST) Received: from localhost ([::1]:39046 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b8H-0005GU-Bh for importer@patchew.org; Fri, 14 Feb 2020 08:35:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52404) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b2E-0002mT-UO for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b2D-0002PS-DE for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:34 -0500 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:28335 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b2D-0002Ou-9z for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:33 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-175-m7yOsnNjOp-DneQW3rTyXA-1; Fri, 14 Feb 2020 08:29:31 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BA4ED13E6; Fri, 14 Feb 2020 13:29:29 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 254485DA7D; Fri, 14 Feb 2020 13:29:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686972; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mw5Txo7B8RTdVDvgpa5OdD0dWzCb9iRe7tmh1tgKvcE=; b=ZCLpte4/26P8zHWi5Ay7Xslsco1v+1cqXOo7wpxmWEBHDiSYm3dhXjGzOPPxiVJl26GwP6 m6gkpgIR7N4/EWG0T5Ipq0WinPGa0gqdkWFvoCRTkBvKg4aY3WXsOuBXQmVSGI8VMgREPk 0HSMnB3cHFncNyp7WEyGDkdxUrpZ8to= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 08/10] virtio-iommu-pci: Add virtio iommu pci support Date: Fri, 14 Feb 2020 14:27:43 +0100 Message-Id: <20200214132745.23392-9-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: m7yOsnNjOp-DneQW3rTyXA-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.81 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" This patch adds virtio-iommu-pci, which is the pci proxy for the virtio-iommu device. Currently non DT integration is not yet supported by the kernel. So the machine must implement a hotplug handler for the virtio-iommu-pci device that creates the device tree iommu-map bindings as documented in kernel documentation: Documentation/devicetree/bindings/virtio/iommu.txt Signed-off-by: Eric Auger Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin --- v15 -> v16: - made the device not hotpluggable v14 -> v15: - checker whether the machine implements a hotplug handler for the virtio-iommu-pci v13 -> v14: - add device_class_set_props v11 -> v12: - added Jean's R-b - remove the array of intervals. Will be introduced later? v10 -> v11: - add the reserved_regions array property v9 -> v10: - include "hw/qdev-properties.h" header v8 -> v9: - add the msi-bypass property - create virtio-iommu-pci.c --- hw/virtio/Makefile.objs | 1 + hw/virtio/virtio-iommu-pci.c | 104 +++++++++++++++++++++++++++++++ include/hw/pci/pci.h | 1 + include/hw/virtio/virtio-iommu.h | 1 + qdev-monitor.c | 1 + 5 files changed, 108 insertions(+) create mode 100644 hw/virtio/virtio-iommu-pci.c diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index 2fd9da7410..4e4d39a0a4 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -29,6 +29,7 @@ obj-$(CONFIG_VIRTIO_INPUT_HOST) +=3D virtio-input-host-pc= i.o obj-$(CONFIG_VIRTIO_INPUT) +=3D virtio-input-pci.o obj-$(CONFIG_VIRTIO_RNG) +=3D virtio-rng-pci.o obj-$(CONFIG_VIRTIO_BALLOON) +=3D virtio-balloon-pci.o +obj-$(CONFIG_VIRTIO_IOMMU) +=3D virtio-iommu-pci.o obj-$(CONFIG_VIRTIO_9P) +=3D virtio-9p-pci.o obj-$(CONFIG_VIRTIO_SCSI) +=3D virtio-scsi-pci.o obj-$(CONFIG_VIRTIO_BLK) +=3D virtio-blk-pci.o diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c new file mode 100644 index 0000000000..3dfbf55b47 --- /dev/null +++ b/hw/virtio/virtio-iommu-pci.c @@ -0,0 +1,104 @@ +/* + * Virtio IOMMU PCI Bindings + * + * Copyright (c) 2019 Red Hat, Inc. + * Written by Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" + +#include "virtio-pci.h" +#include "hw/virtio/virtio-iommu.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "hw/boards.h" + +typedef struct VirtIOIOMMUPCI VirtIOIOMMUPCI; + +/* + * virtio-iommu-pci: This extends VirtioPCIProxy. + * + */ +#define VIRTIO_IOMMU_PCI(obj) \ + OBJECT_CHECK(VirtIOIOMMUPCI, (obj), TYPE_VIRTIO_IOMMU_PCI) + +struct VirtIOIOMMUPCI { + VirtIOPCIProxy parent_obj; + VirtIOIOMMU vdev; +}; + +static Property virtio_iommu_pci_properties[] =3D { + DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **err= p) +{ + VirtIOIOMMUPCI *dev =3D VIRTIO_IOMMU_PCI(vpci_dev); + DeviceState *vdev =3D DEVICE(&dev->vdev); + + if (!qdev_get_machine_hotplug_handler(DEVICE(vpci_dev))) { + MachineClass *mc =3D MACHINE_GET_CLASS(qdev_get_machine()); + + error_setg(errp, + "%s machine fails to create iommu-map device tree bindi= ngs", + mc->name); + error_append_hint(errp, + "Check you machine implements a hotplug handler " + "for the virtio-iommu-pci device\n"); + error_append_hint(errp, "Check the guest is booted without FW or w= ith " + "-no-acpi\n"); + return; + } + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + object_property_set_link(OBJECT(dev), + OBJECT(pci_get_bus(&vpci_dev->pci_dev)), + "primary-bus", errp); + object_property_set_bool(OBJECT(vdev), true, "realized", errp); +} + +static void virtio_iommu_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + VirtioPCIClass *k =3D VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k =3D PCI_DEVICE_CLASS(klass); + k->realize =3D virtio_iommu_pci_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + device_class_set_props(dc, virtio_iommu_pci_properties); + pcidev_k->vendor_id =3D PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id =3D PCI_DEVICE_ID_VIRTIO_IOMMU; + pcidev_k->revision =3D VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id =3D PCI_CLASS_OTHERS; + dc->hotpluggable =3D false; +} + +static void virtio_iommu_pci_instance_init(Object *obj) +{ + VirtIOIOMMUPCI *dev =3D VIRTIO_IOMMU_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_IOMMU); +} + +static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info =3D { + .base_name =3D TYPE_VIRTIO_IOMMU_PCI, + .generic_name =3D "virtio-iommu-pci", + .transitional_name =3D "virtio-iommu-pci-transitional", + .non_transitional_name =3D "virtio-iommu-pci-non-transitional", + .instance_size =3D sizeof(VirtIOIOMMUPCI), + .instance_init =3D virtio_iommu_pci_instance_init, + .class_init =3D virtio_iommu_pci_class_init, +}; + +static void virtio_iommu_pci_register(void) +{ + virtio_pci_types_register(&virtio_iommu_pci_info); +} + +type_init(virtio_iommu_pci_register) + + diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 2acd8321af..cfedf5a995 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -86,6 +86,7 @@ extern bool pci_available; #define PCI_DEVICE_ID_VIRTIO_9P 0x1009 #define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012 #define PCI_DEVICE_ID_VIRTIO_PMEM 0x1013 +#define PCI_DEVICE_ID_VIRTIO_IOMMU 0x1014 =20 #define PCI_VENDOR_ID_REDHAT 0x1b36 #define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001 diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-io= mmu.h index ae88f730cf..6f67f1020a 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -25,6 +25,7 @@ #include "hw/pci/pci.h" =20 #define TYPE_VIRTIO_IOMMU "virtio-iommu-device" +#define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-device-base" #define VIRTIO_IOMMU(obj) \ OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU) =20 diff --git a/qdev-monitor.c b/qdev-monitor.c index 8ce71a206b..dbbe92dfa1 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -67,6 +67,7 @@ static const QDevAlias qdev_alias_table[] =3D { { "virtio-input-host-ccw", "virtio-input-host", QEMU_ARCH_S390X }, { "virtio-input-host-pci", "virtio-input-host", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, + { "virtio-iommu-pci", "virtio-iommu", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X= }, { "virtio-keyboard-ccw", "virtio-keyboard", QEMU_ARCH_S390X }, { "virtio-keyboard-pci", "virtio-keyboard", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X }, --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687419929396.89785240246147; Fri, 14 Feb 2020 05:36:59 -0800 (PST) Received: from localhost ([::1]:39064 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b9O-0006tj-Mo for importer@patchew.org; Fri, 14 Feb 2020 08:36:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52437) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b2M-0002rF-5G for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b2K-0002c6-MC for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:41 -0500 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:29867 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b2K-0002al-EA for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:40 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-334-GIISC-KNOmSdItGpTPrz2w-1; Fri, 14 Feb 2020 08:29:38 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CC522107B0E1; Fri, 14 Feb 2020 13:29:36 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7AEA75DA7D; Fri, 14 Feb 2020 13:29:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686979; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UsqorQ5AgfbunbUBcdlUU/gqRKtwpqkatB0STexBchg=; b=Wgzgw3seU2cSgZ4ntAS7o7zSLxz28q9l+YC2ekTDIcU5Zy2kBg6CsOYhfo13YZUHEc1xLv sY4W4jXHUlTmKoI6DP/SQ7sysxeb5945uxsPHIxvKXFNyF+espX34rs3VxjsiRzdCmL/+o GXyW8XOwdgFdG2QUdmGvxiprH4YQoLU= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 09/10] hw/arm/virt: Add the virtio-iommu device tree mappings Date: Fri, 14 Feb 2020 14:27:44 +0100 Message-Id: <20200214132745.23392-10-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: GIISC-KNOmSdItGpTPrz2w-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Adds the "virtio,pci-iommu" node in the host bridge node and the RID mapping, excluding the IOMMU RID. This is done in the virtio-iommu-pci hotplug handler which gets called only if no firmware is loaded or if -no-acpi is passed on the command line. As non DT integration is not yet supported by the kernel we must make sure we are in DT mode. This limitation will be removed as soon as the topology description feature gets supported. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell --- v15 -> v16: - rename create_virtio_iommu into create_virtio_iommu_dt_bindings v14 -> v15: - only support the hotplug handler for virtio-iommu-pci if dt can be guaranteed v11 -> v12: - Added Jean's R-b v10 -> v11: - remove msi_bypass v8 -> v9: - disable msi-bypass property - addition of the subnode is handled is the hotplug handler and IOMMU RID is notimposed anymore v6 -> v7: - align to the smmu instantiation code v4 -> v5: - VirtMachineClass no_iommu added in this patch - Use object_resolve_path_type --- hw/arm/virt.c | 57 +++++++++++++++++++++++++++++++++++++------ include/hw/arm/virt.h | 2 ++ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f788fe27d6..cfe317922f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -32,6 +32,7 @@ #include "qemu-common.h" #include "qemu/units.h" #include "qemu/option.h" +#include "monitor/qdev.h" #include "qapi/error.h" #include "hw/sysbus.h" #include "hw/boards.h" @@ -54,6 +55,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "hw/pci-host/gpex.h" +#include "hw/virtio/virtio-pci.h" #include "hw/arm/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/qdev-properties.h" @@ -71,6 +73,7 @@ #include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" #include "hw/acpi/generic_event_device.h" +#include "hw/virtio/virtio-iommu.h" =20 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -1180,6 +1183,30 @@ static void create_smmu(const VirtMachineState *vms, g_free(node); } =20 +static void create_virtio_iommu_dt_bindings(VirtMachineState *vms, Error *= *errp) +{ + const char compat[] =3D "virtio,pci-iommu"; + uint16_t bdf =3D vms->virtio_iommu_bdf; + char *node; + + vms->iommu_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); + + node =3D g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, b= df); + qemu_fdt_add_subnode(vms->fdt, node); + qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", + 1, bdf << 8, 1, 0, 1, 0, + 1, 0, 1, 0); + + qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1); + qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle); + g_free(node); + + qemu_fdt_setprop_cells(vms->fdt, vms->pciehb_nodename, "iommu-map", + 0x0, vms->iommu_phandle, 0x0, bdf, + bdf + 1, vms->iommu_phandle, bdf + 1, 0xffff - = bdf); +} + static void create_pcie(VirtMachineState *vms) { hwaddr base_mmio =3D vms->memmap[VIRT_PCIE_MMIO].base; @@ -1258,7 +1285,7 @@ static void create_pcie(VirtMachineState *vms) } } =20 - nodename =3D g_strdup_printf("/pcie@%" PRIx64, base); + nodename =3D vms->pciehb_nodename =3D g_strdup_printf("/pcie@%" PRIx64= , base); qemu_fdt_add_subnode(vms->fdt, nodename); qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "pci-host-ecam-generic"); @@ -1301,13 +1328,16 @@ static void create_pcie(VirtMachineState *vms) if (vms->iommu) { vms->iommu_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); =20 - create_smmu(vms, pci->bus); - - qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", - 0x0, vms->iommu_phandle, 0x0, 0x10000); + switch (vms->iommu) { + case VIRT_IOMMU_SMMUV3: + create_smmu(vms, pci->bus); + qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", + 0x0, vms->iommu_phandle, 0x0, 0x10000); + break; + default: + g_assert_not_reached(); + } } - - g_free(nodename); } =20 static void create_platform_bus(VirtMachineState *vms) @@ -1976,6 +2006,13 @@ static void virt_machine_device_plug_cb(HotplugHandl= er *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_plug(hotplug_dev, dev, errp); } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + PCIDevice *pdev =3D PCI_DEVICE(dev); + + vms->iommu =3D VIRT_IOMMU_VIRTIO; + vms->virtio_iommu_bdf =3D pci_get_bdf(pdev); + create_virtio_iommu_dt_bindings(vms, errp); + } } =20 static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_= dev, @@ -1992,7 +2029,13 @@ static HotplugHandler *virt_machine_get_hotplug_hand= ler(MachineState *machine, (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { return HOTPLUG_HANDLER(machine); } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + VirtMachineState *vms =3D VIRT_MACHINE(machine); =20 + if (!vms->bootinfo.firmware_loaded || !acpi_enabled) { + return HOTPLUG_HANDLER(machine); + } + } return NULL; } =20 diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 71508bf40c..02f500cb8e 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -125,8 +125,10 @@ typedef struct { bool virt; int32_t gic_version; VirtIOMMUType iommu; + uint16_t virtio_iommu_bdf; struct arm_boot_info bootinfo; MemMapEntry *memmap; + char *pciehb_nodename; const int *irqmap; int smp_cpus; void *fdt; --=20 2.20.1 From nobody Thu Apr 25 18:55:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1581687362779968.0323232400029; Fri, 14 Feb 2020 05:36:02 -0800 (PST) Received: from localhost ([::1]:39048 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b8T-0005ag-8W for importer@patchew.org; Fri, 14 Feb 2020 08:36:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52522) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j2b2X-0003Ac-Lg for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j2b2W-0003Lh-NS for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:53 -0500 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:34018 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j2b2W-0003JT-JO for qemu-devel@nongnu.org; Fri, 14 Feb 2020 08:29:52 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-387-btnV4LqKNDm0DqxunrjcTw-1; Fri, 14 Feb 2020 08:29:50 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 35BAD801E66; Fri, 14 Feb 2020 13:29:49 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8DF4A5DA7D; Fri, 14 Feb 2020 13:29:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581686992; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HjKFH/nidefwo3HE1V+8oDIe2P6XzNRGslG25dH2YO0=; b=hUzU19ru9M7XMm/p5OBQnUVT5/N3LB8GDl7yYiQ4Xh6DWIrYBn5UVeLZQztPLsOmotUJ2x tRIS6MjEKOfGdkOzIBnZeBq2eogzPWZkZ0Zly2nIeExrnOVaSCxzk79Nrzfs1TtU8eb/KA 4WkMp66XIz31uFSipji9i0DjcntR4AU= From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, jean-philippe@linaro.org, dgilbert@redhat.com, quintela@redhat.com, mst@redhat.com, peterx@redhat.com Subject: [PATCH v16 10/10] MAINTAINERS: add virtio-iommu related files Date: Fri, 14 Feb 2020 14:27:45 +0100 Message-Id: <20200214132745.23392-11-eric.auger@redhat.com> In-Reply-To: <20200214132745.23392-1-eric.auger@redhat.com> References: <20200214132745.23392-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: btnV4LqKNDm0DqxunrjcTw-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.81 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kevin.tian@intel.com, bharatb.linux@gmail.com, tnowicki@marvell.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Add a new "virtio-iommu" section with the new files related to this device. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c7717df720..b7a7a18737 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1623,6 +1623,12 @@ F: hw/input/virtio-input*.c F: include/hw/virtio/virtio-input.h F: contrib/vhost-user-input/* =20 +virtio-iommu +M: Eric Auger +S: Maintained +F: hw/virtio/virtio-iommu*.c +F: include/hw/virtio/virtio-iommu.h + virtio-serial M: Laurent Vivier R: Amit Shah --=20 2.20.1