From patchwork Fri Jan 9 01:02:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 426889 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7E5C5140129 for ; Fri, 9 Jan 2015 12:03:32 +1100 (AEDT) Received: from localhost ([::1]:48751 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y9Nz8-0001Ww-Dz for incoming@patchwork.ozlabs.org; Thu, 08 Jan 2015 20:03:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40611) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y9Nyl-00012q-Pp for qemu-devel@nongnu.org; Thu, 08 Jan 2015 20:03:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y9Nyi-0005Hp-Gh for qemu-devel@nongnu.org; Thu, 08 Jan 2015 20:03:07 -0500 Received: from e23smtp09.au.ibm.com ([202.81.31.142]:47725) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y9Nyh-0005HO-Lc for qemu-devel@nongnu.org; Thu, 08 Jan 2015 20:03:04 -0500 Received: from /spool/local by e23smtp09.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 9 Jan 2015 11:02:59 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp09.au.ibm.com (202.81.31.206) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 9 Jan 2015 11:02:57 +1000 Received: from d23relay06.au.ibm.com (d23relay06.au.ibm.com [9.185.63.219]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id 83F2C3578048; Fri, 9 Jan 2015 12:02:56 +1100 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay06.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t0912rGK53346352; Fri, 9 Jan 2015 12:02:56 +1100 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t0912rm6031499; Fri, 9 Jan 2015 12:02:53 +1100 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t0912rUq031495; Fri, 9 Jan 2015 12:02:53 +1100 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.192.253.15]) by ozlabs.au.ibm.com (Postfix) with ESMTP id D7D42A00D4; Fri, 9 Jan 2015 12:02:52 +1100 (AEDT) Received: from ka1.ozlabs.ibm.com (ka1.ozlabs.ibm.com [10.61.145.11]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id 520DA16A9B6; Fri, 9 Jan 2015 12:02:52 +1100 (AEDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Fri, 9 Jan 2015 12:02:51 +1100 Message-Id: <1420765371-25342-1-git-send-email-aik@ozlabs.ru> X-Mailer: git-send-email 2.0.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15010901-0033-0000-0000-000000E5D398 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 202.81.31.142 Cc: Alexey Kardashevskiy , qemu-ppc@nongnu.org, Alexander Graf , David Gibson Subject: [Qemu-devel] [RFC PATCH] spapr_vio/spapr_iommu: Move VIO bypass where it belongs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Instead of tweaking a TCE table device by adding there a bypass flag, let's add an alias to RAM and IOMMU memory region, and enable/disable those according to the selected bypass mode. This way IOMMU memory region can have size of the actual window rather than ram_size which is essential for upcoming DDW support. Signed-off-by: Alexey Kardashevskiy --- The main reason for this patch is DDW and the fact that sPAPRTCETable used for DMA windows for VFIO. My latest approach removes all DMA windows on the guest reset (and creates a new 32bit one) which means than VFIO unmaps everything and this fails as normally sPAPRTCETable MemoryRegion is ram_size big (to support bypass) while it should be 1-2GB. --- hw/ppc/spapr_iommu.c | 15 ++++----------- hw/ppc/spapr_vio.c | 42 +++++++++++++++++++++++++++++++++++++++--- include/hw/ppc/spapr.h | 2 -- include/hw/ppc/spapr_vio.h | 3 +++ 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 6c91d8e..cb01f8a 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -72,9 +72,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (tcet->bypass) { - ret.perm = IOMMU_RW; - } else if ((addr >> tcet->page_shift) < tcet->nb_table) { + if ((addr >> tcet->page_shift) < tcet->nb_table) { /* Check if we are in bound */ hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); @@ -100,7 +98,7 @@ static const VMStateDescription vmstate_spapr_tce_table = { VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable), /* IOMMU state */ - VMSTATE_BOOL(bypass, sPAPRTCETable), + VMSTATE_UNUSED(sizeof(bool)), VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t), VMSTATE_END_OF_LIST() @@ -131,7 +129,8 @@ static int spapr_tce_table_realize(DeviceState *dev) trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd); memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops, - "iommu-spapr", ram_size); + "iommu-spapr", + (uint64_t)tcet->nb_table << tcet->page_shift); QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); @@ -191,17 +190,11 @@ MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet) return &tcet->iommu; } -void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass) -{ - tcet->bypass = bypass; -} - static void spapr_tce_reset(DeviceState *dev) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); size_t table_size = tcet->nb_table * sizeof(uint64_t); - tcet->bypass = false; memset(tcet->table, 0, table_size); } diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index dc9e46a..a1f2316 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -322,6 +322,18 @@ static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev) free_crq(dev); } +static void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass) +{ + if (dev->bypass == bypass) { + return; + } + + memory_region_set_enabled(&dev->mrbypass, bypass); + memory_region_set_enabled(spapr_tce_get_iommu(dev->tcet), !bypass); + + dev->bypass = bypass; +} + static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -348,7 +360,7 @@ static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr, return; } - spapr_tce_set_bypass(dev->tcet, !!enable); + spapr_vio_set_bypass(dev, !!enable); rtas_st(rets, 0, RTAS_OUT_SUCCESS); } @@ -407,6 +419,7 @@ static void spapr_vio_busdev_reset(DeviceState *qdev) dev->signal_state = 0; + spapr_vio_set_bypass(dev, false); if (pc->reset) { pc->reset(dev); } @@ -456,14 +469,25 @@ static int spapr_vio_busdev_init(DeviceState *qdev) if (pc->rtce_window_size) { uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; + + memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root", + ram_size); + memory_region_init_alias(&dev->mrbypass, OBJECT(dev), + "iommu-spapr-bypass", get_system_memory(), + 0, ram_size); + memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1); + address_space_init(&dev->as, &dev->mrroot, qdev->id); + dev->tcet = spapr_tce_new_table(qdev, liobn, 0, SPAPR_TCE_PAGE_SHIFT, pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT, false); - address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id); + memory_region_add_subregion_overlap(&dev->mrroot, 0, + spapr_tce_get_iommu(dev->tcet), 2); } + return pc->init(dev); } @@ -541,6 +565,15 @@ static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data) k->init = spapr_vio_bridge_init; } +static int spapr_vio_post_load(void *opaque, int version_id) +{ + VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(opaque); + + spapr_vio_set_bypass(dev, dev->bypass); + + return 0; +} + static const TypeInfo spapr_vio_bridge_info = { .name = "spapr-vio-bridge", .parent = TYPE_SYS_BUS_DEVICE, @@ -550,8 +583,9 @@ static const TypeInfo spapr_vio_bridge_info = { const VMStateDescription vmstate_spapr_vio = { .name = "spapr_vio", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, + .post_load = spapr_vio_post_load, .fields = (VMStateField[]) { /* Sanity check */ VMSTATE_UINT32_EQUAL(reg, VIOsPAPRDevice), @@ -563,6 +597,8 @@ const VMStateDescription vmstate_spapr_vio = { VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice), VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice), + VMSTATE_BOOL_V(bypass, VIOsPAPRDevice, 2), + VMSTATE_END_OF_LIST() }, }; diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 749daf4..92f6fc1 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -458,7 +458,6 @@ struct sPAPRTCETable { uint64_t bus_offset; uint32_t page_shift; uint64_t *table; - bool bypass; bool vfio_accel; int fd; MemoryRegion iommu; @@ -474,7 +473,6 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, uint32_t nb_table, bool vfio_accel); MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); -void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 46edc2a..90e3965 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -64,6 +64,9 @@ struct VIOsPAPRDevice { target_ulong signal_state; VIOsPAPR_CRQ crq; AddressSpace as; + bool bypass; + MemoryRegion mrroot; + MemoryRegion mrbypass; sPAPRTCETable *tcet; };