From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 10.223.172.38 with SMTP id v35csp1423511wrc; Fri, 8 Sep 2017 04:15:32 -0700 (PDT) X-Received: by 10.55.15.65 with SMTP id z62mr3448060qkg.2.1504869332053; Fri, 08 Sep 2017 04:15:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1504869332; cv=none; d=google.com; s=arc-20160816; b=hXZPv0qX9icDl4lKvq11iMc8IrPd6R7SmYFcv5KobQ3vffSpIq60koX2eKWtrHvrJS 8Tz9RzrZOJii2c6etsGhp4B1qayvF6/O+qEflBQqjyQk4k4NCiioIXODxmk9gZXQ3b14 /hD92lGbjgl40O4erqtGqmvWimZkgS7k3ydxG4USK74iPvmZmhOeSj28XN4bwetcoXVm 4kYDSPwCiaWryBBj0dss4a99a4j/Yq1+cqoibAtzFi96jqDHcFC1f9zBguLKVRRJZ1kI bl9JjNmJ6EUSTNNFEtVwUUSj/98urr+XNOFMmBtiY+eZGQxw6cVsMnlT7uJfhV/Rf7pY TCDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:to:from:date :dkim-signature:arc-authentication-results; bh=JJbyP33CB49A0OOSpBan0QDkCR+0bX4gYwcCtJtWtvY=; b=MhIOWQkVPq9Iuad3dbww6vGeuSqm+azpcN2Px2hA5Xs8VsegkJkFHMyEmqF5x5wjBB lKoIDOGaz5ViVAAeFM8jvfNv43ukiV1UXzmUWXv9zCA4MP1CUYvAYMuMT4UvhYPmeHuD V8YZIdx2NiRNqZ9b5s603cScbTVkilv8HKyjMWp6xwVLGH/8Aj0B8JDYQBinLieFHtxl QEDu9M8Df9o9SXqvy1l0z2C7su3S+mB2fGowbnnKv8MRu2afNLB98z80QzCJMU0+s7NU oNvzNO6ldk1u1tm7f1kkRetxKGgGmJYhNUGWkFF4AUaf7B0FWp/V7dm6x68OV70I7yMa eWuA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=W0W8oz8P; spf=pass (google.com: domain of qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id b184si1755109qkf.407.2017.09.08.04.15.31 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 08 Sep 2017 04:15:32 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=W0W8oz8P; spf=pass (google.com: domain of qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from localhost ([::1]:44689 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dqHFx-0003DX-Fc for alex.bennee@linaro.org; Fri, 08 Sep 2017 07:15:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37837) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dqGu4-00013b-Q1 for qemu-devel@nongnu.org; Fri, 08 Sep 2017 06:52:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dqGty-0001Kn-K4 for qemu-devel@nongnu.org; Fri, 08 Sep 2017 06:52:52 -0400 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:38838) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dqGtl-0001CV-7e; Fri, 08 Sep 2017 06:52:33 -0400 Received: by mail-pg0-x243.google.com with SMTP id t3so1153763pgt.5; Fri, 08 Sep 2017 03:52:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=JJbyP33CB49A0OOSpBan0QDkCR+0bX4gYwcCtJtWtvY=; b=W0W8oz8PPZ8PoMd3Rr/sXwHFGdhjDXmrGOFHWaDDBza8GhN83LxVWpCYUkI0G+WKhP QJkVNxo4BSbS8uA5vqMHTYAiDOyoCysxJqmg6SF++UyRIb3FJUphezKkVQfqAE7VNQ+Q mQz+Khzsxx9BJ5+xMsMPS7pd9shlpCkGZnDFaGLYBZOaJEDT9rxlYngd4GP337Be3hwN 8jAtDkbR3JtTTW5XQ8R0suT8B6zC3Qg/btqojqfbB654MgBOyZ1vet1/ccNVqd4yfFVs +tAA6w2nCYxrtbQJJ1y/zlufCtyTVt8Wd9qhSoKFtb6vLVpvDJAy2j0ihQ9atdXb3Vok +pAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=JJbyP33CB49A0OOSpBan0QDkCR+0bX4gYwcCtJtWtvY=; b=VPNUSzMMumRokvMlNnUxq2Kp/091iMEPz+hpr0oyVeCnbees3aN53VT9ISghuV7mPc tW532xMuYb5Ia01npCKOOcMYCeWAhZ+KTHgFAqzudaDs9Lc+laRMzfALF62OW/m7qNWG 2/KZG5O3VyIU560HQNq4KjUigbDYYYy9XdZOm25fcjAeRHKJnA5VRQkzBi9tog1+S3zt Jj6pwLTqf2v3qBTFmiOML3MvIQa5u5BH73bPm29vgNtvthxsdCo6jWq8VBhq1m1cu2Lp 0GH6mz4h5WLiHkRkus0ayGYh9y2y/4mb/FBdpSD4F9IVbcpbqVEKAZ3BrUnjoXuckRSR GH+Q== X-Gm-Message-State: AHPjjUgdAk8RBFXmz7/ST40OfORjVqitrByWxNh7kAHEqdMKZtsKta8v rjVpfTq3lxjIVA== X-Google-Smtp-Source: ADKCNb69VrKq4LC1w1gtYWNVk5Jh3kR/mpo2htmkiINOWFgdXREsJJW5DHguqo5R5PY47KCzzDJu6A== X-Received: by 10.84.241.67 with SMTP id u3mr2971586plm.135.1504867950497; Fri, 08 Sep 2017 03:52:30 -0700 (PDT) Received: from virtx40 ([111.93.218.67]) by smtp.gmail.com with ESMTPSA id f29sm3358036pff.136.2017.09.08.03.52.23 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Fri, 08 Sep 2017 03:52:29 -0700 (PDT) Date: Fri, 8 Sep 2017 16:22:14 +0530 From: Linu Cherian To: Eric Auger Message-ID: <20170908105214.GA16412@virtx40> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> <1504286483-23327-6-git-send-email-eric.auger@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1504286483-23327-6-git-send-email-eric.auger@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::243 Subject: Re: [Qemu-devel] [Qemu-arm] [PATCH v7 05/20] hw/arm/smmuv3: Skeleton 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: peter.maydell@linaro.org, drjones@redhat.com, tcain@qti.qualcomm.com, Radha.Chintakuntla@cavium.com, Sunil.Goutham@cavium.com, mohun106@gmail.com, jean-philippe.brucker@arm.com, tn@semihalf.com, bharat.bhushan@nxp.com, mst@redhat.com, will.deacon@arm.com, qemu-devel@nongnu.org, peterx@redhat.com, alex.williamson@redhat.com, qemu-arm@nongnu.org, christoffer.dall@linaro.org, linu.cherian@cavium.com, wtownsen@redhat.com, robin.murphy@arm.com, prem.mallappa@gmail.com, eric.auger.pro@gmail.com Errors-To: qemu-devel-bounces+alex.bennee=linaro.org@nongnu.org Sender: "Qemu-devel" X-TUID: tzEEVh9u6v3y Hi Eric, On Fri Sep 01, 2017 at 07:21:08PM +0200, Eric Auger wrote: > From: Prem Mallappa > > This patch implements a skeleton for the smmuv3 device. > Datatypes and register definitions are introduced. The MMIO > region, the interrupts and the queue are initialized (PRI is > not supported). > > Only the MMIO read operation is implemented here. > > Signed-off-by: Prem Mallappa > Signed-off-by: Eric Auger > > --- > v6 -> v7: > - split into several patches > > v5 -> v6: > - Use IOMMUMemoryregion > - regs become uint32_t and fix 64b MMIO access (.impl) > - trace_smmuv3_write/read_mmio take the size param > > v4 -> v5: > - change smmuv3_translate proto (IOMMUAccessFlags flag) > - has_stagex replaced by is_ste_stagex > - smmu_cfg_populate removed > - added smmuv3_decode_config and reworked error management > - remwork the naming of IOMMU mrs > - fix SMMU_CMDQ_CONS offset > > v3 -> v4 > - smmu_irq_update > - fix hash key allocation > - set smmu_iommu_ops > - set SMMU_REG_CR0, > - smmuv3_translate: ret.perm not set in bypass mode > - use trace events > - renamed STM2U64 into L1STD_L2PTR and STMSPAN into L1STD_SPAN > - rework smmu_find_ste > - fix tg2granule in TT0/0b10 corresponds to 16kB > > v2 -> v3: > - move creation of include/hw/arm/smmuv3.h to this patch to fix compil issue > - compilation allowed > - fix sbus allocation in smmu_init_pci_iommu > - restructure code into headers > - misc cleanups > --- > hw/arm/Makefile.objs | 2 +- > hw/arm/smmuv3-internal.h | 201 +++++++++++++++++++++++++++++++++++++++ > hw/arm/smmuv3.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++ > hw/arm/trace-events | 3 + > include/hw/arm/smmuv3.h | 79 ++++++++++++++++ > 5 files changed, 523 insertions(+), 1 deletion(-) > create mode 100644 hw/arm/smmuv3-internal.h > create mode 100644 hw/arm/smmuv3.c > create mode 100644 include/hw/arm/smmuv3.h > > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs > index 5b2d38d..a7c808b 100644 > --- a/hw/arm/Makefile.objs > +++ b/hw/arm/Makefile.objs > @@ -19,4 +19,4 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o > obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o > obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o > obj-$(CONFIG_MPS2) += mps2.o > -obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o > +obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o > diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h > new file mode 100644 > index 0000000..488acc8 > --- /dev/null > +++ b/hw/arm/smmuv3-internal.h > @@ -0,0 +1,201 @@ > +/* > + * ARM SMMUv3 support - Internal API > + * > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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_ARM_SMMU_V3_INTERNAL_H > +#define HW_ARM_SMMU_V3_INTERNAL_H > + > +#include "trace.h" > +#include "qemu/error-report.h" > +#include "hw/arm/smmu-common.h" > + > +/***************************** > + * MMIO Register > + *****************************/ > +enum { > + SMMU_REG_IDR0 = 0x0, > + > +/* IDR0 Field Values and supported features */ > + > +#define SMMU_IDR0_S2P 1 /* stage 2 */ > +#define SMMU_IDR0_S1P 1 /* stage 1 */ > +#define SMMU_IDR0_TTF 2 /* Aarch64 only - not Aarch32 (LPAE) */ > +#define SMMU_IDR0_COHACC 1 /* IO coherent access */ > +#define SMMU_IDR0_HTTU 2 /* Access and Dirty flag update */ > +#define SMMU_IDR0_HYP 0 /* Hypervisor Stage 1 contexts */ > +#define SMMU_IDR0_ATS 0 /* PCIe RC ATS */ > +#define SMMU_IDR0_ASID16 1 /* 16-bit ASID */ > +#define SMMU_IDR0_PRI 0 /* Page Request Interface */ > +#define SMMU_IDR0_VMID16 0 /* 16-bit VMID */ > +#define SMMU_IDR0_CD2L 0 /* 2-level Context Descriptor table */ > +#define SMMU_IDR0_STALL 1 /* Stalling fault model */ > +#define SMMU_IDR0_TERM 1 /* Termination model behaviour */ > +#define SMMU_IDR0_STLEVEL 1 /* Multi-level Stream Table */ > + > +#define SMMU_IDR0_S2P_SHIFT 0 > +#define SMMU_IDR0_S1P_SHIFT 1 > +#define SMMU_IDR0_TTF_SHIFT 2 > +#define SMMU_IDR0_COHACC_SHIFT 4 > +#define SMMU_IDR0_HTTU_SHIFT 6 > +#define SMMU_IDR0_HYP_SHIFT 9 > +#define SMMU_IDR0_ATS_SHIFT 10 > +#define SMMU_IDR0_ASID16_SHIFT 12 > +#define SMMU_IDR0_PRI_SHIFT 16 > +#define SMMU_IDR0_VMID16_SHIFT 18 > +#define SMMU_IDR0_CD2L_SHIFT 19 > +#define SMMU_IDR0_STALL_SHIFT 24 > +#define SMMU_IDR0_TERM_SHIFT 26 > +#define SMMU_IDR0_STLEVEL_SHIFT 27 > + > + SMMU_REG_IDR1 = 0x4, > +#define SMMU_IDR1_SIDSIZE 16 > + SMMU_REG_IDR2 = 0x8, > + SMMU_REG_IDR3 = 0xc, > + SMMU_REG_IDR4 = 0x10, > + SMMU_REG_IDR5 = 0x14, > +#define SMMU_IDR5_GRAN_SHIFT 4 > +#define SMMU_IDR5_GRAN 0b101 /* GRAN4K, GRAN64K */ > +#define SMMU_IDR5_OAS 4 /* 44 bits */ > + SMMU_REG_IIDR = 0x1c, > + SMMU_REG_CR0 = 0x20, > + > +#define SMMU_CR0_SMMU_ENABLE (1 << 0) > +#define SMMU_CR0_PRIQ_ENABLE (1 << 1) > +#define SMMU_CR0_EVTQ_ENABLE (1 << 2) > +#define SMMU_CR0_CMDQ_ENABLE (1 << 3) > +#define SMMU_CR0_ATS_CHECK (1 << 4) > + > + SMMU_REG_CR0_ACK = 0x24, > + SMMU_REG_CR1 = 0x28, > + SMMU_REG_CR2 = 0x2c, > + > + SMMU_REG_STATUSR = 0x40, > + > + SMMU_REG_IRQ_CTRL = 0x50, > + SMMU_REG_IRQ_CTRL_ACK = 0x54, > + > +#define SMMU_IRQ_CTRL_GERROR_EN (1 << 0) > +#define SMMU_IRQ_CTRL_EVENT_EN (1 << 1) > +#define SMMU_IRQ_CTRL_PRI_EN (1 << 2) > + > + SMMU_REG_GERROR = 0x60, > + > +#define SMMU_GERROR_CMDQ (1 << 0) > +#define SMMU_GERROR_EVENTQ_ABT (1 << 2) > +#define SMMU_GERROR_PRIQ_ABT (1 << 3) > +#define SMMU_GERROR_MSI_CMDQ_ABT (1 << 4) > +#define SMMU_GERROR_MSI_EVENTQ_ABT (1 << 5) > +#define SMMU_GERROR_MSI_PRIQ_ABT (1 << 6) > +#define SMMU_GERROR_MSI_GERROR_ABT (1 << 7) > +#define SMMU_GERROR_SFM_ERR (1 << 8) > + > + SMMU_REG_GERRORN = 0x64, > + SMMU_REG_GERROR_IRQ_CFG0 = 0x68, > + SMMU_REG_GERROR_IRQ_CFG1 = 0x70, > + SMMU_REG_GERROR_IRQ_CFG2 = 0x74, > + > + /* SMMU_BASE_RA Applies to STRTAB_BASE, CMDQ_BASE and EVTQ_BASE */ > +#define SMMU_BASE_RA (1ULL << 62) > + SMMU_REG_STRTAB_BASE = 0x80, > + SMMU_REG_STRTAB_BASE_CFG = 0x88, > + > + SMMU_REG_CMDQ_BASE = 0x90, > + SMMU_REG_CMDQ_PROD = 0x98, > + SMMU_REG_CMDQ_CONS = 0x9c, > + /* CMD Consumer (CONS) */ > +#define SMMU_CMD_CONS_ERR_SHIFT 24 > +#define SMMU_CMD_CONS_ERR_BITS 7 > + > + SMMU_REG_EVTQ_BASE = 0xa0, > + SMMU_REG_EVTQ_PROD = 0xa8, > + SMMU_REG_EVTQ_CONS = 0xac, > + SMMU_REG_EVTQ_IRQ_CFG0 = 0xb0, > + SMMU_REG_EVTQ_IRQ_CFG1 = 0xb8, > + SMMU_REG_EVTQ_IRQ_CFG2 = 0xbc, > + > + SMMU_REG_PRIQ_BASE = 0xc0, > + SMMU_REG_PRIQ_PROD = 0xc8, > + SMMU_REG_PRIQ_CONS = 0xcc, > + SMMU_REG_PRIQ_IRQ_CFG0 = 0xd0, > + SMMU_REG_PRIQ_IRQ_CFG1 = 0xd8, > + SMMU_REG_PRIQ_IRQ_CFG2 = 0xdc, > + > + SMMU_ID_REGS_OFFSET = 0xfd0, > + > + /* Secure registers are not used for now */ > + SMMU_SECURE_OFFSET = 0x8000, > +}; > + > +/********************** > + * Data Structures > + **********************/ > + > +struct __smmu_data2 { > + uint32_t word[2]; > +}; > + > +struct __smmu_data8 { > + uint32_t word[8]; > +}; > + > +struct __smmu_data16 { > + uint32_t word[16]; > +}; > + > +struct __smmu_data4 { > + uint32_t word[4]; > +}; > + > +typedef struct __smmu_data4 Cmd; /* Command Entry */ > +typedef struct __smmu_data8 Evt; /* Event Entry */ > + > +/***************************** > + * Register Access Primitives > + *****************************/ > + > +static inline void smmu_write32_reg(SMMUV3State *s, uint32_t addr, uint32_t val) > +{ > + s->regs[addr >> 2] = val; > +} > + > +static inline void smmu_write64_reg(SMMUV3State *s, uint32_t addr, uint64_t val) > +{ > + addr >>= 2; > + s->regs[addr] = extract64(val, 0, 32); > + s->regs[addr + 1] = extract64(val, 32, 32); > +} > + > +static inline uint32_t smmu_read32_reg(SMMUV3State *s, uint32_t addr) > +{ > + return s->regs[addr >> 2]; > +} > + > +static inline uint64_t smmu_read64_reg(SMMUV3State *s, uint32_t addr) > +{ > + addr >>= 2; > + return s->regs[addr] | ((uint64_t)(s->regs[addr + 1]) << 32); > +} > + > +static inline int smmu_enabled(SMMUV3State *s) > +{ > + return smmu_read32_reg(s, SMMU_REG_CR0) & SMMU_CR0_SMMU_ENABLE; > +} > + > +#endif > diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c > new file mode 100644 > index 0000000..0a7cd1c > --- /dev/null > +++ b/hw/arm/smmuv3.c > @@ -0,0 +1,239 @@ > +/* > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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/boards.h" > +#include "sysemu/sysemu.h" > +#include "hw/sysbus.h" > +#include "hw/pci/pci.h" > +#include "exec/address-spaces.h" > +#include "trace.h" > +#include "qemu/error-report.h" > + > +#include "hw/arm/smmuv3.h" > +#include "smmuv3-internal.h" > + > +static void smmuv3_init_regs(SMMUV3State *s) > +{ > + uint32_t data = > + SMMU_IDR0_STLEVEL << SMMU_IDR0_STLEVEL_SHIFT | > + SMMU_IDR0_TERM << SMMU_IDR0_TERM_SHIFT | > + SMMU_IDR0_STALL << SMMU_IDR0_STALL_SHIFT | > + SMMU_IDR0_VMID16 << SMMU_IDR0_VMID16_SHIFT | > + SMMU_IDR0_PRI << SMMU_IDR0_PRI_SHIFT | > + SMMU_IDR0_ASID16 << SMMU_IDR0_ASID16_SHIFT | > + SMMU_IDR0_ATS << SMMU_IDR0_ATS_SHIFT | > + SMMU_IDR0_HYP << SMMU_IDR0_HYP_SHIFT | > + SMMU_IDR0_HTTU << SMMU_IDR0_HTTU_SHIFT | > + SMMU_IDR0_COHACC << SMMU_IDR0_COHACC_SHIFT | > + SMMU_IDR0_TTF << SMMU_IDR0_TTF_SHIFT | > + SMMU_IDR0_S1P << SMMU_IDR0_S1P_SHIFT | > + SMMU_IDR0_S2P << SMMU_IDR0_S2P_SHIFT; > + > + smmu_write32_reg(s, SMMU_REG_IDR0, data); > + > +#define SMMU_QUEUE_SIZE_LOG2 19 > + data = > + 1 << 27 | /* Attr Types override */ > + SMMU_QUEUE_SIZE_LOG2 << 21 | /* Cmd Q size */ > + SMMU_QUEUE_SIZE_LOG2 << 16 | /* Event Q size */ > + SMMU_QUEUE_SIZE_LOG2 << 11 | /* PRI Q size */ > + 0 << 6 | /* SSID not supported */ > + SMMU_IDR1_SIDSIZE; > + > + smmu_write32_reg(s, SMMU_REG_IDR1, data); > + > + s->sid_size = SMMU_IDR1_SIDSIZE; > + > + data = SMMU_IDR5_GRAN << SMMU_IDR5_GRAN_SHIFT | SMMU_IDR5_OAS; For VFIO case, should we not set the granule size based on underlying pagesize bitmap derived from VFIO_IOMMU_GET_INFO. Else if guest kernel is build with 4k page size and the host kernel is 64k we would start getting map errors. > + > + smmu_write32_reg(s, SMMU_REG_IDR5, data); > +} > + > +static void smmuv3_init_queues(SMMUV3State *s) > +{ > + s->cmdq.prod = 0; > + s->cmdq.cons = 0; > + s->cmdq.wrap.prod = 0; > + s->cmdq.wrap.cons = 0; > + > + s->evtq.prod = 0; > + s->evtq.cons = 0; > + s->evtq.wrap.prod = 0; > + s->evtq.wrap.cons = 0; > + > + s->cmdq.entries = SMMU_QUEUE_SIZE_LOG2; > + s->cmdq.ent_size = sizeof(Cmd); > + s->evtq.entries = SMMU_QUEUE_SIZE_LOG2; > + s->evtq.ent_size = sizeof(Evt); > +} > + > +static void smmuv3_init(SMMUV3State *s) > +{ > + smmuv3_init_regs(s); > + smmuv3_init_queues(s); > +} > + > +static inline void smmu_update_base_reg(SMMUV3State *s, uint64_t *base, > + uint64_t val) > +{ > + *base = val & ~(SMMU_BASE_RA | 0x3fULL); > +} > + > +static void smmu_write_mmio_fixup(SMMUV3State *s, hwaddr *addr) > +{ > + switch (*addr) { > + case 0x100a8: case 0x100ac: /* Aliasing => page0 registers */ > + case 0x100c8: case 0x100cc: > + *addr ^= (hwaddr)0x10000; > + } > +} > + > +static void smmu_write_mmio(void *opaque, hwaddr addr, > + uint64_t val, unsigned size) > +{ > +} > + > +static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) > +{ > + SMMUState *sys = opaque; > + SMMUV3State *s = SMMU_V3_DEV(sys); > + uint64_t val; > + > + smmu_write_mmio_fixup(s, &addr); > + > + /* Primecell/Corelink ID registers */ > + switch (addr) { > + case 0xFF0 ... 0xFFC: > + case 0xFDC ... 0xFE4: > + val = 0; > + error_report("addr:0x%"PRIx64" val:0x%"PRIx64, addr, val); > + break; > + case SMMU_REG_STRTAB_BASE ... SMMU_REG_CMDQ_BASE: > + case SMMU_REG_EVTQ_BASE: > + case SMMU_REG_PRIQ_BASE ... SMMU_REG_PRIQ_IRQ_CFG1: > + val = smmu_read64_reg(s, addr); > + break; > + default: > + val = (uint64_t)smmu_read32_reg(s, addr); > + break; > + } > + > + trace_smmuv3_read_mmio(addr, val, size); > + return val; > +} > + > +static const MemoryRegionOps smmu_mem_ops = { > + .read = smmu_read_mmio, > + .write = smmu_write_mmio, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > + .impl = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > +}; > + > +static void smmu_init_irq(SMMUV3State *s, SysBusDevice *dev) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(s->irq); i++) { > + sysbus_init_irq(dev, &s->irq[i]); > + } > +} > + > +static void smmu_reset(DeviceState *dev) > +{ > + SMMUV3State *s = SMMU_V3_DEV(dev); > + smmuv3_init(s); > +} > + > +static void smmu_realize(DeviceState *d, Error **errp) > +{ > + SMMUState *sys = SMMU_SYS_DEV(d); > + SMMUV3State *s = SMMU_V3_DEV(sys); > + SysBusDevice *dev = SYS_BUS_DEVICE(d); > + > + memory_region_init_io(&sys->iomem, OBJECT(s), > + &smmu_mem_ops, sys, TYPE_SMMU_V3_DEV, 0x20000); > + > + sys->mrtypename = g_strdup(TYPE_SMMUV3_IOMMU_MEMORY_REGION); > + > + sysbus_init_mmio(dev, &sys->iomem); > + > + smmu_init_irq(s, dev); > +} > + > +static const VMStateDescription vmstate_smmuv3 = { > + .name = "smmuv3", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32_ARRAY(regs, SMMUV3State, SMMU_NREGS), > + VMSTATE_END_OF_LIST(), > + }, > +}; > + > +static void smmuv3_instance_init(Object *obj) > +{ > + /* Nothing much to do here as of now */ > +} > + > +static void smmuv3_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->reset = smmu_reset; > + dc->vmsd = &vmstate_smmuv3; > + dc->realize = smmu_realize; > +} > + > +static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, > + void *data) > +{ > +} > + > +static const TypeInfo smmuv3_type_info = { > + .name = TYPE_SMMU_V3_DEV, > + .parent = TYPE_SMMU_DEV_BASE, > + .instance_size = sizeof(SMMUV3State), > + .instance_init = smmuv3_instance_init, > + .class_data = NULL, > + .class_size = sizeof(SMMUV3Class), > + .class_init = smmuv3_class_init, > +}; > + > +static const TypeInfo smmuv3_iommu_memory_region_info = { > + .parent = TYPE_IOMMU_MEMORY_REGION, > + .name = TYPE_SMMUV3_IOMMU_MEMORY_REGION, > + .class_init = smmuv3_iommu_memory_region_class_init, > +}; > + > +static void smmuv3_register_types(void) > +{ > + type_register(&smmuv3_type_info); > + type_register(&smmuv3_iommu_memory_region_info); > +} > + > +type_init(smmuv3_register_types) > + > diff --git a/hw/arm/trace-events b/hw/arm/trace-events > index c67cd39..8affbf7 100644 > --- a/hw/arm/trace-events > +++ b/hw/arm/trace-events > @@ -14,3 +14,6 @@ smmu_page_walk_level_block_pte(int stage, int level, uint64_t baseaddr, uint64_t > smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d, level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" next table address = 0x%"PRIx64 > smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64 > smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova = 0x%"PRIx64" -> pa = 0x%"PRIx64 > + > +#hw/arm/smmuv3.c > +smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x" > diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h > new file mode 100644 > index 0000000..0c8973d > --- /dev/null > +++ b/include/hw/arm/smmuv3.h > @@ -0,0 +1,79 @@ > +/* > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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_ARM_SMMUV3_H > +#define HW_ARM_SMMUV3_H > + > +#include "hw/arm/smmu-common.h" > + > +#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region" > + > +#define SMMU_NREGS 0x200 > + > +typedef struct SMMUQueue { > + hwaddr base; > + uint32_t prod; > + uint32_t cons; > + union { > + struct { > + uint8_t prod:1; > + uint8_t cons:1; > + }; > + uint8_t unused; > + } wrap; > + > + uint16_t entries; /* Number of entries */ > + uint8_t ent_size; /* Size of entry in bytes */ > + uint8_t shift; /* Size in log2 */ > +} SMMUQueue; > + > +typedef struct SMMUV3State { > + SMMUState smmu_state; > + > + /* Local cache of most-frequently used registers */ > +#define SMMU_FEATURE_2LVL_STE (1 << 0) > + uint32_t features; > + uint16_t sid_size; > + uint16_t sid_split; > + uint64_t strtab_base; > + > + uint32_t regs[SMMU_NREGS]; > + > + qemu_irq irq[4]; > + SMMUQueue cmdq, evtq; > + > +} SMMUV3State; > + > +typedef enum { > + SMMU_IRQ_EVTQ, > + SMMU_IRQ_PRIQ, > + SMMU_IRQ_CMD_SYNC, > + SMMU_IRQ_GERROR, > +} SMMUIrq; > + > +typedef struct { > + SMMUBaseClass smmu_base_class; > +} SMMUV3Class; > + > +#define TYPE_SMMU_V3_DEV "smmuv3" > +#define SMMU_V3_DEV(obj) OBJECT_CHECK(SMMUV3State, (obj), TYPE_SMMU_V3_DEV) > +#define SMMU_V3_DEVICE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_V3_DEV) > + > +#endif > -- > 2.5.5 > > -- Linu cherian From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37837) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dqGu4-00013b-Q1 for qemu-devel@nongnu.org; Fri, 08 Sep 2017 06:52:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dqGty-0001Kn-K4 for qemu-devel@nongnu.org; Fri, 08 Sep 2017 06:52:52 -0400 Date: Fri, 8 Sep 2017 16:22:14 +0530 From: Linu Cherian Message-ID: <20170908105214.GA16412@virtx40> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> <1504286483-23327-6-git-send-email-eric.auger@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1504286483-23327-6-git-send-email-eric.auger@redhat.com> Subject: Re: [Qemu-devel] [Qemu-arm] [PATCH v7 05/20] hw/arm/smmuv3: Skeleton List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Eric Auger Cc: eric.auger.pro@gmail.com, peter.maydell@linaro.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org, prem.mallappa@gmail.com, alex.williamson@redhat.com, mohun106@gmail.com, drjones@redhat.com, tcain@qti.qualcomm.com, Radha.Chintakuntla@cavium.com, Sunil.Goutham@cavium.com, mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, will.deacon@arm.com, robin.murphy@arm.com, peterx@redhat.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org, wtownsen@redhat.com, linu.cherian@cavium.com Hi Eric, On Fri Sep 01, 2017 at 07:21:08PM +0200, Eric Auger wrote: > From: Prem Mallappa > > This patch implements a skeleton for the smmuv3 device. > Datatypes and register definitions are introduced. The MMIO > region, the interrupts and the queue are initialized (PRI is > not supported). > > Only the MMIO read operation is implemented here. > > Signed-off-by: Prem Mallappa > Signed-off-by: Eric Auger > > --- > v6 -> v7: > - split into several patches > > v5 -> v6: > - Use IOMMUMemoryregion > - regs become uint32_t and fix 64b MMIO access (.impl) > - trace_smmuv3_write/read_mmio take the size param > > v4 -> v5: > - change smmuv3_translate proto (IOMMUAccessFlags flag) > - has_stagex replaced by is_ste_stagex > - smmu_cfg_populate removed > - added smmuv3_decode_config and reworked error management > - remwork the naming of IOMMU mrs > - fix SMMU_CMDQ_CONS offset > > v3 -> v4 > - smmu_irq_update > - fix hash key allocation > - set smmu_iommu_ops > - set SMMU_REG_CR0, > - smmuv3_translate: ret.perm not set in bypass mode > - use trace events > - renamed STM2U64 into L1STD_L2PTR and STMSPAN into L1STD_SPAN > - rework smmu_find_ste > - fix tg2granule in TT0/0b10 corresponds to 16kB > > v2 -> v3: > - move creation of include/hw/arm/smmuv3.h to this patch to fix compil issue > - compilation allowed > - fix sbus allocation in smmu_init_pci_iommu > - restructure code into headers > - misc cleanups > --- > hw/arm/Makefile.objs | 2 +- > hw/arm/smmuv3-internal.h | 201 +++++++++++++++++++++++++++++++++++++++ > hw/arm/smmuv3.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++ > hw/arm/trace-events | 3 + > include/hw/arm/smmuv3.h | 79 ++++++++++++++++ > 5 files changed, 523 insertions(+), 1 deletion(-) > create mode 100644 hw/arm/smmuv3-internal.h > create mode 100644 hw/arm/smmuv3.c > create mode 100644 include/hw/arm/smmuv3.h > > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs > index 5b2d38d..a7c808b 100644 > --- a/hw/arm/Makefile.objs > +++ b/hw/arm/Makefile.objs > @@ -19,4 +19,4 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o > obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o > obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o > obj-$(CONFIG_MPS2) += mps2.o > -obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o > +obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o > diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h > new file mode 100644 > index 0000000..488acc8 > --- /dev/null > +++ b/hw/arm/smmuv3-internal.h > @@ -0,0 +1,201 @@ > +/* > + * ARM SMMUv3 support - Internal API > + * > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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_ARM_SMMU_V3_INTERNAL_H > +#define HW_ARM_SMMU_V3_INTERNAL_H > + > +#include "trace.h" > +#include "qemu/error-report.h" > +#include "hw/arm/smmu-common.h" > + > +/***************************** > + * MMIO Register > + *****************************/ > +enum { > + SMMU_REG_IDR0 = 0x0, > + > +/* IDR0 Field Values and supported features */ > + > +#define SMMU_IDR0_S2P 1 /* stage 2 */ > +#define SMMU_IDR0_S1P 1 /* stage 1 */ > +#define SMMU_IDR0_TTF 2 /* Aarch64 only - not Aarch32 (LPAE) */ > +#define SMMU_IDR0_COHACC 1 /* IO coherent access */ > +#define SMMU_IDR0_HTTU 2 /* Access and Dirty flag update */ > +#define SMMU_IDR0_HYP 0 /* Hypervisor Stage 1 contexts */ > +#define SMMU_IDR0_ATS 0 /* PCIe RC ATS */ > +#define SMMU_IDR0_ASID16 1 /* 16-bit ASID */ > +#define SMMU_IDR0_PRI 0 /* Page Request Interface */ > +#define SMMU_IDR0_VMID16 0 /* 16-bit VMID */ > +#define SMMU_IDR0_CD2L 0 /* 2-level Context Descriptor table */ > +#define SMMU_IDR0_STALL 1 /* Stalling fault model */ > +#define SMMU_IDR0_TERM 1 /* Termination model behaviour */ > +#define SMMU_IDR0_STLEVEL 1 /* Multi-level Stream Table */ > + > +#define SMMU_IDR0_S2P_SHIFT 0 > +#define SMMU_IDR0_S1P_SHIFT 1 > +#define SMMU_IDR0_TTF_SHIFT 2 > +#define SMMU_IDR0_COHACC_SHIFT 4 > +#define SMMU_IDR0_HTTU_SHIFT 6 > +#define SMMU_IDR0_HYP_SHIFT 9 > +#define SMMU_IDR0_ATS_SHIFT 10 > +#define SMMU_IDR0_ASID16_SHIFT 12 > +#define SMMU_IDR0_PRI_SHIFT 16 > +#define SMMU_IDR0_VMID16_SHIFT 18 > +#define SMMU_IDR0_CD2L_SHIFT 19 > +#define SMMU_IDR0_STALL_SHIFT 24 > +#define SMMU_IDR0_TERM_SHIFT 26 > +#define SMMU_IDR0_STLEVEL_SHIFT 27 > + > + SMMU_REG_IDR1 = 0x4, > +#define SMMU_IDR1_SIDSIZE 16 > + SMMU_REG_IDR2 = 0x8, > + SMMU_REG_IDR3 = 0xc, > + SMMU_REG_IDR4 = 0x10, > + SMMU_REG_IDR5 = 0x14, > +#define SMMU_IDR5_GRAN_SHIFT 4 > +#define SMMU_IDR5_GRAN 0b101 /* GRAN4K, GRAN64K */ > +#define SMMU_IDR5_OAS 4 /* 44 bits */ > + SMMU_REG_IIDR = 0x1c, > + SMMU_REG_CR0 = 0x20, > + > +#define SMMU_CR0_SMMU_ENABLE (1 << 0) > +#define SMMU_CR0_PRIQ_ENABLE (1 << 1) > +#define SMMU_CR0_EVTQ_ENABLE (1 << 2) > +#define SMMU_CR0_CMDQ_ENABLE (1 << 3) > +#define SMMU_CR0_ATS_CHECK (1 << 4) > + > + SMMU_REG_CR0_ACK = 0x24, > + SMMU_REG_CR1 = 0x28, > + SMMU_REG_CR2 = 0x2c, > + > + SMMU_REG_STATUSR = 0x40, > + > + SMMU_REG_IRQ_CTRL = 0x50, > + SMMU_REG_IRQ_CTRL_ACK = 0x54, > + > +#define SMMU_IRQ_CTRL_GERROR_EN (1 << 0) > +#define SMMU_IRQ_CTRL_EVENT_EN (1 << 1) > +#define SMMU_IRQ_CTRL_PRI_EN (1 << 2) > + > + SMMU_REG_GERROR = 0x60, > + > +#define SMMU_GERROR_CMDQ (1 << 0) > +#define SMMU_GERROR_EVENTQ_ABT (1 << 2) > +#define SMMU_GERROR_PRIQ_ABT (1 << 3) > +#define SMMU_GERROR_MSI_CMDQ_ABT (1 << 4) > +#define SMMU_GERROR_MSI_EVENTQ_ABT (1 << 5) > +#define SMMU_GERROR_MSI_PRIQ_ABT (1 << 6) > +#define SMMU_GERROR_MSI_GERROR_ABT (1 << 7) > +#define SMMU_GERROR_SFM_ERR (1 << 8) > + > + SMMU_REG_GERRORN = 0x64, > + SMMU_REG_GERROR_IRQ_CFG0 = 0x68, > + SMMU_REG_GERROR_IRQ_CFG1 = 0x70, > + SMMU_REG_GERROR_IRQ_CFG2 = 0x74, > + > + /* SMMU_BASE_RA Applies to STRTAB_BASE, CMDQ_BASE and EVTQ_BASE */ > +#define SMMU_BASE_RA (1ULL << 62) > + SMMU_REG_STRTAB_BASE = 0x80, > + SMMU_REG_STRTAB_BASE_CFG = 0x88, > + > + SMMU_REG_CMDQ_BASE = 0x90, > + SMMU_REG_CMDQ_PROD = 0x98, > + SMMU_REG_CMDQ_CONS = 0x9c, > + /* CMD Consumer (CONS) */ > +#define SMMU_CMD_CONS_ERR_SHIFT 24 > +#define SMMU_CMD_CONS_ERR_BITS 7 > + > + SMMU_REG_EVTQ_BASE = 0xa0, > + SMMU_REG_EVTQ_PROD = 0xa8, > + SMMU_REG_EVTQ_CONS = 0xac, > + SMMU_REG_EVTQ_IRQ_CFG0 = 0xb0, > + SMMU_REG_EVTQ_IRQ_CFG1 = 0xb8, > + SMMU_REG_EVTQ_IRQ_CFG2 = 0xbc, > + > + SMMU_REG_PRIQ_BASE = 0xc0, > + SMMU_REG_PRIQ_PROD = 0xc8, > + SMMU_REG_PRIQ_CONS = 0xcc, > + SMMU_REG_PRIQ_IRQ_CFG0 = 0xd0, > + SMMU_REG_PRIQ_IRQ_CFG1 = 0xd8, > + SMMU_REG_PRIQ_IRQ_CFG2 = 0xdc, > + > + SMMU_ID_REGS_OFFSET = 0xfd0, > + > + /* Secure registers are not used for now */ > + SMMU_SECURE_OFFSET = 0x8000, > +}; > + > +/********************** > + * Data Structures > + **********************/ > + > +struct __smmu_data2 { > + uint32_t word[2]; > +}; > + > +struct __smmu_data8 { > + uint32_t word[8]; > +}; > + > +struct __smmu_data16 { > + uint32_t word[16]; > +}; > + > +struct __smmu_data4 { > + uint32_t word[4]; > +}; > + > +typedef struct __smmu_data4 Cmd; /* Command Entry */ > +typedef struct __smmu_data8 Evt; /* Event Entry */ > + > +/***************************** > + * Register Access Primitives > + *****************************/ > + > +static inline void smmu_write32_reg(SMMUV3State *s, uint32_t addr, uint32_t val) > +{ > + s->regs[addr >> 2] = val; > +} > + > +static inline void smmu_write64_reg(SMMUV3State *s, uint32_t addr, uint64_t val) > +{ > + addr >>= 2; > + s->regs[addr] = extract64(val, 0, 32); > + s->regs[addr + 1] = extract64(val, 32, 32); > +} > + > +static inline uint32_t smmu_read32_reg(SMMUV3State *s, uint32_t addr) > +{ > + return s->regs[addr >> 2]; > +} > + > +static inline uint64_t smmu_read64_reg(SMMUV3State *s, uint32_t addr) > +{ > + addr >>= 2; > + return s->regs[addr] | ((uint64_t)(s->regs[addr + 1]) << 32); > +} > + > +static inline int smmu_enabled(SMMUV3State *s) > +{ > + return smmu_read32_reg(s, SMMU_REG_CR0) & SMMU_CR0_SMMU_ENABLE; > +} > + > +#endif > diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c > new file mode 100644 > index 0000000..0a7cd1c > --- /dev/null > +++ b/hw/arm/smmuv3.c > @@ -0,0 +1,239 @@ > +/* > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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/boards.h" > +#include "sysemu/sysemu.h" > +#include "hw/sysbus.h" > +#include "hw/pci/pci.h" > +#include "exec/address-spaces.h" > +#include "trace.h" > +#include "qemu/error-report.h" > + > +#include "hw/arm/smmuv3.h" > +#include "smmuv3-internal.h" > + > +static void smmuv3_init_regs(SMMUV3State *s) > +{ > + uint32_t data = > + SMMU_IDR0_STLEVEL << SMMU_IDR0_STLEVEL_SHIFT | > + SMMU_IDR0_TERM << SMMU_IDR0_TERM_SHIFT | > + SMMU_IDR0_STALL << SMMU_IDR0_STALL_SHIFT | > + SMMU_IDR0_VMID16 << SMMU_IDR0_VMID16_SHIFT | > + SMMU_IDR0_PRI << SMMU_IDR0_PRI_SHIFT | > + SMMU_IDR0_ASID16 << SMMU_IDR0_ASID16_SHIFT | > + SMMU_IDR0_ATS << SMMU_IDR0_ATS_SHIFT | > + SMMU_IDR0_HYP << SMMU_IDR0_HYP_SHIFT | > + SMMU_IDR0_HTTU << SMMU_IDR0_HTTU_SHIFT | > + SMMU_IDR0_COHACC << SMMU_IDR0_COHACC_SHIFT | > + SMMU_IDR0_TTF << SMMU_IDR0_TTF_SHIFT | > + SMMU_IDR0_S1P << SMMU_IDR0_S1P_SHIFT | > + SMMU_IDR0_S2P << SMMU_IDR0_S2P_SHIFT; > + > + smmu_write32_reg(s, SMMU_REG_IDR0, data); > + > +#define SMMU_QUEUE_SIZE_LOG2 19 > + data = > + 1 << 27 | /* Attr Types override */ > + SMMU_QUEUE_SIZE_LOG2 << 21 | /* Cmd Q size */ > + SMMU_QUEUE_SIZE_LOG2 << 16 | /* Event Q size */ > + SMMU_QUEUE_SIZE_LOG2 << 11 | /* PRI Q size */ > + 0 << 6 | /* SSID not supported */ > + SMMU_IDR1_SIDSIZE; > + > + smmu_write32_reg(s, SMMU_REG_IDR1, data); > + > + s->sid_size = SMMU_IDR1_SIDSIZE; > + > + data = SMMU_IDR5_GRAN << SMMU_IDR5_GRAN_SHIFT | SMMU_IDR5_OAS; For VFIO case, should we not set the granule size based on underlying pagesize bitmap derived from VFIO_IOMMU_GET_INFO. Else if guest kernel is build with 4k page size and the host kernel is 64k we would start getting map errors. > + > + smmu_write32_reg(s, SMMU_REG_IDR5, data); > +} > + > +static void smmuv3_init_queues(SMMUV3State *s) > +{ > + s->cmdq.prod = 0; > + s->cmdq.cons = 0; > + s->cmdq.wrap.prod = 0; > + s->cmdq.wrap.cons = 0; > + > + s->evtq.prod = 0; > + s->evtq.cons = 0; > + s->evtq.wrap.prod = 0; > + s->evtq.wrap.cons = 0; > + > + s->cmdq.entries = SMMU_QUEUE_SIZE_LOG2; > + s->cmdq.ent_size = sizeof(Cmd); > + s->evtq.entries = SMMU_QUEUE_SIZE_LOG2; > + s->evtq.ent_size = sizeof(Evt); > +} > + > +static void smmuv3_init(SMMUV3State *s) > +{ > + smmuv3_init_regs(s); > + smmuv3_init_queues(s); > +} > + > +static inline void smmu_update_base_reg(SMMUV3State *s, uint64_t *base, > + uint64_t val) > +{ > + *base = val & ~(SMMU_BASE_RA | 0x3fULL); > +} > + > +static void smmu_write_mmio_fixup(SMMUV3State *s, hwaddr *addr) > +{ > + switch (*addr) { > + case 0x100a8: case 0x100ac: /* Aliasing => page0 registers */ > + case 0x100c8: case 0x100cc: > + *addr ^= (hwaddr)0x10000; > + } > +} > + > +static void smmu_write_mmio(void *opaque, hwaddr addr, > + uint64_t val, unsigned size) > +{ > +} > + > +static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) > +{ > + SMMUState *sys = opaque; > + SMMUV3State *s = SMMU_V3_DEV(sys); > + uint64_t val; > + > + smmu_write_mmio_fixup(s, &addr); > + > + /* Primecell/Corelink ID registers */ > + switch (addr) { > + case 0xFF0 ... 0xFFC: > + case 0xFDC ... 0xFE4: > + val = 0; > + error_report("addr:0x%"PRIx64" val:0x%"PRIx64, addr, val); > + break; > + case SMMU_REG_STRTAB_BASE ... SMMU_REG_CMDQ_BASE: > + case SMMU_REG_EVTQ_BASE: > + case SMMU_REG_PRIQ_BASE ... SMMU_REG_PRIQ_IRQ_CFG1: > + val = smmu_read64_reg(s, addr); > + break; > + default: > + val = (uint64_t)smmu_read32_reg(s, addr); > + break; > + } > + > + trace_smmuv3_read_mmio(addr, val, size); > + return val; > +} > + > +static const MemoryRegionOps smmu_mem_ops = { > + .read = smmu_read_mmio, > + .write = smmu_write_mmio, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > + .impl = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > +}; > + > +static void smmu_init_irq(SMMUV3State *s, SysBusDevice *dev) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(s->irq); i++) { > + sysbus_init_irq(dev, &s->irq[i]); > + } > +} > + > +static void smmu_reset(DeviceState *dev) > +{ > + SMMUV3State *s = SMMU_V3_DEV(dev); > + smmuv3_init(s); > +} > + > +static void smmu_realize(DeviceState *d, Error **errp) > +{ > + SMMUState *sys = SMMU_SYS_DEV(d); > + SMMUV3State *s = SMMU_V3_DEV(sys); > + SysBusDevice *dev = SYS_BUS_DEVICE(d); > + > + memory_region_init_io(&sys->iomem, OBJECT(s), > + &smmu_mem_ops, sys, TYPE_SMMU_V3_DEV, 0x20000); > + > + sys->mrtypename = g_strdup(TYPE_SMMUV3_IOMMU_MEMORY_REGION); > + > + sysbus_init_mmio(dev, &sys->iomem); > + > + smmu_init_irq(s, dev); > +} > + > +static const VMStateDescription vmstate_smmuv3 = { > + .name = "smmuv3", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32_ARRAY(regs, SMMUV3State, SMMU_NREGS), > + VMSTATE_END_OF_LIST(), > + }, > +}; > + > +static void smmuv3_instance_init(Object *obj) > +{ > + /* Nothing much to do here as of now */ > +} > + > +static void smmuv3_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->reset = smmu_reset; > + dc->vmsd = &vmstate_smmuv3; > + dc->realize = smmu_realize; > +} > + > +static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, > + void *data) > +{ > +} > + > +static const TypeInfo smmuv3_type_info = { > + .name = TYPE_SMMU_V3_DEV, > + .parent = TYPE_SMMU_DEV_BASE, > + .instance_size = sizeof(SMMUV3State), > + .instance_init = smmuv3_instance_init, > + .class_data = NULL, > + .class_size = sizeof(SMMUV3Class), > + .class_init = smmuv3_class_init, > +}; > + > +static const TypeInfo smmuv3_iommu_memory_region_info = { > + .parent = TYPE_IOMMU_MEMORY_REGION, > + .name = TYPE_SMMUV3_IOMMU_MEMORY_REGION, > + .class_init = smmuv3_iommu_memory_region_class_init, > +}; > + > +static void smmuv3_register_types(void) > +{ > + type_register(&smmuv3_type_info); > + type_register(&smmuv3_iommu_memory_region_info); > +} > + > +type_init(smmuv3_register_types) > + > diff --git a/hw/arm/trace-events b/hw/arm/trace-events > index c67cd39..8affbf7 100644 > --- a/hw/arm/trace-events > +++ b/hw/arm/trace-events > @@ -14,3 +14,6 @@ smmu_page_walk_level_block_pte(int stage, int level, uint64_t baseaddr, uint64_t > smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d, level=%d base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" next table address = 0x%"PRIx64 > smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64 > smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova = 0x%"PRIx64" -> pa = 0x%"PRIx64 > + > +#hw/arm/smmuv3.c > +smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x" > diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h > new file mode 100644 > index 0000000..0c8973d > --- /dev/null > +++ b/include/hw/arm/smmuv3.h > @@ -0,0 +1,79 @@ > +/* > + * Copyright (C) 2014-2016 Broadcom Corporation > + * Copyright (c) 2017 Red Hat, Inc. > + * Written by Prem Mallappa, Eric Auger > + * > + * 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_ARM_SMMUV3_H > +#define HW_ARM_SMMUV3_H > + > +#include "hw/arm/smmu-common.h" > + > +#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region" > + > +#define SMMU_NREGS 0x200 > + > +typedef struct SMMUQueue { > + hwaddr base; > + uint32_t prod; > + uint32_t cons; > + union { > + struct { > + uint8_t prod:1; > + uint8_t cons:1; > + }; > + uint8_t unused; > + } wrap; > + > + uint16_t entries; /* Number of entries */ > + uint8_t ent_size; /* Size of entry in bytes */ > + uint8_t shift; /* Size in log2 */ > +} SMMUQueue; > + > +typedef struct SMMUV3State { > + SMMUState smmu_state; > + > + /* Local cache of most-frequently used registers */ > +#define SMMU_FEATURE_2LVL_STE (1 << 0) > + uint32_t features; > + uint16_t sid_size; > + uint16_t sid_split; > + uint64_t strtab_base; > + > + uint32_t regs[SMMU_NREGS]; > + > + qemu_irq irq[4]; > + SMMUQueue cmdq, evtq; > + > +} SMMUV3State; > + > +typedef enum { > + SMMU_IRQ_EVTQ, > + SMMU_IRQ_PRIQ, > + SMMU_IRQ_CMD_SYNC, > + SMMU_IRQ_GERROR, > +} SMMUIrq; > + > +typedef struct { > + SMMUBaseClass smmu_base_class; > +} SMMUV3Class; > + > +#define TYPE_SMMU_V3_DEV "smmuv3" > +#define SMMU_V3_DEV(obj) OBJECT_CHECK(SMMUV3State, (obj), TYPE_SMMU_V3_DEV) > +#define SMMU_V3_DEVICE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_V3_DEV) > + > +#endif > -- > 2.5.5 > > -- Linu cherian