From patchwork Fri Nov 3 12:01:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Liu, Yi L" X-Patchwork-Id: 10039943 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 539796032D for ; Fri, 3 Nov 2017 12:20:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 36C3F29578 for ; Fri, 3 Nov 2017 12:20:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B6F2295BF; Fri, 3 Nov 2017 12:20:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7CCA629578 for ; Fri, 3 Nov 2017 12:20:41 +0000 (UTC) Received: from localhost ([::1]:36449 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eAaxk-0008Pw-O6 for patchwork-qemu-devel@patchwork.kernel.org; Fri, 03 Nov 2017 08:20:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41293) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eAavY-0007lv-Co for qemu-devel@nongnu.org; Fri, 03 Nov 2017 08:18:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eAavW-0004PE-Fd for qemu-devel@nongnu.org; Fri, 03 Nov 2017 08:18:24 -0400 Received: from mga11.intel.com ([192.55.52.93]:37808) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eAavW-0004Mu-5E for qemu-devel@nongnu.org; Fri, 03 Nov 2017 08:18:22 -0400 Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Nov 2017 05:18:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.44,338,1505804400"; d="scan'208"; a="1033103159" Received: from sky-dev.bj.intel.com ([10.238.144.127]) by orsmga003.jf.intel.com with ESMTP; 03 Nov 2017 05:18:18 -0700 From: "Liu, Yi L" To: qemu-devel@nongnu.org, mst@redhat.com, david@gibson.dropbear.id.au, pbonzini@redhat.com, alex.williamson@redhat.com Date: Fri, 3 Nov 2017 20:01:52 +0800 Message-Id: <1509710516-21084-3-git-send-email-yi.l.liu@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1509710516-21084-1-git-send-email-yi.l.liu@linux.intel.com> References: <1509710516-21084-1-git-send-email-yi.l.liu@linux.intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 192.55.52.93 Subject: [Qemu-devel] [RESEND PATCH 2/6] memory: introduce AddressSpaceOps and IOMMUObject X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: tianyu.lan@intel.com, "Liu, Yi L" , kevin.tian@intel.com, yi.l.liu@intel.com, jasowang@redhat.com, peterx@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Peter Xu AddressSpaceOps is similar to MemoryRegionOps, it's just for address spaces to store arch-specific hooks. The first hook I would like to introduce is iommu_get(). Return an IOMMUObject behind the AddressSpace. For systems that have IOMMUs, we will create a special address space per device which is different from system default address space for it (please refer to pci_device_iommu_address_space()). Normally when that happens, there will be one specific IOMMU (or say, translation unit) stands right behind that new address space. This iommu_get() fetches that guy behind the address space. Here, the guy is defined as IOMMUObject, which includes a notifier_list so far, may extend in future. Along with IOMMUObject, a new iommu notifier mechanism is introduced. It would be used for virt-svm. Also IOMMUObject can further have a IOMMUObjectOps which is similar to MemoryRegionOps. The difference is IOMMUObjectOps is not relied on MemoryRegion. Signed-off-by: Peter Xu Signed-off-by: Liu, Yi L --- hw/core/Makefile.objs | 1 + hw/core/iommu.c | 58 +++++++++++++++++++++++++++++++++++++++ include/exec/memory.h | 22 +++++++++++++++ include/hw/core/iommu.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ memory.c | 10 +++++-- 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 hw/core/iommu.c create mode 100644 include/hw/core/iommu.h diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index f8d7a4a..d688412 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -5,6 +5,7 @@ common-obj-y += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o +common-obj-y += iommu.o common-obj-y += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o diff --git a/hw/core/iommu.c b/hw/core/iommu.c new file mode 100644 index 0000000..7c4fcfe --- /dev/null +++ b/hw/core/iommu.c @@ -0,0 +1,58 @@ +/* + * QEMU emulation of IOMMU logic + * + * Copyright (C) 2017 Red Hat Inc. + * + * Authors: Peter Xu , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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 for 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 "hw/core/iommu.h" + +void iommu_notifier_register(IOMMUObject *iommu, + IOMMUNotifier *n, + IOMMUNotifyFn fn, + IOMMUEvent event) +{ + n->event = event; + n->iommu_notify = fn; + QLIST_INSERT_HEAD(&iommu->iommu_notifiers, n, node); + return; +} + +void iommu_notifier_unregister(IOMMUObject *iommu, + IOMMUNotifier *notifier) +{ + IOMMUNotifier *cur, *next; + + QLIST_FOREACH_SAFE(cur, &iommu->iommu_notifiers, node, next) { + if (cur == notifier) { + QLIST_REMOVE(cur, node); + break; + } + } +} + +void iommu_notify(IOMMUObject *iommu, IOMMUEventData *event_data) +{ + IOMMUNotifier *cur; + + QLIST_FOREACH(cur, &iommu->iommu_notifiers, node) { + if ((cur->event == event_data->event) && cur->iommu_notify) { + cur->iommu_notify(cur, event_data); + } + } +} diff --git a/include/exec/memory.h b/include/exec/memory.h index 03595e3..8350973 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -26,6 +26,7 @@ #include "qom/object.h" #include "qemu/rcu.h" #include "hw/qdev-core.h" +#include "hw/core/iommu.h" #define RAM_ADDR_INVALID (~(ram_addr_t)0) @@ -301,6 +302,19 @@ struct MemoryListener { }; /** + * AddressSpaceOps: callbacks structure for address space specific operations + * + * @iommu_get: returns an IOMMU object that backs the address space. + * Normally this should be NULL for generic address + * spaces, and it's only used when there is one + * translation unit behind this address space. + */ +struct AddressSpaceOps { + IOMMUObject *(*iommu_get)(AddressSpace *as); +}; +typedef struct AddressSpaceOps AddressSpaceOps; + +/** * AddressSpace: describes a mapping of addresses to #MemoryRegion objects */ struct AddressSpace { @@ -316,6 +330,7 @@ struct AddressSpace { struct MemoryRegionIoeventfd *ioeventfds; QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners; QTAILQ_ENTRY(AddressSpace) address_spaces_link; + AddressSpaceOps as_ops; }; FlatView *address_space_to_flatview(AddressSpace *as); @@ -1988,6 +2003,13 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr, address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len); } +/** + * address_space_iommu_get: Get the backend IOMMU for the address space + * + * @as: the address space to fetch IOMMU from + */ +IOMMUObject *address_space_iommu_get(AddressSpace *as); + #endif #endif diff --git a/include/hw/core/iommu.h b/include/hw/core/iommu.h new file mode 100644 index 0000000..34387c0 --- /dev/null +++ b/include/hw/core/iommu.h @@ -0,0 +1,73 @@ +/* + * QEMU emulation of IOMMU logic + * + * Copyright (C) 2017 Red Hat Inc. + * + * Authors: Peter Xu , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that 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 for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_CORE_IOMMU_H +#define HW_CORE_IOMMU_H + +#include "qemu/queue.h" + +enum IOMMUEvent { + IOMMU_EVENT_BIND_PASIDT, +}; +typedef enum IOMMUEvent IOMMUEvent; + +struct IOMMUEventData { + IOMMUEvent event; + uint64_t length; + void *data; +}; +typedef struct IOMMUEventData IOMMUEventData; + +typedef struct IOMMUNotifier IOMMUNotifier; + +typedef void (*IOMMUNotifyFn)(IOMMUNotifier *notifier, + IOMMUEventData *event_data); + +struct IOMMUNotifier { + IOMMUNotifyFn iommu_notify; + /* + * What events we are listening to. Let's allow multiple event + * registrations from beginning. + */ + IOMMUEvent event; + QLIST_ENTRY(IOMMUNotifier) node; +}; + +typedef struct IOMMUObject IOMMUObject; + +/* + * This stands for an IOMMU unit. Any translation device should have + * this struct inside its own structure to make sure it can leverage + * common IOMMU functionalities. + */ +struct IOMMUObject { + QLIST_HEAD(, IOMMUNotifier) iommu_notifiers; +}; + +void iommu_notifier_register(IOMMUObject *iommu, + IOMMUNotifier *n, + IOMMUNotifyFn fn, + IOMMUEvent event); +void iommu_notifier_unregister(IOMMUObject *iommu, + IOMMUNotifier *notifier); +void iommu_notify(IOMMUObject *iommu, IOMMUEventData *event_data); + +#endif diff --git a/memory.c b/memory.c index 77fb3ef..307f665 100644 --- a/memory.c +++ b/memory.c @@ -235,8 +235,6 @@ struct FlatView { MemoryRegion *root; }; -typedef struct AddressSpaceOps AddressSpaceOps; - #define FOR_EACH_FLAT_RANGE(var, view) \ for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var) @@ -2793,6 +2791,14 @@ static void do_address_space_destroy(AddressSpace *as) memory_region_unref(as->root); } +IOMMUObject *address_space_iommu_get(AddressSpace *as) +{ + if (!as->as_ops.iommu_get) { + return NULL; + } + return as->as_ops.iommu_get(as); +} + void address_space_destroy(AddressSpace *as) { MemoryRegion *root = as->root;