From: Baptiste Reynal <b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
qemu-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org
Cc: tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org,
will.deacon-5wv7dgnIgG8@public.gmane.org
Subject: [RFC 4/6] hw/vfio: vsmmu device
Date: Fri, 12 Jun 2015 16:20:08 +0200 [thread overview]
Message-ID: <1434118810-28219-5-git-send-email-b.reynal@virtualopensystems.com> (raw)
In-Reply-To: <1434118810-28219-1-git-send-email-b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
This patches introduces support for ARM virtual SMMU, enabling two stages
address translation.
The vSMMU device can be instantiated from the command line using following
option:
-device vsmmu,x-group=1
Signed-off-by: Baptiste Reynal <b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
---
hw/vfio/Makefile.objs | 1 +
hw/vfio/common.c | 8 ++-
hw/vfio/platform.c | 1 +
hw/vfio/smmu.c | 157 ++++++++++++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-smmu.h | 50 ++++++++++++++
5 files changed, 215 insertions(+), 2 deletions(-)
create mode 100644 hw/vfio/smmu.c
create mode 100644 include/hw/vfio/vfio-smmu.h
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index d540c9d..4b91901 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -3,4 +3,5 @@ obj-$(CONFIG_SOFTMMU) += common.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_SOFTMMU) += platform.o
obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
+obj-$(CONFIG_SOFTMMU) += smmu.o
endif
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b1045da..a3ee72f 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -676,8 +676,12 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)
goto free_container_exit;
}
- ret = ioctl(fd, VFIO_SET_IOMMU,
- v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
+ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_NESTING_IOMMU)) {
+ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_NESTING_IOMMU);
+ } else {
+ ret = ioctl(fd, VFIO_SET_IOMMU,
+ v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
+ }
if (ret) {
error_report("vfio: failed to set iommu for container: %m");
ret = -errno;
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 9382bb7..6192458 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -475,6 +475,7 @@ static int vfio_base_device_init(VFIODevice *vbasedev)
error_report("vfio: failed to get group %d", groupid);
return -ENOENT;
}
+ vbasedev->group = group;
g_snprintf(path, sizeof(path), "%s", vbasedev->name);
diff --git a/hw/vfio/smmu.c b/hw/vfio/smmu.c
new file mode 100644
index 0000000..467abbe
--- /dev/null
+++ b/hw/vfio/smmu.c
@@ -0,0 +1,157 @@
+/*
+ * support for vsmmu interface to use it with vfio devices
+ *
+ * Copyright (C) 2015 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <sys/ioctl.h>
+
+#include "hw/vfio/vfio-smmu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/platform-bus.h"
+#include "hw/vfio/vfio.h"
+#include "hw/vfio/vfio-common.h"
+
+static void vsmmu_notify(Notifier *notifier, void *data)
+{
+ SmmuNotifierParams *p = DO_UPCAST(SmmuNotifierParams,
+ notifier, notifier);
+
+ DeviceState *dev;
+ PlatformBusDevice *pbus;
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(p->vsmmu);
+
+ dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE);
+ pbus = PLATFORM_BUS_DEVICE(dev);
+ assert(pbus->done_gathering);
+
+ hwaddr base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+ base += pbus->base_address;
+
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_ARM_SMMU_V2_CFG,
+ .attr = KVM_DEV_ARM_SMMU_V2_CFG_INIT,
+ .addr = (uint64_t)(unsigned long) &base,
+ };
+
+ if (ioctl(p->vsmmu->kvm_device, KVM_SET_DEVICE_ATTR, &attr)) {
+ error_report("Error during vSMMU initialization: %m.\n");
+ } else {
+ p->vsmmu->base = base;
+ }
+}
+
+static void smmu_realize(DeviceState *dev, Error **errp)
+{
+ VFIOSmmuDevice *vsmmu = VFIO_SMMU_DEVICE(dev);
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+ VFIOGroup *group;
+ int ret;
+ const char *name = "smmu memory";
+
+ group = vfio_get_group(vsmmu->group, &address_space_memory);
+ if (!group) {
+ error_report("vfio: failed to get group %d", vsmmu->group);
+ goto fail;
+ }
+
+ /* Create ARM_SMMU_V2 */
+ struct kvm_create_device cd = {
+ .type = KVM_DEV_TYPE_ARM_SMMU_V2,
+ };
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
+ if (ret < 0) {
+ error_report("vfio: error creating vSMMU: %m");
+ goto fail;
+ };
+ vsmmu->kvm_device = cd.fd;
+
+ /* Add group */
+ struct arm_smmu_v2_vfio_group_sid group_sid = {
+ .fd = group->fd,
+ .sid = group->groupid,
+ };
+
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_ARM_SMMU_V2_VFIO,
+ .attr = KVM_DEV_ARM_SMMU_V2_VFIO_GROUP_ADD,
+ .addr = (uint64_t)(unsigned long) &group_sid,
+ };
+
+ if (ioctl(cd.fd, KVM_SET_DEVICE_ATTR, &attr)) {
+ error_report("Failed to add group %d to vSMMU: %m",
+ group->groupid);
+ goto fail;
+ }
+
+ /* Initialize the virtual device */
+ /* Get vSMMU size for allocation */
+ int size;
+
+ attr.group = KVM_DEV_ARM_SMMU_V2_CFG;
+ attr.attr = KVM_DEV_ARM_SMMU_V2_CFG_SIZE;
+ attr.addr = (uint64_t)(unsigned long) &size;
+
+ ret = ioctl(cd.fd, KVM_GET_DEVICE_ATTR, &attr);
+
+ if (ret) {
+ error_report("Failed to get vSMMU size: %m");
+ goto fail;
+ }
+
+ vsmmu->size = size;
+
+ memory_region_init_reservation(&vsmmu->mem, OBJECT(vsmmu), name, size);
+ sysbus_init_mmio(sbdev, &vsmmu->mem);
+
+ /* Register a machine init done notifier to initialize the
+ * vSMMU at the right address */
+ SmmuNotifierParams *p = g_new(SmmuNotifierParams, 1);
+ p->vsmmu = vsmmu;
+ p->notifier.notify = vsmmu_notify;
+ qemu_add_platform_bus_link_done_notifier(&p->notifier);
+fail:
+ return;
+}
+
+static const VMStateDescription vfio_platform_vmstate = {
+ .name = TYPE_VFIO_SMMU,
+ .unmigratable = 1,
+};
+
+static Property vfio_smmu_dev_properties[] = {
+ DEFINE_PROP_UINT32("x-group", VFIOSmmuDevice,
+ group, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vfio_smmu_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = smmu_realize;
+ dc->desc = "VFIO SMMU";
+ dc->props = vfio_smmu_dev_properties;
+}
+
+static const TypeInfo vfio_smmu_dev_info = {
+ .name = TYPE_VFIO_SMMU,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(VFIOSmmuDevice),
+ .class_init = vfio_smmu_class_init,
+ .class_size = sizeof(VFIOSmmuDeviceClass),
+};
+
+static void register_smmu_dev_type(void)
+{
+ type_register_static(&vfio_smmu_dev_info);
+}
+
+type_init(register_smmu_dev_type)
diff --git a/include/hw/vfio/vfio-smmu.h b/include/hw/vfio/vfio-smmu.h
new file mode 100644
index 0000000..c14ff8e
--- /dev/null
+++ b/include/hw/vfio/vfio-smmu.h
@@ -0,0 +1,50 @@
+/*
+ * support for vsmmu interface to use it with vfio devices
+ *
+ * Copyright (C) 2015 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VFIO_SMMU_H
+#define HW_VFIO_SMMU_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_VFIO_SMMU "vfio-smmu"
+
+typedef struct VFIOSmmuDevice {
+ SysBusDevice sbdev;
+ int kvm_device;
+ int size;
+ hwaddr base;
+
+ MemoryRegion mem;
+
+ uint32_t group;
+} VFIOSmmuDevice;
+
+typedef struct SmmuNotifierParams {
+ Notifier notifier;
+ VFIOSmmuDevice *vsmmu;
+} SmmuNotifierParams;
+
+typedef struct VFIOSmmuDeviceClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+} VFIOSmmuDeviceClass;
+
+#define VFIO_SMMU_DEVICE(obj) \
+ OBJECT_CHECK(VFIOSmmuDevice, (obj), TYPE_VFIO_SMMU)
+#define VFIO_SMMU_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VFIOSmmuDeviceClass, (klass), \
+ TYPE_VFIO_SMMU)
+#define VFIO_SMMU_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VFIOSmmuDeviceClass, (obj), \
+ TYPE_VFIO_SMMU)
+
+#endif
--
2.4.3
next prev parent reply other threads:[~2015-06-12 14:20 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-12 14:20 [RFC 0/6] vSMMU initialization Baptiste Reynal
[not found] ` <1434118810-28219-1-git-send-email-b.reynal-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org>
2015-06-12 14:20 ` [RFC 1/6] headers sync Baptiste Reynal
2015-06-12 14:20 ` [RFC 2/6] hw/core/platform-bus: initialization notifier Baptiste Reynal
2015-06-12 14:20 ` [RFC 3/6] hw/core/platform-bus: add base_address field Baptiste Reynal
2015-06-12 14:20 ` Baptiste Reynal [this message]
2015-06-12 14:20 ` [RFC 5/6] hw/arm/sysbus-fdt: enable vsmmu dynamic instantiation Baptiste Reynal
2015-06-12 14:20 ` [RFC 6/6] hw/arm/sysbus-fdt: add smmu masters in device tree Baptiste Reynal
2015-06-12 14:23 ` [RFC 0/6] vSMMU initialization Will Deacon
[not found] ` <20150612142328.GF12174-5wv7dgnIgG8@public.gmane.org>
2015-07-14 2:21 ` Varun Sethi
[not found] ` <BN1PR0301MB06274ACB3A193799F40BE9F4EA9B0-RQSpjbwlmjSD1ymB6+i1+JwN6zqB+hSMnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org>
2015-07-14 11:04 ` Will Deacon
[not found] ` <20150714110416.GD16213-5wv7dgnIgG8@public.gmane.org>
2015-07-15 13:38 ` Baptiste Reynal
[not found] ` <CAN9JPjF1E0Dg_KAQcc4C+jKDuOHEATVhN+1NPa66jLrP8RieKA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-07-15 13:42 ` Will Deacon
2015-07-15 16:41 ` Varun Sethi
2015-07-15 17:28 ` Varun Sethi
[not found] ` <BN1PR0301MB0627944BCFB295564CA1F7AAEA9A0-RQSpjbwlmjSD1ymB6+i1+JwN6zqB+hSMnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org>
2015-07-15 17:37 ` Will Deacon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1434118810-28219-5-git-send-email-b.reynal@virtualopensystems.com \
--to=b.reynal-lrhrjnjw1ufhk3s98ze1ajgjjy/sre9j@public.gmane.org \
--cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=qemu-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org \
--cc=tech-lrHrjnjw1UfHK3s98zE1ajGjJy/sRE9J@public.gmane.org \
--cc=will.deacon-5wv7dgnIgG8@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox