From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827481; cv=none; d=zohomail.com; s=zohoarc; b=eXUL/4ZOHg9eApZ3Z+qkkbkH/G4+ZEu9NEpmFMmUJn73EAkMWZTFlZCx9Wc4tSrP82lNsqLS+LE8R4CVH7ZViLEeGPmFL2nEgRqwNDLdO+sWz0jLZEzFksW3ROeFmrwqu2Z+eM66+n1EdGINHGketPD8wDFHU1NCMLYa9/Bh5pg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827481; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=B2zdcROsQbOFiJxi4YFtPRy8krLPDKRLFmYJHbhltrk=; b=IbxSQD9C3nSyK3dXJY+Ccsmm7PWkMMA8YMmnfkWbndkhPG3TrdjDqWJwGCgHxE5RMwkhzUWSNQ//gWCAkc+vP9cDEsKFDIvOOUm6aZe7w3dUxMFu0Lb3dG5XGAaEPH1W36/Y6iGhZRB2kA/ijqISNZ08mbN2aak5gJApQNx6xrA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17098274813371023.540181934183; Thu, 7 Mar 2024 08:04:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDZ-00055k-Q7; Thu, 07 Mar 2024 11:03:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDV-00054B-OY for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:35 -0500 Received: from mail-pl1-x633.google.com ([2607:f8b0:4864:20::633]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDT-00065A-Mw for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:33 -0500 Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-1dd2c8f1204so7624275ad.1 for ; Thu, 07 Mar 2024 08:03:30 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827408; x=1710432208; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=B2zdcROsQbOFiJxi4YFtPRy8krLPDKRLFmYJHbhltrk=; b=SjCc9f9F1+pm6HfPJDf05vYkYpw5o7OK84U6spGz0JyUTPWX2jH2FruCBQLv/TKGLA wFuvt/t03mSfrsQeGnbP0bUQoGFBf6AWf1WeA3JVmX60QVkX+1SdEezj4GQ+2zIPyZh3 tzVvwSbf23ESTzeEM7K6E3WueMQtwyJD97cRxj4WyJ1pCgvTr8zFz9YD84GrZ/zaYa5A vmNAc+iK1QTmHX34LWXflGl1jrULrXgrWBnX5dI1sTB5ZUTYCS5pJ2mT3kqhcr7yFvk7 b8sTqQF8ZgGRaLPPNp7doIcs+/UoxA4+OIVHdK0Jx+/cOg8quGO75CEyBOHuP3vXLLls c64g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827408; x=1710432208; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=B2zdcROsQbOFiJxi4YFtPRy8krLPDKRLFmYJHbhltrk=; b=EZsDIvkuO17YkfRynxMGCtPqa07TmBS46HBdFnHyAqia01Xc/MBAI/izUXB6UpsVu1 6twL7La11itUHCPBnEihVnTZv+sao20U3LltxNxaNPct8rWOkQq3hW1t2PoLiV6hON3W 3XBA+FMhq40OAF85zTBVU0S8HrUidDCCG7XWljor/fAa/emQfzZatEjCLuqi/1l3lE1o O/i6tFTuN1Vw48Y2pjggXQOU6jB9fZAACH3UIq0E0M82kAFKuJAAtzWFHnne+XnA9JTI gZiffZ3fdZWa3csQwaV51dpEFaCQxqBqvsdHwgKG0M3qvfD/AMhdU2zVWrNudjqpgc03 txAg== X-Gm-Message-State: AOJu0YwVgOsyBt303viofPWfnQCP9p6qQD9MUceCR7RGS8v4315DnWKa EXbW4rgnAkANcal4Q3TR0hlt1Iv17Rg2CAM8M5btxcyo5OtVaIVNsbnCVciHs10iZLGHdLdh7mf + X-Google-Smtp-Source: AGHT+IGOruu9QRefE1sWJ0Ke5tPBrLgdf6nv0d4Lcde4VeqKQ4XkxLEaAFYR+PXxHLbV8KzSc/Asxg== X-Received: by 2002:a17:902:f552:b0:1dd:6092:743f with SMTP id h18-20020a170902f55200b001dd6092743fmr1261025plf.56.1709827408388; Thu, 07 Mar 2024 08:03:28 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com Subject: [PATCH v2 01/15] exec/memtxattr: add process identifier to the transaction attributes Date: Thu, 7 Mar 2024 13:03:04 -0300 Message-ID: <20240307160319.675044-2-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::633; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x633.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827482074100001 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Extend memory transaction attributes with process identifier to allow per-request address translation logic to use requester_id / process_id to identify memory mapping (e.g. enabling IOMMU w/ PASID translations). Signed-off-by: Tomasz Jeznach Reviewed-by: Frank Chang --- include/exec/memattrs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h index 14cdd8d582..46d0725416 100644 --- a/include/exec/memattrs.h +++ b/include/exec/memattrs.h @@ -52,6 +52,11 @@ typedef struct MemTxAttrs { unsigned int memory:1; /* Requester ID (for MSI for example) */ unsigned int requester_id:16; + + /* + * PCI PASID support: Limited to 8 bits process identifier. + */ + unsigned int pasid:8; } MemTxAttrs; =20 /* Bus masters which don't specify any attributes will get this, --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827616; cv=none; d=zohomail.com; s=zohoarc; b=VHTiG1BFWIVMKrD7fRhtAxiSb3PS4K2XDTIjCDFz9bv1A6uGroixtZse3rrCZ7KYcyGxIVH/O2dJipzrjKfRjIBvaKVdn0q9ZppyfxbY48Htn6Vjz1LL95Ubj3wT50upam7NhAEfzMeK1iy4HquXWNAQl+rShc140E96NOBUY2Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827616; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=es6c9miaYNGt+xfwKAXG4vexKbZlkFBazU5yYx1dLDk=; b=JTfYrmDYzJnm7f0JGe1pyzbLur2v0WRT1aFnkfa2FDKe4sKnNAdOjWmqq+mf9Y75JZOrOoL6a+d2cR2Q5WpTo+eNfNiwwjiqWx0wlgWyuc8YUbIyMR4GeYLdMpumej2VC5EGaynxZYzFS0Or9KW1VzPsMR4TZwliFv2qNKai18c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827616024912.0908157179355; Thu, 7 Mar 2024 08:06:56 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDm-000599-Kj; Thu, 07 Mar 2024 11:03:51 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDX-00054w-PV for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:35 -0500 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDV-00065e-GX for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:35 -0500 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-6e46dcd8feaso746040b3a.2 for ; Thu, 07 Mar 2024 08:03:33 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827412; x=1710432212; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=es6c9miaYNGt+xfwKAXG4vexKbZlkFBazU5yYx1dLDk=; b=L29uoS0Sa5fZPsDoKf5y/gL4LptXkOCMWhwvDXt7DA3g+mB4a/DQ2y1ozIYlTM2N72 APsWrD9LuoZ0EG8vgoWxkRRlS3a+TSFtTJlfltXk6yX/Khw+LF4rokJTED5ZsMqlNRmZ 6rKMTF8Gysd9GlnwbZ4STFi19xte6F5WrG3/VQUUYJ6UTonQo74pkqGdk5THqb72mcaJ 2gWHUGRicf6Cm4eA/Z4+uulMfjFvrSsaNwnXIp2FLjmNHXUfbr6VjJU/lxcm8Faz1NvU KmvlXbhFFquMjgLiChqijutMERZZEGXnDWqQAD2kzPg+qjhZNsRLT9CSKYbYgiRd/pJQ oj/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827412; x=1710432212; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=es6c9miaYNGt+xfwKAXG4vexKbZlkFBazU5yYx1dLDk=; b=xJy7ka69pW/TkCDVlQW7lReuqsYXmaKpMggYbhDWgaIYvdvKk4KQwth2ncC1GEC66V eiB3c+m0lhDOeAILDDkwAlP/dcDGpXIUPHuUFbMn4MNcpBAfpzQpGTEt75LYNu1OgPpa 5Azz0s0ry4EOCTpBFYDjaSd3vmREKsBG0e938w5LL/YOXtpn4Q13cFaTW76O/KK34NMS YC+/a5L9tBiN34PGlrrff/936+r/DMb2vE8tBrF7JpCRscmx+2vKsQue5CPd2NFkZCSC vIzSv+eTe6vIKqA+C0tbHSTALz+PXjg4mTGmcx8Ghkk4Nd5CD4NyuDDVRvndSJJX4v14 AxrA== X-Gm-Message-State: AOJu0Yw2f1xDkwhInR/dBY3XShykT71peTNsC6OYmluXXJj/W/gZr26Y aGvAjFa1LmZXaYWPV2ecw1Yw6Nmq9CWYpiaPkjK+UXNIF7Y2itFChyyrYDubMicJxuJU/0XWghU S X-Google-Smtp-Source: AGHT+IHafpSGl+WSRGzxb7+Fr9YxMiljIFpTNi8gdxf+YucmluW/YLX1VDiT8o8t+iIGTU9Gaww0dQ== X-Received: by 2002:a17:902:c412:b0:1db:5b41:c59a with SMTP id k18-20020a170902c41200b001db5b41c59amr11324535plk.45.1709827411689; Thu, 07 Mar 2024 08:03:31 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 02/15] hw/riscv: add riscv-iommu-bits.h Date: Thu, 7 Mar 2024 13:03:05 -0300 Message-ID: <20240307160319.675044-3-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::42d; envelope-from=dbarboza@ventanamicro.com; helo=mail-pf1-x42d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, UPPERCASE_50_75=0.008 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827616647100001 From: Tomasz Jeznach This header will be used by the RISC-V IOMMU emulation to be added in the next patch. Due to its size it's being sent in separate for an easier review. One thing to notice is that this header can be replaced by the future Linux RISC-V IOMMU driver header, which would become a linux-header we would import instead of keeping our own. The Linux implementation isn't upstream yet so for now we'll have to manage riscv-iommu-bits.h. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- hw/riscv/riscv-iommu-bits.h | 335 ++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 hw/riscv/riscv-iommu-bits.h diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h new file mode 100644 index 0000000000..8e80b1e52a --- /dev/null +++ b/hw/riscv/riscv-iommu-bits.h @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright =C2=A9 2022-2023 Rivos Inc. + * Copyright =C2=A9 2023 FORTH-ICS/CARV + * Copyright =C2=A9 2023 RISC-V IOMMU Task Group + * + * RISC-V Ziommu - Register Layout and Data Structures. + * + * Based on the IOMMU spec version 1.0, 3/2023 + * https://github.com/riscv-non-isa/riscv-iommu + */ + +#ifndef HW_RISCV_IOMMU_BITS_H +#define HW_RISCV_IOMMU_BITS_H + +#include "qemu/osdep.h" + +#define RISCV_IOMMU_SPEC_DOT_VER 0x010 + +#ifndef GENMASK_ULL +#define GENMASK_ULL(h, l) (((~0ULL) >> (63 - (h) + (l))) << (l)) +#endif + +/* + * struct riscv_iommu_fq_record - Fault/Event Queue Record + * See section 3.2 for more info. + */ +struct riscv_iommu_fq_record { + uint64_t hdr; + uint64_t _reserved; + uint64_t iotval; + uint64_t iotval2; +}; +/* Header fields */ +#define RISCV_IOMMU_FQ_HDR_CAUSE GENMASK_ULL(11, 0) +#define RISCV_IOMMU_FQ_HDR_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_FQ_HDR_PV BIT_ULL(32) +#define RISCV_IOMMU_FQ_HDR_TTYPE GENMASK_ULL(39, 34) +#define RISCV_IOMMU_FQ_HDR_DID GENMASK_ULL(63, 40) + +/* + * struct riscv_iommu_pq_record - PCIe Page Request record + * For more infos on the PCIe Page Request queue see chapter 3.3. + */ +struct riscv_iommu_pq_record { + uint64_t hdr; + uint64_t payload; +}; +/* Header fields */ +#define RISCV_IOMMU_PREQ_HDR_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32) +#define RISCV_IOMMU_PREQ_HDR_PRIV BIT_ULL(33) +#define RISCV_IOMMU_PREQ_HDR_EXEC BIT_ULL(34) +#define RISCV_IOMMU_PREQ_HDR_DID GENMASK_ULL(63, 40) +/* Payload fields */ +#define RISCV_IOMMU_PREQ_PAYLOAD_M GENMASK_ULL(2, 0) + +/* Common field positions */ +#define RISCV_IOMMU_PPN_FIELD GENMASK_ULL(53, 10) +#define RISCV_IOMMU_QUEUE_LOGSZ_FIELD GENMASK_ULL(4, 0) +#define RISCV_IOMMU_QUEUE_INDEX_FIELD GENMASK_ULL(31, 0) +#define RISCV_IOMMU_QUEUE_ENABLE BIT(0) +#define RISCV_IOMMU_QUEUE_INTR_ENABLE BIT(1) +#define RISCV_IOMMU_QUEUE_MEM_FAULT BIT(8) +#define RISCV_IOMMU_QUEUE_OVERFLOW BIT(9) +#define RISCV_IOMMU_QUEUE_ACTIVE BIT(16) +#define RISCV_IOMMU_QUEUE_BUSY BIT(17) +#define RISCV_IOMMU_ATP_PPN_FIELD GENMASK_ULL(43, 0) +#define RISCV_IOMMU_ATP_MODE_FIELD GENMASK_ULL(63, 60) + +/* 5.3 IOMMU Capabilities (64bits) */ +#define RISCV_IOMMU_REG_CAP 0x0000 +#define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0) +#define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22) +#define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) +#define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) +#define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32) +#define RISCV_IOMMU_CAP_PD8 BIT_ULL(38) + +/* 5.4 Features control register (32bits) */ +#define RISCV_IOMMU_REG_FCTL 0x0008 + +/* 5.5 Device-directory-table pointer (64bits) */ +#define RISCV_IOMMU_REG_DDTP 0x0010 +#define RISCV_IOMMU_DDTP_MODE GENMASK_ULL(3, 0) +#define RISCV_IOMMU_DDTP_BUSY BIT_ULL(4) +#define RISCV_IOMMU_DDTP_PPN RISCV_IOMMU_PPN_FIELD + +enum riscv_iommu_ddtp_modes { + RISCV_IOMMU_DDTP_MODE_OFF =3D 0, + RISCV_IOMMU_DDTP_MODE_BARE =3D 1, + RISCV_IOMMU_DDTP_MODE_1LVL =3D 2, + RISCV_IOMMU_DDTP_MODE_2LVL =3D 3, + RISCV_IOMMU_DDTP_MODE_3LVL =3D 4, + RISCV_IOMMU_DDTP_MODE_MAX =3D 4 +}; + +/* 5.6 Command Queue Base (64bits) */ +#define RISCV_IOMMU_REG_CQB 0x0018 +#define RISCV_IOMMU_CQB_LOG2SZ RISCV_IOMMU_QUEUE_LOGSZ_FIELD +#define RISCV_IOMMU_CQB_PPN RISCV_IOMMU_PPN_FIELD + +/* 5.7 Command Queue head (32bits) */ +#define RISCV_IOMMU_REG_CQH 0x0020 + +/* 5.8 Command Queue tail (32bits) */ +#define RISCV_IOMMU_REG_CQT 0x0024 + +/* 5.9 Fault Queue Base (64bits) */ +#define RISCV_IOMMU_REG_FQB 0x0028 +#define RISCV_IOMMU_FQB_LOG2SZ RISCV_IOMMU_QUEUE_LOGSZ_FIELD +#define RISCV_IOMMU_FQB_PPN RISCV_IOMMU_PPN_FIELD + +/* 5.10 Fault Queue Head (32bits) */ +#define RISCV_IOMMU_REG_FQH 0x0030 + +/* 5.11 Fault Queue tail (32bits) */ +#define RISCV_IOMMU_REG_FQT 0x0034 + +/* 5.12 Page Request Queue base (64bits) */ +#define RISCV_IOMMU_REG_PQB 0x0038 +#define RISCV_IOMMU_PQB_LOG2SZ RISCV_IOMMU_QUEUE_LOGSZ_FIELD +#define RISCV_IOMMU_PQB_PPN RISCV_IOMMU_PPN_FIELD + +/* 5.13 Page Request Queue head (32bits) */ +#define RISCV_IOMMU_REG_PQH 0x0040 + +/* 5.14 Page Request Queue tail (32bits) */ +#define RISCV_IOMMU_REG_PQT 0x0044 + +/* 5.15 Command Queue CSR (32bits) */ +#define RISCV_IOMMU_REG_CQCSR 0x0048 +#define RISCV_IOMMU_CQCSR_CQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_CQCSR_CIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_CQCSR_CQMF RISCV_IOMMU_QUEUE_MEM_FAULT +#define RISCV_IOMMU_CQCSR_CMD_TO BIT(9) +#define RISCV_IOMMU_CQCSR_CMD_ILL BIT(10) +#define RISCV_IOMMU_CQCSR_CQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_CQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +/* 5.16 Fault Queue CSR (32bits) */ +#define RISCV_IOMMU_REG_FQCSR 0x004C +#define RISCV_IOMMU_FQCSR_FQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_FQCSR_FIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_FQCSR_FQMF RISCV_IOMMU_QUEUE_MEM_FAULT +#define RISCV_IOMMU_FQCSR_FQOF RISCV_IOMMU_QUEUE_OVERFLOW +#define RISCV_IOMMU_FQCSR_FQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_FQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +/* 5.17 Page Request Queue CSR (32bits) */ +#define RISCV_IOMMU_REG_PQCSR 0x0050 +#define RISCV_IOMMU_PQCSR_PQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_PQCSR_PIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_PQCSR_PQMF RISCV_IOMMU_QUEUE_MEM_FAULT +#define RISCV_IOMMU_PQCSR_PQOF RISCV_IOMMU_QUEUE_OVERFLOW +#define RISCV_IOMMU_PQCSR_PQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_PQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +/* 5.18 Interrupt Pending Status (32bits) */ +#define RISCV_IOMMU_REG_IPSR 0x0054 + +enum { + RISCV_IOMMU_INTR_CQ, + RISCV_IOMMU_INTR_FQ, + RISCV_IOMMU_INTR_PM, + RISCV_IOMMU_INTR_PQ, + RISCV_IOMMU_INTR_COUNT +}; + +/* 5.27 Interrupt cause to vector (64bits) */ +#define RISCV_IOMMU_REG_IVEC 0x02F8 + +/* 5.28 MSI Configuration table (32 * 64bits) */ +#define RISCV_IOMMU_REG_MSI_CONFIG 0x0300 + +#define RISCV_IOMMU_REG_SIZE 0x1000 + +#define RISCV_IOMMU_DDTE_VALID BIT_ULL(0) +#define RISCV_IOMMU_DDTE_PPN RISCV_IOMMU_PPN_FIELD + +/* Struct riscv_iommu_dc - Device Context - section 2.1 */ +struct riscv_iommu_dc { + uint64_t tc; + uint64_t iohgatp; + uint64_t ta; + uint64_t fsc; + uint64_t msiptp; + uint64_t msi_addr_mask; + uint64_t msi_addr_pattern; + uint64_t _reserved; +}; + +/* Translation control fields */ +#define RISCV_IOMMU_DC_TC_V BIT_ULL(0) +#define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4) +#define RISCV_IOMMU_DC_TC_PDTV BIT_ULL(5) +#define RISCV_IOMMU_DC_TC_PRPR BIT_ULL(6) +#define RISCV_IOMMU_DC_TC_DPE BIT_ULL(9) +#define RISCV_IOMMU_DC_TC_SXL BIT_ULL(11) + +/* Second-stage (aka G-stage) context fields */ +#define RISCV_IOMMU_DC_IOHGATP_PPN RISCV_IOMMU_ATP_PPN_FIELD +#define RISCV_IOMMU_DC_IOHGATP_GSCID GENMASK_ULL(59, 44) +#define RISCV_IOMMU_DC_IOHGATP_MODE RISCV_IOMMU_ATP_MODE_FIELD + +enum riscv_iommu_dc_iohgatp_modes { + RISCV_IOMMU_DC_IOHGATP_MODE_BARE =3D 0, + RISCV_IOMMU_DC_IOHGATP_MODE_SV32X4 =3D 8, + RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4 =3D 8, + RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4 =3D 9, + RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4 =3D 10 +}; + +/* Translation attributes fields */ +#define RISCV_IOMMU_DC_TA_PSCID GENMASK_ULL(31, 12) + +/* First-stage context fields */ +#define RISCV_IOMMU_DC_FSC_PPN RISCV_IOMMU_ATP_PPN_FIELD +#define RISCV_IOMMU_DC_FSC_MODE RISCV_IOMMU_ATP_MODE_FIELD + +/* Generic I/O MMU command structure - check section 3.1 */ +struct riscv_iommu_command { + uint64_t dword0; + uint64_t dword1; +}; + +#define RISCV_IOMMU_CMD_OPCODE GENMASK_ULL(6, 0) +#define RISCV_IOMMU_CMD_FUNC GENMASK_ULL(9, 7) + +#define RISCV_IOMMU_CMD_IOTINVAL_OPCODE 1 +#define RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA 0 +#define RISCV_IOMMU_CMD_IOTINVAL_FUNC_GVMA 1 +#define RISCV_IOMMU_CMD_IOTINVAL_AV BIT_ULL(10) +#define RISCV_IOMMU_CMD_IOTINVAL_PSCID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_CMD_IOTINVAL_PSCV BIT_ULL(32) +#define RISCV_IOMMU_CMD_IOTINVAL_GV BIT_ULL(33) +#define RISCV_IOMMU_CMD_IOTINVAL_GSCID GENMASK_ULL(59, 44) + +#define RISCV_IOMMU_CMD_IOFENCE_OPCODE 2 +#define RISCV_IOMMU_CMD_IOFENCE_FUNC_C 0 +#define RISCV_IOMMU_CMD_IOFENCE_AV BIT_ULL(10) +#define RISCV_IOMMU_CMD_IOFENCE_DATA GENMASK_ULL(63, 32) + +#define RISCV_IOMMU_CMD_IODIR_OPCODE 3 +#define RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT 0 +#define RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_PDT 1 +#define RISCV_IOMMU_CMD_IODIR_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_CMD_IODIR_DV BIT_ULL(33) +#define RISCV_IOMMU_CMD_IODIR_DID GENMASK_ULL(63, 40) + +enum riscv_iommu_dc_fsc_atp_modes { + RISCV_IOMMU_DC_FSC_MODE_BARE =3D 0, + RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 =3D 8, + RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV39 =3D 8, + RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV48 =3D 9, + RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57 =3D 10, + RISCV_IOMMU_DC_FSC_PDTP_MODE_PD8 =3D 1, + RISCV_IOMMU_DC_FSC_PDTP_MODE_PD17 =3D 2, + RISCV_IOMMU_DC_FSC_PDTP_MODE_PD20 =3D 3 +}; + +enum riscv_iommu_fq_causes { + RISCV_IOMMU_FQ_CAUSE_INST_FAULT =3D 1, + RISCV_IOMMU_FQ_CAUSE_RD_ADDR_MISALIGNED =3D 4, + RISCV_IOMMU_FQ_CAUSE_RD_FAULT =3D 5, + RISCV_IOMMU_FQ_CAUSE_WR_ADDR_MISALIGNED =3D 6, + RISCV_IOMMU_FQ_CAUSE_WR_FAULT =3D 7, + RISCV_IOMMU_FQ_CAUSE_INST_FAULT_S =3D 12, + RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S =3D 13, + RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S =3D 15, + RISCV_IOMMU_FQ_CAUSE_INST_FAULT_VS =3D 20, + RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS =3D 21, + RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS =3D 23, + RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED =3D 256, + RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT =3D 257, + RISCV_IOMMU_FQ_CAUSE_DDT_INVALID =3D 258, + RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED =3D 259, + RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED =3D 260, + RISCV_IOMMU_FQ_CAUSE_MSI_LOAD_FAULT =3D 261, + RISCV_IOMMU_FQ_CAUSE_MSI_INVALID =3D 262, + RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED =3D 263, + RISCV_IOMMU_FQ_CAUSE_MRIF_FAULT =3D 264, + RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT =3D 265, + RISCV_IOMMU_FQ_CAUSE_PDT_INVALID =3D 266, + RISCV_IOMMU_FQ_CAUSE_PDT_MISCONFIGURED =3D 267, + RISCV_IOMMU_FQ_CAUSE_DDT_CORRUPTED =3D 268, + RISCV_IOMMU_FQ_CAUSE_PDT_CORRUPTED =3D 269, + RISCV_IOMMU_FQ_CAUSE_MSI_PT_CORRUPTED =3D 270, + RISCV_IOMMU_FQ_CAUSE_MRIF_CORRUIPTED =3D 271, + RISCV_IOMMU_FQ_CAUSE_INTERNAL_DP_ERROR =3D 272, + RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT =3D 273, + RISCV_IOMMU_FQ_CAUSE_PT_CORRUPTED =3D 274 +}; + +/* MSI page table pointer */ +#define RISCV_IOMMU_DC_MSIPTP_PPN RISCV_IOMMU_ATP_PPN_FIELD +#define RISCV_IOMMU_DC_MSIPTP_MODE RISCV_IOMMU_ATP_MODE_FIELD +#define RISCV_IOMMU_DC_MSIPTP_MODE_FLAT 1 + +/* Translation attributes fields */ +#define RISCV_IOMMU_PC_TA_V BIT_ULL(0) + +/* First stage context fields */ +#define RISCV_IOMMU_PC_FSC_PPN GENMASK_ULL(43, 0) + +enum riscv_iommu_fq_ttypes { + RISCV_IOMMU_FQ_TTYPE_NONE =3D 0, + RISCV_IOMMU_FQ_TTYPE_UADDR_INST_FETCH =3D 1, + RISCV_IOMMU_FQ_TTYPE_UADDR_RD =3D 2, + RISCV_IOMMU_FQ_TTYPE_UADDR_WR =3D 3, + RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH =3D 5, + RISCV_IOMMU_FQ_TTYPE_TADDR_RD =3D 6, + RISCV_IOMMU_FQ_TTYPE_TADDR_WR =3D 7, + RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ =3D 8, +}; + +/* Fields on pte */ +#define RISCV_IOMMU_MSI_PTE_V BIT_ULL(0) +#define RISCV_IOMMU_MSI_PTE_M GENMASK_ULL(2, 1) + +#define RISCV_IOMMU_MSI_PTE_M_MRIF 1 +#define RISCV_IOMMU_MSI_PTE_M_BASIC 3 + +/* When M =3D=3D 1 (MRIF mode) */ +#define RISCV_IOMMU_MSI_PTE_MRIF_ADDR GENMASK_ULL(53, 7) +/* When M =3D=3D 3 (basic mode) */ +#define RISCV_IOMMU_MSI_PTE_PPN RISCV_IOMMU_PPN_FIELD +#define RISCV_IOMMU_MSI_PTE_C BIT_ULL(63) + +/* Fields on mrif_info */ +#define RISCV_IOMMU_MSI_MRIF_NID GENMASK_ULL(9, 0) +#define RISCV_IOMMU_MSI_MRIF_NPPN RISCV_IOMMU_PPN_FIELD +#define RISCV_IOMMU_MSI_MRIF_NID_MSB BIT_ULL(60) + +#endif /* _RISCV_IOMMU_BITS_H_ */ --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827523; cv=none; d=zohomail.com; s=zohoarc; b=XRc3sPQPMjcKZNy3jooowPGFfx8fmWaI2LqDyR6XEEejdzejYPIwhqwP6shCSi2CM64+KSRKPZDbW6ajngzn/N35vYrROczqETC/Y+Frp4rjQOqopmdcUT4uBeISnLohmKbibs93FDuZn37xSIOh2Fr86zVfG4Ylub3uDH/jF0c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827523; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BAMaWcHMOypKeYr1sHFj4RwUT43WZbC+jheUuyBSBjM=; b=ISvti4U3sAq8N70lc9hbRTBIrIFZm6B0lYWZdNOL3ixrnZGk7QHILp3BIwrJZ7PNAyYApkdzrSgH18Onbas7o/MyXTyLBJ+3dFvZd8ws0sdlbggfbJuf7MyUa5jfn2xmsqFOUqk7iaDlpUQEunD7osm0kL4sJTwv2/wRqIbbkPs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827523122369.22521318188456; Thu, 7 Mar 2024 08:05:23 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDo-0005AP-MZ; Thu, 07 Mar 2024 11:03:52 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDf-00056Q-9R for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:48 -0500 Received: from mail-pl1-x635.google.com ([2607:f8b0:4864:20::635]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDa-00068O-6J for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:42 -0500 Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1dd59b95677so5112655ad.1 for ; Thu, 07 Mar 2024 08:03:37 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827416; x=1710432216; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BAMaWcHMOypKeYr1sHFj4RwUT43WZbC+jheUuyBSBjM=; b=k0RJYqTbscmvj0QgJ3T+Iv4cQY5XgcESnpwVS6uH6l72AHiPR5NJK+Gv6AMV/gJlEq jHtwA56B4xT3JKFqbKu/kR68iUFOEp8gS6Xxr+7O2auY/ZdbYcgOUxCY1wGB33Wn/BJX scWAKpYlcGoR8CDO7qUSxoDWnFXTcRm3GhEMiqS8pt5ETlkS7OobtUUrIo8Kz+WvFDfo q9k8WrcAuht+JL8zQVpCjLXMvsilCpo7vmers3CUaoEd6eP1N3CGq+Rlmcec81Vd9oSL eZ0KXxoadbfVYXAOeQbz4GvVEtowlQEJtwKWbFCXsP8bBIUsVDs4VOJTElRZOGvF8fpX Wsvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827416; x=1710432216; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BAMaWcHMOypKeYr1sHFj4RwUT43WZbC+jheUuyBSBjM=; b=Toh0CE8YZugsz1y3jheBLl1VWbxn4NVbf8ELEMgtrHfv+Bu5LPCccxTpeRs1qw+JH+ Cbabpt3l0uT1kGTD+Sj4IlJ40krkiR7VPG0Tm2aOSR8GRXjVahrnQuBKACGRfytjceE2 yMHXLm3Kx15DaHQ2pyr6HWKb321h9PziDxo5I0pA1D+sxEEpeBtTrH8dy93WCcv9MgCS S95IcrB6Lc/M+dTS4cbCPYiQgjuYOkKH1p65FsJhdFVX5n8PZHCtj9V6i02RYHSctKBU J3DPIRJ2Y43avLP7Bi4CtekB8VwxICtbwfFFZM4ICF6Rc//YLOcYEAhKAiAEotqvN1FG XBbw== X-Gm-Message-State: AOJu0YwfO/XiW05iJxbS/O3KBIR6hbfNboI4yACweKNygpAiHrdieelP eXUjn9KLHa0Yxk/MdyU4Zqa82sMldAaESQlTJCc8sYsEgfoTGaIJ3yF2tIrhMJibHSEHGKtqEfR I X-Google-Smtp-Source: AGHT+IEpcxDw9aQWiyBRjsQ4Kvpy2Y/cfPIuHcFJGE6Tb+lZRbJlWcnthFPmzXann8P+QRDYSLdP0A== X-Received: by 2002:a17:902:7845:b0:1db:51ee:8677 with SMTP id e5-20020a170902784500b001db51ee8677mr7529093pln.59.1709827415264; Thu, 07 Mar 2024 08:03:35 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Sebastien Boeuf , Daniel Henrique Barboza Subject: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation Date: Thu, 7 Mar 2024 13:03:06 -0300 Message-ID: <20240307160319.675044-4-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::635; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x635.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827524524100003 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach The RISC-V IOMMU specification is now ratified as-per the RISC-V international process. The latest frozen specifcation can be found at: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-i= ommu.pdf Add the foundation of the device emulation for RISC-V IOMMU, which includes an IOMMU that has no capabilities but MSI interrupt support and fault queue interfaces. We'll add add more features incrementally in the next patches. Co-developed-by: Sebastien Boeuf Signed-off-by: Sebastien Boeuf Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza --- hw/riscv/Kconfig | 4 + hw/riscv/meson.build | 1 + hw/riscv/riscv-iommu.c | 1492 ++++++++++++++++++++++++++++++++++++++ hw/riscv/riscv-iommu.h | 141 ++++ hw/riscv/trace-events | 11 + hw/riscv/trace.h | 2 + include/hw/riscv/iommu.h | 36 + meson.build | 1 + 8 files changed, 1688 insertions(+) create mode 100644 hw/riscv/riscv-iommu.c create mode 100644 hw/riscv/riscv-iommu.h create mode 100644 hw/riscv/trace-events create mode 100644 hw/riscv/trace.h create mode 100644 include/hw/riscv/iommu.h diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 5d644eb7b1..faf6a10029 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -1,3 +1,6 @@ +config RISCV_IOMMU + bool + config RISCV_NUMA bool =20 @@ -38,6 +41,7 @@ config RISCV_VIRT select SERIAL select RISCV_ACLINT select RISCV_APLIC + select RISCV_IOMMU select RISCV_IMSIC select SIFIVE_PLIC select SIFIVE_TEST diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 2f7ee81be3..ba9eebd605 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,5 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sif= ive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfs= oc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c')) =20 hw_arch +=3D {'riscv': riscv_ss} diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c new file mode 100644 index 0000000000..df534b99b0 --- /dev/null +++ b/hw/riscv/riscv-iommu.c @@ -0,0 +1,1492 @@ +/* + * QEMU emulation of an RISC-V IOMMU (Ziommu) + * + * Copyright (C) 2021-2023, Rivos Inc. + * + * 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. + * + * 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 "qom/object.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci/pci_device.h" +#include "hw/qdev-properties.h" +#include "hw/riscv/riscv_hart.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/timer.h" + +#include "cpu_bits.h" +#include "riscv-iommu.h" +#include "riscv-iommu-bits.h" +#include "trace.h" + +#define LIMIT_CACHE_CTX (1U << 7) +#define LIMIT_CACHE_IOT (1U << 20) + +/* Physical page number coversions */ +#define PPN_PHYS(ppn) ((ppn) << TARGET_PAGE_BITS) +#define PPN_DOWN(phy) ((phy) >> TARGET_PAGE_BITS) + +typedef struct RISCVIOMMUContext RISCVIOMMUContext; +typedef struct RISCVIOMMUEntry RISCVIOMMUEntry; + +/* Device assigned I/O address space */ +struct RISCVIOMMUSpace { + IOMMUMemoryRegion iova_mr; /* IOVA memory region for attached device = */ + AddressSpace iova_as; /* IOVA address space for attached device = */ + RISCVIOMMUState *iommu; /* Managing IOMMU device state */ + uint32_t devid; /* Requester identifier, AKA device_id */ + bool notifier; /* IOMMU unmap notifier enabled */ + QLIST_ENTRY(RISCVIOMMUSpace) list; +}; + +/* Device translation context state. */ +struct RISCVIOMMUContext { + uint64_t devid:24; /* Requester Id, AKA device_id */ + uint64_t pasid:20; /* Process Address Space ID */ + uint64_t __rfu:20; /* reserved */ + uint64_t tc; /* Translation Control */ + uint64_t ta; /* Translation Attributes */ + uint64_t msi_addr_mask; /* MSI filtering - address mask */ + uint64_t msi_addr_pattern; /* MSI filtering - address pattern */ + uint64_t msiptp; /* MSI redirection page table pointer */ +}; + +/* IOMMU index for transactions without PASID specified. */ +#define RISCV_IOMMU_NOPASID 0 + +static void riscv_iommu_notify(RISCVIOMMUState *s, int vec) +{ + const uint32_t ipsr =3D + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IPSR, (1 << vec), 0); + const uint32_t ivec =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IVEC); + if (s->notify && !(ipsr & (1 << vec))) { + s->notify(s, (ivec >> (vec * 4)) & 0x0F); + } +} + +static void riscv_iommu_fault(RISCVIOMMUState *s, + struct riscv_iommu_fq_record *ev) +{ + uint32_t ctrl =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQCSR); + uint32_t head =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQH) & s->f= q_mask; + uint32_t tail =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQT) & s->f= q_mask; + uint32_t next =3D (tail + 1) & s->fq_mask; + uint32_t devid =3D get_field(ev->hdr, RISCV_IOMMU_FQ_HDR_DID); + + trace_riscv_iommu_flt(s->parent_obj.id, PCI_BUS_NUM(devid), PCI_SLOT(d= evid), + PCI_FUNC(devid), ev->hdr, ev->iotval); + + if (!(ctrl & RISCV_IOMMU_FQCSR_FQON) || + !!(ctrl & (RISCV_IOMMU_FQCSR_FQOF | RISCV_IOMMU_FQCSR_FQMF))) { + return; + } + + if (head =3D=3D next) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, + RISCV_IOMMU_FQCSR_FQOF, 0); + } else { + dma_addr_t addr =3D s->fq_addr + tail * sizeof(*ev); + if (dma_memory_write(s->target_as, addr, ev, sizeof(*ev), + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, + RISCV_IOMMU_FQCSR_FQMF, 0); + } else { + riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_FQT, next); + } + } + + if (ctrl & RISCV_IOMMU_FQCSR_FIE) { + riscv_iommu_notify(s, RISCV_IOMMU_INTR_FQ); + } +} + +static void riscv_iommu_pri(RISCVIOMMUState *s, + struct riscv_iommu_pq_record *pr) +{ + uint32_t ctrl =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR); + uint32_t head =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQH) & s->p= q_mask; + uint32_t tail =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQT) & s->p= q_mask; + uint32_t next =3D (tail + 1) & s->pq_mask; + uint32_t devid =3D get_field(pr->hdr, RISCV_IOMMU_PREQ_HDR_DID); + + trace_riscv_iommu_pri(s->parent_obj.id, PCI_BUS_NUM(devid), PCI_SLOT(d= evid), + PCI_FUNC(devid), pr->payload); + + if (!(ctrl & RISCV_IOMMU_PQCSR_PQON) || + !!(ctrl & (RISCV_IOMMU_PQCSR_PQOF | RISCV_IOMMU_PQCSR_PQMF))) { + return; + } + + if (head =3D=3D next) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, + RISCV_IOMMU_PQCSR_PQOF, 0); + } else { + dma_addr_t addr =3D s->pq_addr + tail * sizeof(*pr); + if (dma_memory_write(s->target_as, addr, pr, sizeof(*pr), + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, + RISCV_IOMMU_PQCSR_PQMF, 0); + } else { + riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_PQT, next); + } + } + + if (ctrl & RISCV_IOMMU_PQCSR_PIE) { + riscv_iommu_notify(s, RISCV_IOMMU_INTR_PQ); + } +} + +/* Portable implementation of pext_u64, bit-mask extraction. */ +static uint64_t _pext_u64(uint64_t val, uint64_t ext) +{ + uint64_t ret =3D 0; + uint64_t rot =3D 1; + + while (ext) { + if (ext & 1) { + if (val & 1) { + ret |=3D rot; + } + rot <<=3D 1; + } + val >>=3D 1; + ext >>=3D 1; + } + + return ret; +} + +/* Check if GPA matches MSI/MRIF pattern. */ +static bool riscv_iommu_msi_check(RISCVIOMMUState *s, RISCVIOMMUContext *c= tx, + dma_addr_t gpa) +{ + if (get_field(ctx->msiptp, RISCV_IOMMU_DC_MSIPTP_MODE) !=3D + RISCV_IOMMU_DC_MSIPTP_MODE_FLAT) { + return false; /* Invalid MSI/MRIF mode */ + } + + if ((PPN_DOWN(gpa) ^ ctx->msi_addr_pattern) & ~ctx->msi_addr_mask) { + return false; /* GPA not in MSI range defined by AIA IMSIC rules. = */ + } + + return true; +} + +/* RISCV IOMMU Address Translation Lookup - Page Table Walk */ +static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x, + IOMMUTLBEntry *iotlb) +{ + /* Early check for MSI address match when IOVA =3D=3D GPA */ + if (iotlb->perm & IOMMU_WO && + riscv_iommu_msi_check(s, ctx, iotlb->iova)) { + iotlb->target_as =3D &s->trap_as; + iotlb->translated_addr =3D iotlb->iova; + iotlb->addr_mask =3D ~TARGET_PAGE_MASK; + return 0; + } + + /* Exit early for pass-through mode. */ + iotlb->translated_addr =3D iotlb->iova; + iotlb->addr_mask =3D ~TARGET_PAGE_MASK; + /* Allow R/W in pass-through mode */ + iotlb->perm =3D IOMMU_RW; + return 0; +} + +/* Redirect MSI write for given GPA. */ +static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s, + RISCVIOMMUContext *ctx, uint64_t gpa, uint64_t data, + unsigned size, MemTxAttrs attrs) +{ + MemTxResult res; + dma_addr_t addr; + uint64_t intn; + uint32_t n190; + uint64_t pte[2]; + + if (!riscv_iommu_msi_check(s, ctx, gpa)) { + return MEMTX_ACCESS_ERROR; + } + + /* Interrupt File Number */ + intn =3D _pext_u64(PPN_DOWN(gpa), ctx->msi_addr_mask); + if (intn >=3D 256) { + /* Interrupt file number out of range */ + return MEMTX_ACCESS_ERROR; + } + + /* fetch MSI PTE */ + addr =3D PPN_PHYS(get_field(ctx->msiptp, RISCV_IOMMU_DC_MSIPTP_PPN)); + addr =3D addr | (intn * sizeof(pte)); + res =3D dma_memory_read(s->target_as, addr, &pte, sizeof(pte), + MEMTXATTRS_UNSPECIFIED); + if (res !=3D MEMTX_OK) { + return res; + } + + le64_to_cpus(&pte[0]); + le64_to_cpus(&pte[1]); + + if (!(pte[0] & RISCV_IOMMU_MSI_PTE_V) || (pte[0] & RISCV_IOMMU_MSI_PTE= _C)) { + return MEMTX_ACCESS_ERROR; + } + + switch (get_field(pte[0], RISCV_IOMMU_MSI_PTE_M)) { + case RISCV_IOMMU_MSI_PTE_M_BASIC: + /* MSI Pass-through mode */ + addr =3D PPN_PHYS(get_field(pte[0], RISCV_IOMMU_MSI_PTE_PPN)); + addr =3D addr | (gpa & TARGET_PAGE_MASK); + + trace_riscv_iommu_msi(s->parent_obj.id, PCI_BUS_NUM(ctx->devid), + PCI_SLOT(ctx->devid), PCI_FUNC(ctx->devid), + gpa, addr); + + return dma_memory_write(s->target_as, addr, &data, size, attrs); + case RISCV_IOMMU_MSI_PTE_M_MRIF: + /* MRIF mode, continue. */ + break; + default: + return MEMTX_ACCESS_ERROR; + } + + /* + * Report an error for interrupt identities exceeding the maximum allo= wed + * for an IMSIC interrupt file (2047) or destination address is not 32= -bit + * aligned. See IOMMU Specification, Chapter 2.3. MSI page tables. + */ + if ((data > 2047) || (gpa & 3)) { + return MEMTX_ACCESS_ERROR; + } + + /* MSI MRIF mode, non atomic pending bit update */ + + /* MRIF pending bit address */ + addr =3D get_field(pte[0], RISCV_IOMMU_MSI_PTE_MRIF_ADDR) << 9; + addr =3D addr | ((data & 0x7c0) >> 3); + + trace_riscv_iommu_msi(s->parent_obj.id, PCI_BUS_NUM(ctx->devid), + PCI_SLOT(ctx->devid), PCI_FUNC(ctx->devid), + gpa, addr); + + /* MRIF pending bit mask */ + data =3D 1ULL << (data & 0x03f); + res =3D dma_memory_read(s->target_as, addr, &intn, sizeof(intn), attrs= ); + if (res !=3D MEMTX_OK) { + return res; + } + intn =3D intn | data; + res =3D dma_memory_write(s->target_as, addr, &intn, sizeof(intn), attr= s); + if (res !=3D MEMTX_OK) { + return res; + } + + /* Get MRIF enable bits */ + addr =3D addr + sizeof(intn); + res =3D dma_memory_read(s->target_as, addr, &intn, sizeof(intn), attrs= ); + if (res !=3D MEMTX_OK) { + return res; + } + if (!(intn & data)) { + /* notification disabled, MRIF update completed. */ + return MEMTX_OK; + } + + /* Send notification message */ + addr =3D PPN_PHYS(get_field(pte[1], RISCV_IOMMU_MSI_MRIF_NPPN)); + n190 =3D get_field(pte[1], RISCV_IOMMU_MSI_MRIF_NID) | + (get_field(pte[1], RISCV_IOMMU_MSI_MRIF_NID_MSB) << 10); + + res =3D dma_memory_write(s->target_as, addr, &n190, sizeof(n190), attr= s); + if (res !=3D MEMTX_OK) { + return res; + } + + return MEMTX_OK; +} + +/* + * RISC-V IOMMU Device Context Loopkup - Device Directory Tree Walk + * + * @s : IOMMU Device State + * @ctx : Device Translation Context with devid and pasid set. + * @return : success or fault code. + */ +static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x) +{ + const uint64_t ddtp =3D s->ddtp; + unsigned mode =3D get_field(ddtp, RISCV_IOMMU_DDTP_MODE); + dma_addr_t addr =3D PPN_PHYS(get_field(ddtp, RISCV_IOMMU_DDTP_PPN)); + struct riscv_iommu_dc dc; + /* Device Context format: 0: extended (64 bytes) | 1: base (32 bytes) = */ + const int dc_fmt =3D !s->enable_msi; + const size_t dc_len =3D sizeof(dc) >> dc_fmt; + unsigned depth; + uint64_t de; + + switch (mode) { + case RISCV_IOMMU_DDTP_MODE_OFF: + return RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED; + + case RISCV_IOMMU_DDTP_MODE_BARE: + /* mock up pass-through translation context */ + ctx->tc =3D RISCV_IOMMU_DC_TC_V; + ctx->ta =3D 0; + ctx->msiptp =3D 0; + return 0; + + case RISCV_IOMMU_DDTP_MODE_1LVL: + depth =3D 0; + break; + + case RISCV_IOMMU_DDTP_MODE_2LVL: + depth =3D 1; + break; + + case RISCV_IOMMU_DDTP_MODE_3LVL: + depth =3D 2; + break; + + default: + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + + /* + * Check supported device id width (in bits). + * See IOMMU Specification, Chapter 6. Software guidelines. + * - if extended device-context format is used: + * 1LVL: 6, 2LVL: 15, 3LVL: 24 + * - if base device-context format is used: + * 1LVL: 7, 2LVL: 16, 3LVL: 24 + */ + if (ctx->devid >=3D (1 << (depth * 9 + 6 + (dc_fmt && depth !=3D 2))))= { + return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; + } + + /* Device directory tree walk */ + for (; depth-- > 0; ) { + /* + * Select device id index bits based on device directory tree level + * and device context format. + * See IOMMU Specification, Chapter 2. Data Structures. + * - if extended device-context format is used: + * device index: [23:15][14:6][5:0] + * - if base device-context format is used: + * device index: [23:16][15:7][6:0] + */ + const int split =3D depth * 9 + 6 + dc_fmt; + addr |=3D ((ctx->devid >> split) << 3) & ~TARGET_PAGE_MASK; + if (dma_memory_read(s->target_as, addr, &de, sizeof(de), + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + return RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT; + } + le64_to_cpus(&de); + if (!(de & RISCV_IOMMU_DDTE_VALID)) { + /* invalid directory entry */ + return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; + } + if (de & ~(RISCV_IOMMU_DDTE_PPN | RISCV_IOMMU_DDTE_VALID)) { + /* reserved bits set */ + return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; + } + addr =3D PPN_PHYS(get_field(de, RISCV_IOMMU_DDTE_PPN)); + } + + /* index into device context entry page */ + addr |=3D (ctx->devid * dc_len) & ~TARGET_PAGE_MASK; + + memset(&dc, 0, sizeof(dc)); + if (dma_memory_read(s->target_as, addr, &dc, dc_len, + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + return RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT; + } + + /* Set translation context. */ + ctx->tc =3D le64_to_cpu(dc.tc); + ctx->ta =3D le64_to_cpu(dc.ta); + ctx->msiptp =3D le64_to_cpu(dc.msiptp); + ctx->msi_addr_mask =3D le64_to_cpu(dc.msi_addr_mask); + ctx->msi_addr_pattern =3D le64_to_cpu(dc.msi_addr_pattern); + + if (!(ctx->tc & RISCV_IOMMU_DC_TC_V)) { + return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; + } + + if (!(ctx->tc & RISCV_IOMMU_DC_TC_PDTV)) { + if (ctx->pasid !=3D RISCV_IOMMU_NOPASID) { + /* PASID is disabled */ + return RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED; + } + return 0; + } + + /* FSC.TC.PDTV enabled */ + if (mode > RISCV_IOMMU_DC_FSC_PDTP_MODE_PD20) { + /* Invalid PDTP.MODE */ + return RISCV_IOMMU_FQ_CAUSE_PDT_MISCONFIGURED; + } + + for (depth =3D mode - RISCV_IOMMU_DC_FSC_PDTP_MODE_PD8; depth-- > 0; )= { + /* + * Select process id index bits based on process directory tree + * level. See IOMMU Specification, 2.2. Process-Directory-Table. + */ + const int split =3D depth * 9 + 8; + addr |=3D ((ctx->pasid >> split) << 3) & ~TARGET_PAGE_MASK; + if (dma_memory_read(s->target_as, addr, &de, sizeof(de), + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + return RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT; + } + le64_to_cpus(&de); + if (!(de & RISCV_IOMMU_PC_TA_V)) { + return RISCV_IOMMU_FQ_CAUSE_PDT_INVALID; + } + addr =3D PPN_PHYS(get_field(de, RISCV_IOMMU_PC_FSC_PPN)); + } + + /* Leaf entry in PDT */ + addr |=3D (ctx->pasid << 4) & ~TARGET_PAGE_MASK; + if (dma_memory_read(s->target_as, addr, &dc.ta, sizeof(uint64_t) * 2, + MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + return RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT; + } + + /* Use FSC and TA from process directory entry. */ + ctx->ta =3D le64_to_cpu(dc.ta); + + return 0; +} + +/* Translation Context cache support */ +static gboolean __ctx_equal(gconstpointer v1, gconstpointer v2) +{ + RISCVIOMMUContext *c1 =3D (RISCVIOMMUContext *) v1; + RISCVIOMMUContext *c2 =3D (RISCVIOMMUContext *) v2; + return c1->devid =3D=3D c2->devid && c1->pasid =3D=3D c2->pasid; +} + +static guint __ctx_hash(gconstpointer v) +{ + RISCVIOMMUContext *ctx =3D (RISCVIOMMUContext *) v; + /* Generate simple hash of (pasid, devid), assuming 24-bit wide devid = */ + return (guint)(ctx->devid) + ((guint)(ctx->pasid) << 24); +} + +static void __ctx_inval_devid_pasid(gpointer key, gpointer value, gpointer= data) +{ + RISCVIOMMUContext *ctx =3D (RISCVIOMMUContext *) value; + RISCVIOMMUContext *arg =3D (RISCVIOMMUContext *) data; + if (ctx->tc & RISCV_IOMMU_DC_TC_V && + ctx->devid =3D=3D arg->devid && + ctx->pasid =3D=3D arg->pasid) { + ctx->tc &=3D ~RISCV_IOMMU_DC_TC_V; + } +} + +static void __ctx_inval_devid(gpointer key, gpointer value, gpointer data) +{ + RISCVIOMMUContext *ctx =3D (RISCVIOMMUContext *) value; + RISCVIOMMUContext *arg =3D (RISCVIOMMUContext *) data; + if (ctx->tc & RISCV_IOMMU_DC_TC_V && + ctx->devid =3D=3D arg->devid) { + ctx->tc &=3D ~RISCV_IOMMU_DC_TC_V; + } +} + +static void __ctx_inval_all(gpointer key, gpointer value, gpointer data) +{ + RISCVIOMMUContext *ctx =3D (RISCVIOMMUContext *) value; + if (ctx->tc & RISCV_IOMMU_DC_TC_V) { + ctx->tc &=3D ~RISCV_IOMMU_DC_TC_V; + } +} + +static void riscv_iommu_ctx_inval(RISCVIOMMUState *s, GHFunc func, + uint32_t devid, uint32_t pasid) +{ + GHashTable *ctx_cache; + RISCVIOMMUContext key =3D { + .devid =3D devid, + .pasid =3D pasid, + }; + ctx_cache =3D g_hash_table_ref(s->ctx_cache); + g_hash_table_foreach(ctx_cache, func, &key); + g_hash_table_unref(ctx_cache); +} + +/* Find or allocate translation context for a given {device_id, process_id= } */ +static RISCVIOMMUContext *riscv_iommu_ctx(RISCVIOMMUState *s, + unsigned devid, unsigned pasid, void **ref) +{ + GHashTable *ctx_cache; + RISCVIOMMUContext *ctx; + RISCVIOMMUContext key =3D { + .devid =3D devid, + .pasid =3D pasid, + }; + + ctx_cache =3D g_hash_table_ref(s->ctx_cache); + ctx =3D g_hash_table_lookup(ctx_cache, &key); + + if (ctx && (ctx->tc & RISCV_IOMMU_DC_TC_V)) { + *ref =3D ctx_cache; + return ctx; + } + + if (g_hash_table_size(s->ctx_cache) >=3D LIMIT_CACHE_CTX) { + ctx_cache =3D g_hash_table_new_full(__ctx_hash, __ctx_equal, + g_free, NULL); + g_hash_table_unref(qatomic_xchg(&s->ctx_cache, ctx_cache)); + } + + ctx =3D g_new0(RISCVIOMMUContext, 1); + ctx->devid =3D devid; + ctx->pasid =3D pasid; + + int fault =3D riscv_iommu_ctx_fetch(s, ctx); + if (!fault) { + g_hash_table_add(ctx_cache, ctx); + *ref =3D ctx_cache; + return ctx; + } + + g_hash_table_unref(ctx_cache); + *ref =3D NULL; + + if (!(ctx->tc & RISCV_IOMMU_DC_TC_DTF)) { + struct riscv_iommu_fq_record ev =3D { 0 }; + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_CAUSE, fault); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE, + RISCV_IOMMU_FQ_TTYPE_UADDR_RD); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_DID, devid); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PID, pasid); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PV, !!pasid); + riscv_iommu_fault(s, &ev); + } + + g_free(ctx); + return NULL; +} + +static void riscv_iommu_ctx_put(RISCVIOMMUState *s, void *ref) +{ + if (ref) { + g_hash_table_unref((GHashTable *)ref); + } +} + +/* Find or allocate address space for a given device */ +static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) +{ + RISCVIOMMUSpace *as; + + /* FIXME: PCIe bus remapping for attached endpoints. */ + devid |=3D s->bus << 8; + + qemu_mutex_lock(&s->core_lock); + QLIST_FOREACH(as, &s->spaces, list) { + if (as->devid =3D=3D devid) { + break; + } + } + qemu_mutex_unlock(&s->core_lock); + + if (as =3D=3D NULL) { + char name[64]; + as =3D g_new0(RISCVIOMMUSpace, 1); + + as->iommu =3D s; + as->devid =3D devid; + + snprintf(name, sizeof(name), "riscv-iommu-%04x:%02x.%d-iova", + PCI_BUS_NUM(as->devid), PCI_SLOT(as->devid), PCI_FUNC(as->devi= d)); + + /* IOVA address space, untranslated addresses */ + memory_region_init_iommu(&as->iova_mr, sizeof(as->iova_mr), + TYPE_RISCV_IOMMU_MEMORY_REGION, + OBJECT(as), name, UINT64_MAX); + address_space_init(&as->iova_as, MEMORY_REGION(&as->iova_mr), + TYPE_RISCV_IOMMU_PCI); + + qemu_mutex_lock(&s->core_lock); + QLIST_INSERT_HEAD(&s->spaces, as, list); + qemu_mutex_unlock(&s->core_lock); + + trace_riscv_iommu_new(s->parent_obj.id, PCI_BUS_NUM(as->devid), + PCI_SLOT(as->devid), PCI_FUNC(as->devid)); + } + return &as->iova_as; +} + +static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x, + IOMMUTLBEntry *iotlb) +{ + bool enable_faults; + bool enable_pasid; + bool enable_pri; + int fault; + + enable_faults =3D !(ctx->tc & RISCV_IOMMU_DC_TC_DTF); + /* + * TC[32] is reserved for custom extensions, used here to temporarily + * enable automatic page-request generation for ATS queries. + */ + enable_pri =3D (iotlb->perm =3D=3D IOMMU_NONE) && (ctx->tc & BIT_ULL(3= 2)); + enable_pasid =3D (ctx->tc & RISCV_IOMMU_DC_TC_PDTV); + + /* Translate using device directory / page table information. */ + fault =3D riscv_iommu_spa_fetch(s, ctx, iotlb); + + if (enable_pri && fault) { + struct riscv_iommu_pq_record pr =3D {0}; + if (enable_pasid) { + pr.hdr =3D set_field(RISCV_IOMMU_PREQ_HDR_PV, + RISCV_IOMMU_PREQ_HDR_PID, ctx->pasid); + } + pr.hdr =3D set_field(pr.hdr, RISCV_IOMMU_PREQ_HDR_DID, ctx->devid); + pr.payload =3D (iotlb->iova & TARGET_PAGE_MASK) | + RISCV_IOMMU_PREQ_PAYLOAD_M; + riscv_iommu_pri(s, &pr); + return fault; + } + + if (enable_faults && fault) { + struct riscv_iommu_fq_record ev; + unsigned ttype; + + if (iotlb->perm & IOMMU_RW) { + ttype =3D RISCV_IOMMU_FQ_TTYPE_UADDR_WR; + } else { + ttype =3D RISCV_IOMMU_FQ_TTYPE_UADDR_RD; + } + ev.hdr =3D set_field(0, RISCV_IOMMU_FQ_HDR_CAUSE, fault); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE, ttype); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PV, enable_pasid); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PID, ctx->pasid); + ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_DID, ctx->devid); + ev.iotval =3D iotlb->iova; + ev.iotval2 =3D iotlb->translated_addr; + ev._reserved =3D 0; + riscv_iommu_fault(s, &ev); + return fault; + } + + return 0; +} + +/* IOMMU Command Interface */ +static MemTxResult riscv_iommu_iofence(RISCVIOMMUState *s, bool notify, + uint64_t addr, uint32_t data) +{ + /* + * ATS processing in this implementation of the IOMMU is synchronous, + * no need to wait for completions here. + */ + if (!notify) { + return MEMTX_OK; + } + + return dma_memory_write(s->target_as, addr, &data, sizeof(data), + MEMTXATTRS_UNSPECIFIED); +} + +static void riscv_iommu_process_ddtp(RISCVIOMMUState *s) +{ + uint64_t old_ddtp =3D s->ddtp; + uint64_t new_ddtp =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_DDTP); + unsigned new_mode =3D get_field(new_ddtp, RISCV_IOMMU_DDTP_MODE); + unsigned old_mode =3D get_field(old_ddtp, RISCV_IOMMU_DDTP_MODE); + bool ok =3D false; + + /* + * Check for allowed DDTP.MODE transitions: + * {OFF, BARE} -> {OFF, BARE, 1LVL, 2LVL, 3LVL} + * {1LVL, 2LVL, 3LVL} -> {OFF, BARE} + */ + if (new_mode =3D=3D old_mode || + new_mode =3D=3D RISCV_IOMMU_DDTP_MODE_OFF || + new_mode =3D=3D RISCV_IOMMU_DDTP_MODE_BARE) { + ok =3D true; + } else if (new_mode =3D=3D RISCV_IOMMU_DDTP_MODE_1LVL || + new_mode =3D=3D RISCV_IOMMU_DDTP_MODE_2LVL || + new_mode =3D=3D RISCV_IOMMU_DDTP_MODE_3LVL) { + ok =3D old_mode =3D=3D RISCV_IOMMU_DDTP_MODE_OFF || + old_mode =3D=3D RISCV_IOMMU_DDTP_MODE_BARE; + } + + if (ok) { + /* clear reserved and busy bits, report back sanitized version */ + new_ddtp =3D set_field(new_ddtp & RISCV_IOMMU_DDTP_PPN, + RISCV_IOMMU_DDTP_MODE, new_mode); + } else { + new_ddtp =3D old_ddtp; + } + s->ddtp =3D new_ddtp; + + riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_DDTP, new_ddtp); +} + +/* Command function and opcode field. */ +#define RISCV_IOMMU_CMD(func, op) (((func) << 7) | (op)) + +static void riscv_iommu_process_cq_tail(RISCVIOMMUState *s) +{ + struct riscv_iommu_command cmd; + MemTxResult res; + dma_addr_t addr; + uint32_t tail, head, ctrl; + uint64_t cmd_opcode; + GHFunc func; + + ctrl =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQCSR); + tail =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQT) & s->cq_mask; + head =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQH) & s->cq_mask; + + /* Check for pending error or queue processing disabled */ + if (!(ctrl & RISCV_IOMMU_CQCSR_CQON) || + !!(ctrl & (RISCV_IOMMU_CQCSR_CMD_ILL | RISCV_IOMMU_CQCSR_CQMF))) { + return; + } + + while (tail !=3D head) { + addr =3D s->cq_addr + head * sizeof(cmd); + res =3D dma_memory_read(s->target_as, addr, &cmd, sizeof(cmd), + MEMTXATTRS_UNSPECIFIED); + + if (res !=3D MEMTX_OK) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, + RISCV_IOMMU_CQCSR_CQMF, 0); + goto fault; + } + + trace_riscv_iommu_cmd(s->parent_obj.id, cmd.dword0, cmd.dword1); + + cmd_opcode =3D get_field(cmd.dword0, + RISCV_IOMMU_CMD_OPCODE | RISCV_IOMMU_CMD_FU= NC); + + switch (cmd_opcode) { + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IOFENCE_FUNC_C, + RISCV_IOMMU_CMD_IOFENCE_OPCODE): + res =3D riscv_iommu_iofence(s, + cmd.dword0 & RISCV_IOMMU_CMD_IOFENCE_AV, cmd.dword1, + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOFENCE_DATA)); + + if (res !=3D MEMTX_OK) { + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, + RISCV_IOMMU_CQCSR_CQMF, 0); + goto fault; + } + break; + + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IOTINVAL_FUNC_GVMA, + RISCV_IOMMU_CMD_IOTINVAL_OPCODE): + if (cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_PSCV) { + /* illegal command arguments IOTINVAL.GVMA & PSCV =3D=3D 1= */ + goto cmd_ill; + } + /* translation cache not implemented yet */ + break; + + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA, + RISCV_IOMMU_CMD_IOTINVAL_OPCODE): + /* translation cache not implemented yet */ + break; + + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT, + RISCV_IOMMU_CMD_IODIR_OPCODE): + if (!(cmd.dword0 & RISCV_IOMMU_CMD_IODIR_DV)) { + /* invalidate all device context cache mappings */ + func =3D __ctx_inval_all; + } else { + /* invalidate all device context matching DID */ + func =3D __ctx_inval_devid; + } + riscv_iommu_ctx_inval(s, func, + get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_DID), 0); + break; + + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_PDT, + RISCV_IOMMU_CMD_IODIR_OPCODE): + if (!(cmd.dword0 & RISCV_IOMMU_CMD_IODIR_DV)) { + /* illegal command arguments IODIR_PDT & DV =3D=3D 0 */ + goto cmd_ill; + } else { + func =3D __ctx_inval_devid_pasid; + } + riscv_iommu_ctx_inval(s, func, + get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_DID), + get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_PID)); + break; + + default: + cmd_ill: + /* Invalid instruction, do not advance instruction index. */ + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, + RISCV_IOMMU_CQCSR_CMD_ILL, 0); + goto fault; + } + + /* Advance and update head pointer after command completes. */ + head =3D (head + 1) & s->cq_mask; + riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_CQH, head); + } + return; + +fault: + if (ctrl & RISCV_IOMMU_CQCSR_CIE) { + riscv_iommu_notify(s, RISCV_IOMMU_INTR_CQ); + } +} + +static void riscv_iommu_process_cq_control(RISCVIOMMUState *s) +{ + uint64_t base; + uint32_t ctrl_set =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQCSR); + uint32_t ctrl_clr; + bool enable =3D !!(ctrl_set & RISCV_IOMMU_CQCSR_CQEN); + bool active =3D !!(ctrl_set & RISCV_IOMMU_CQCSR_CQON); + + if (enable && !active) { + base =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_CQB); + s->cq_mask =3D (2ULL << get_field(base, RISCV_IOMMU_CQB_LOG2SZ)) -= 1; + s->cq_addr =3D PPN_PHYS(get_field(base, RISCV_IOMMU_CQB_PPN)); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_CQT], ~s->cq_mask); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_CQH], 0); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_CQT], 0); + ctrl_set =3D RISCV_IOMMU_CQCSR_CQON; + ctrl_clr =3D RISCV_IOMMU_CQCSR_BUSY | RISCV_IOMMU_CQCSR_CQMF | + RISCV_IOMMU_CQCSR_CMD_ILL | RISCV_IOMMU_CQCSR_CMD_TO; + } else if (!enable && active) { + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_CQT], ~0); + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_CQCSR_BUSY | RISCV_IOMMU_CQCSR_CQON; + } else { + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_CQCSR_BUSY; + } + + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, ctrl_set, ctrl_clr); +} + +static void riscv_iommu_process_fq_control(RISCVIOMMUState *s) +{ + uint64_t base; + uint32_t ctrl_set =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQCSR); + uint32_t ctrl_clr; + bool enable =3D !!(ctrl_set & RISCV_IOMMU_FQCSR_FQEN); + bool active =3D !!(ctrl_set & RISCV_IOMMU_FQCSR_FQON); + + if (enable && !active) { + base =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_FQB); + s->fq_mask =3D (2ULL << get_field(base, RISCV_IOMMU_FQB_LOG2SZ)) -= 1; + s->fq_addr =3D PPN_PHYS(get_field(base, RISCV_IOMMU_FQB_PPN)); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_FQH], ~s->fq_mask); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_FQH], 0); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_FQT], 0); + ctrl_set =3D RISCV_IOMMU_FQCSR_FQON; + ctrl_clr =3D RISCV_IOMMU_FQCSR_BUSY | RISCV_IOMMU_FQCSR_FQMF | + RISCV_IOMMU_FQCSR_FQOF; + } else if (!enable && active) { + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_FQH], ~0); + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_FQCSR_BUSY | RISCV_IOMMU_FQCSR_FQON; + } else { + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_FQCSR_BUSY; + } + + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, ctrl_set, ctrl_clr); +} + +static void riscv_iommu_process_pq_control(RISCVIOMMUState *s) +{ + uint64_t base; + uint32_t ctrl_set =3D riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR); + uint32_t ctrl_clr; + bool enable =3D !!(ctrl_set & RISCV_IOMMU_PQCSR_PQEN); + bool active =3D !!(ctrl_set & RISCV_IOMMU_PQCSR_PQON); + + if (enable && !active) { + base =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_PQB); + s->pq_mask =3D (2ULL << get_field(base, RISCV_IOMMU_PQB_LOG2SZ)) -= 1; + s->pq_addr =3D PPN_PHYS(get_field(base, RISCV_IOMMU_PQB_PPN)); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_PQH], ~s->pq_mask); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_PQH], 0); + stl_le_p(&s->regs_rw[RISCV_IOMMU_REG_PQT], 0); + ctrl_set =3D RISCV_IOMMU_PQCSR_PQON; + ctrl_clr =3D RISCV_IOMMU_PQCSR_BUSY | RISCV_IOMMU_PQCSR_PQMF | + RISCV_IOMMU_PQCSR_PQOF; + } else if (!enable && active) { + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_PQH], ~0); + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_PQCSR_BUSY | RISCV_IOMMU_PQCSR_PQON; + } else { + ctrl_set =3D 0; + ctrl_clr =3D RISCV_IOMMU_PQCSR_BUSY; + } + + riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr); +} + +/* Core IOMMU execution activation */ +enum { + RISCV_IOMMU_EXEC_DDTP, + RISCV_IOMMU_EXEC_CQCSR, + RISCV_IOMMU_EXEC_CQT, + RISCV_IOMMU_EXEC_FQCSR, + RISCV_IOMMU_EXEC_FQH, + RISCV_IOMMU_EXEC_PQCSR, + RISCV_IOMMU_EXEC_PQH, + RISCV_IOMMU_EXEC_TR_REQUEST, + /* RISCV_IOMMU_EXEC_EXIT must be the last enum value */ + RISCV_IOMMU_EXEC_EXIT, +}; + +static void *riscv_iommu_core_proc(void* arg) +{ + RISCVIOMMUState *s =3D arg; + unsigned exec =3D 0; + unsigned mask =3D 0; + + while (!(exec & BIT(RISCV_IOMMU_EXEC_EXIT))) { + mask =3D (mask ? mask : BIT(RISCV_IOMMU_EXEC_EXIT)) >> 1; + switch (exec & mask) { + case BIT(RISCV_IOMMU_EXEC_DDTP): + riscv_iommu_process_ddtp(s); + break; + case BIT(RISCV_IOMMU_EXEC_CQCSR): + riscv_iommu_process_cq_control(s); + break; + case BIT(RISCV_IOMMU_EXEC_CQT): + riscv_iommu_process_cq_tail(s); + break; + case BIT(RISCV_IOMMU_EXEC_FQCSR): + riscv_iommu_process_fq_control(s); + break; + case BIT(RISCV_IOMMU_EXEC_FQH): + /* NOP */ + break; + case BIT(RISCV_IOMMU_EXEC_PQCSR): + riscv_iommu_process_pq_control(s); + break; + case BIT(RISCV_IOMMU_EXEC_PQH): + /* NOP */ + break; + case BIT(RISCV_IOMMU_EXEC_TR_REQUEST): + /* DBG support not implemented yet */ + break; + } + exec &=3D ~mask; + if (!exec) { + qemu_mutex_lock(&s->core_lock); + exec =3D s->core_exec; + while (!exec) { + qemu_cond_wait(&s->core_cond, &s->core_lock); + exec =3D s->core_exec; + } + s->core_exec =3D 0; + qemu_mutex_unlock(&s->core_lock); + } + }; + + return NULL; +} + +static MemTxResult riscv_iommu_mmio_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size, MemTxAttrs attrs) +{ + RISCVIOMMUState *s =3D opaque; + uint32_t regb =3D addr & ~3; + uint32_t busy =3D 0; + uint32_t exec =3D 0; + + if (size =3D=3D 0 || size > 8 || (addr & (size - 1)) !=3D 0) { + /* Unsupported MMIO alignment or access size */ + return MEMTX_ERROR; + } + + if (addr + size > RISCV_IOMMU_REG_MSI_CONFIG) { + /* Unsupported MMIO access location. */ + return MEMTX_ACCESS_ERROR; + } + + /* Track actionable MMIO write. */ + switch (regb) { + case RISCV_IOMMU_REG_DDTP: + case RISCV_IOMMU_REG_DDTP + 4: + exec =3D BIT(RISCV_IOMMU_EXEC_DDTP); + regb =3D RISCV_IOMMU_REG_DDTP; + busy =3D RISCV_IOMMU_DDTP_BUSY; + break; + + case RISCV_IOMMU_REG_CQT: + exec =3D BIT(RISCV_IOMMU_EXEC_CQT); + break; + + case RISCV_IOMMU_REG_CQCSR: + exec =3D BIT(RISCV_IOMMU_EXEC_CQCSR); + busy =3D RISCV_IOMMU_CQCSR_BUSY; + break; + + case RISCV_IOMMU_REG_FQH: + exec =3D BIT(RISCV_IOMMU_EXEC_FQH); + break; + + case RISCV_IOMMU_REG_FQCSR: + exec =3D BIT(RISCV_IOMMU_EXEC_FQCSR); + busy =3D RISCV_IOMMU_FQCSR_BUSY; + break; + + case RISCV_IOMMU_REG_PQH: + exec =3D BIT(RISCV_IOMMU_EXEC_PQH); + break; + + case RISCV_IOMMU_REG_PQCSR: + exec =3D BIT(RISCV_IOMMU_EXEC_PQCSR); + busy =3D RISCV_IOMMU_PQCSR_BUSY; + break; + } + + /* + * Registers update might be not synchronized with core logic. + * If system software updates register when relevant BUSY bit is set + * IOMMU behavior of additional writes to the register is UNSPECIFIED + */ + + qemu_spin_lock(&s->regs_lock); + if (size =3D=3D 1) { + uint8_t ro =3D s->regs_ro[addr]; + uint8_t wc =3D s->regs_wc[addr]; + uint8_t rw =3D s->regs_rw[addr]; + s->regs_rw[addr] =3D ((rw & ro) | (data & ~ro)) & ~(data & wc); + } else if (size =3D=3D 2) { + uint16_t ro =3D lduw_le_p(&s->regs_ro[addr]); + uint16_t wc =3D lduw_le_p(&s->regs_wc[addr]); + uint16_t rw =3D lduw_le_p(&s->regs_rw[addr]); + stw_le_p(&s->regs_rw[addr], ((rw & ro) | (data & ~ro)) & ~(data & = wc)); + } else if (size =3D=3D 4) { + uint32_t ro =3D ldl_le_p(&s->regs_ro[addr]); + uint32_t wc =3D ldl_le_p(&s->regs_wc[addr]); + uint32_t rw =3D ldl_le_p(&s->regs_rw[addr]); + stl_le_p(&s->regs_rw[addr], ((rw & ro) | (data & ~ro)) & ~(data & = wc)); + } else if (size =3D=3D 8) { + uint64_t ro =3D ldq_le_p(&s->regs_ro[addr]); + uint64_t wc =3D ldq_le_p(&s->regs_wc[addr]); + uint64_t rw =3D ldq_le_p(&s->regs_rw[addr]); + stq_le_p(&s->regs_rw[addr], ((rw & ro) | (data & ~ro)) & ~(data & = wc)); + } + + /* Busy flag update, MSB 4-byte register. */ + if (busy) { + uint32_t rw =3D ldl_le_p(&s->regs_rw[regb]); + stl_le_p(&s->regs_rw[regb], rw | busy); + } + qemu_spin_unlock(&s->regs_lock); + + /* Wake up core processing thread. */ + if (exec) { + qemu_mutex_lock(&s->core_lock); + s->core_exec |=3D exec; + qemu_cond_signal(&s->core_cond); + qemu_mutex_unlock(&s->core_lock); + } + + return MEMTX_OK; +} + +static MemTxResult riscv_iommu_mmio_read(void *opaque, hwaddr addr, + uint64_t *data, unsigned size, MemTxAttrs attrs) +{ + RISCVIOMMUState *s =3D opaque; + uint64_t val =3D -1; + uint8_t *ptr; + + if ((addr & (size - 1)) !=3D 0) { + /* Unsupported MMIO alignment. */ + return MEMTX_ERROR; + } + + if (addr + size > RISCV_IOMMU_REG_MSI_CONFIG) { + return MEMTX_ACCESS_ERROR; + } + + ptr =3D &s->regs_rw[addr]; + + if (size =3D=3D 1) { + val =3D (uint64_t)*ptr; + } else if (size =3D=3D 2) { + val =3D lduw_le_p(ptr); + } else if (size =3D=3D 4) { + val =3D ldl_le_p(ptr); + } else if (size =3D=3D 8) { + val =3D ldq_le_p(ptr); + } else { + return MEMTX_ERROR; + } + + *data =3D val; + + return MEMTX_OK; +} + +static const MemoryRegionOps riscv_iommu_mmio_ops =3D { + .read_with_attrs =3D riscv_iommu_mmio_read, + .write_with_attrs =3D riscv_iommu_mmio_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + .unaligned =3D false, + }, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + } +}; + +/* + * Translations matching MSI pattern check are redirected to "riscv-iommu-= trap" + * memory region as untranslated address, for additional MSI/MRIF intercep= tion + * by IOMMU interrupt remapping implementation. + * Note: Device emulation code generating an MSI is expected to provide a = valid + * memory transaction attributes with requested_id set. + */ +static MemTxResult riscv_iommu_trap_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size, MemTxAttrs attrs) +{ + RISCVIOMMUState* s =3D (RISCVIOMMUState *)opaque; + RISCVIOMMUContext *ctx; + MemTxResult res; + void *ref; + uint32_t devid =3D attrs.requester_id; + + if (attrs.unspecified) { + return MEMTX_ACCESS_ERROR; + } + + /* FIXME: PCIe bus remapping for attached endpoints. */ + devid |=3D s->bus << 8; + + ctx =3D riscv_iommu_ctx(s, devid, 0, &ref); + if (ctx =3D=3D NULL) { + res =3D MEMTX_ACCESS_ERROR; + } else { + res =3D riscv_iommu_msi_write(s, ctx, addr, data, size, attrs); + } + riscv_iommu_ctx_put(s, ref); + return res; +} + +static MemTxResult riscv_iommu_trap_read(void *opaque, hwaddr addr, + uint64_t *data, unsigned size, MemTxAttrs attrs) +{ + return MEMTX_ACCESS_ERROR; +} + +static const MemoryRegionOps riscv_iommu_trap_ops =3D { + .read_with_attrs =3D riscv_iommu_trap_read, + .write_with_attrs =3D riscv_iommu_trap_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + .unaligned =3D true, + }, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 8, + } +}; + +static void riscv_iommu_realize(DeviceState *dev, Error **errp) +{ + RISCVIOMMUState *s =3D RISCV_IOMMU(dev); + + s->cap =3D s->version & RISCV_IOMMU_CAP_VERSION; + if (s->enable_msi) { + s->cap |=3D RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF; + } + /* Report QEMU target physical address space limits */ + s->cap =3D set_field(s->cap, RISCV_IOMMU_CAP_PAS, + TARGET_PHYS_ADDR_SPACE_BITS); + + /* TODO: method to report supported PASID bits */ + s->pasid_bits =3D 8; /* restricted to size of MemTxAttrs.pasid */ + s->cap |=3D RISCV_IOMMU_CAP_PD8; + + /* Out-of-reset translation mode: OFF (DMA disabled) BARE (passthrough= ) */ + s->ddtp =3D set_field(0, RISCV_IOMMU_DDTP_MODE, s->enable_off ? + RISCV_IOMMU_DDTP_MODE_OFF : RISCV_IOMMU_DDTP_MODE_= BARE); + + /* register storage */ + s->regs_rw =3D g_new0(uint8_t, RISCV_IOMMU_REG_SIZE); + s->regs_ro =3D g_new0(uint8_t, RISCV_IOMMU_REG_SIZE); + s->regs_wc =3D g_new0(uint8_t, RISCV_IOMMU_REG_SIZE); + + /* Mark all registers read-only */ + memset(s->regs_ro, 0xff, RISCV_IOMMU_REG_SIZE); + + /* + * Register complete MMIO space, including MSI/PBA registers. + * Note, PCIDevice implementation will add overlapping MR for MSI/PBA, + * managed directly by the PCIDevice implementation. + */ + memory_region_init_io(&s->regs_mr, OBJECT(dev), &riscv_iommu_mmio_ops,= s, + "riscv-iommu-regs", RISCV_IOMMU_REG_SIZE); + + /* Set power-on register state */ + stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_CAP], s->cap); + stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_FCTL], s->fctl); + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_DDTP], + ~(RISCV_IOMMU_DDTP_PPN | RISCV_IOMMU_DDTP_MODE)); + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_CQB], + ~(RISCV_IOMMU_CQB_LOG2SZ | RISCV_IOMMU_CQB_PPN)); + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_FQB], + ~(RISCV_IOMMU_FQB_LOG2SZ | RISCV_IOMMU_FQB_PPN)); + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_PQB], + ~(RISCV_IOMMU_PQB_LOG2SZ | RISCV_IOMMU_PQB_PPN)); + stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_CQCSR], RISCV_IOMMU_CQCSR_CQMF | + RISCV_IOMMU_CQCSR_CMD_TO | RISCV_IOMMU_CQCSR_CMD_ILL); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_CQCSR], RISCV_IOMMU_CQCSR_CQON | + RISCV_IOMMU_CQCSR_BUSY); + stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_FQCSR], RISCV_IOMMU_FQCSR_FQMF | + RISCV_IOMMU_FQCSR_FQOF); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_FQCSR], RISCV_IOMMU_FQCSR_FQON | + RISCV_IOMMU_FQCSR_BUSY); + stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_PQCSR], RISCV_IOMMU_PQCSR_PQMF | + RISCV_IOMMU_PQCSR_PQOF); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_PQCSR], RISCV_IOMMU_PQCSR_PQON | + RISCV_IOMMU_PQCSR_BUSY); + stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_IPSR], ~0); + stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_IVEC], 0); + stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_DDTP], s->ddtp); + + /* Memory region for downstream access, if specified. */ + if (s->target_mr) { + s->target_as =3D g_new0(AddressSpace, 1); + address_space_init(s->target_as, s->target_mr, + "riscv-iommu-downstream"); + } else { + /* Fallback to global system memory. */ + s->target_as =3D &address_space_memory; + } + + /* Memory region for untranslated MRIF/MSI writes */ + memory_region_init_io(&s->trap_mr, OBJECT(dev), &riscv_iommu_trap_ops,= s, + "riscv-iommu-trap", ~0ULL); + address_space_init(&s->trap_as, &s->trap_mr, "riscv-iommu-trap-as"); + + /* Device translation context cache */ + s->ctx_cache =3D g_hash_table_new_full(__ctx_hash, __ctx_equal, + g_free, NULL); + + s->iommus.le_next =3D NULL; + s->iommus.le_prev =3D NULL; + QLIST_INIT(&s->spaces); + qemu_cond_init(&s->core_cond); + qemu_mutex_init(&s->core_lock); + qemu_spin_init(&s->regs_lock); + qemu_thread_create(&s->core_proc, "riscv-iommu-core", + riscv_iommu_core_proc, s, QEMU_THREAD_JOINABLE); +} + +static void riscv_iommu_unrealize(DeviceState *dev) +{ + RISCVIOMMUState *s =3D RISCV_IOMMU(dev); + + qemu_mutex_lock(&s->core_lock); + /* cancel pending operations and stop */ + s->core_exec =3D BIT(RISCV_IOMMU_EXEC_EXIT); + qemu_cond_signal(&s->core_cond); + qemu_mutex_unlock(&s->core_lock); + qemu_thread_join(&s->core_proc); + qemu_cond_destroy(&s->core_cond); + qemu_mutex_destroy(&s->core_lock); + g_hash_table_unref(s->ctx_cache); +} + +static Property riscv_iommu_properties[] =3D { + DEFINE_PROP_UINT32("version", RISCVIOMMUState, version, + RISCV_IOMMU_SPEC_DOT_VER), + DEFINE_PROP_UINT32("bus", RISCVIOMMUState, bus, 0x0), + DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE), + DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE), + DEFINE_PROP_LINK("downstream-mr", RISCVIOMMUState, target_mr, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void riscv_iommu_class_init(ObjectClass *klass, void* data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + /* internal device for riscv-iommu-{pci/sys}, not user-creatable */ + dc->user_creatable =3D false; + dc->realize =3D riscv_iommu_realize; + dc->unrealize =3D riscv_iommu_unrealize; + device_class_set_props(dc, riscv_iommu_properties); +} + +static const TypeInfo riscv_iommu_info =3D { + .name =3D TYPE_RISCV_IOMMU, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(RISCVIOMMUState), + .class_init =3D riscv_iommu_class_init, +}; + +static const char *IOMMU_FLAG_STR[] =3D { + "NA", + "RO", + "WR", + "RW", +}; + +/* RISC-V IOMMU Memory Region - Address Translation Space */ +static IOMMUTLBEntry riscv_iommu_memory_region_translate( + IOMMUMemoryRegion *iommu_mr, hwaddr addr, + IOMMUAccessFlags flag, int iommu_idx) +{ + RISCVIOMMUSpace *as =3D container_of(iommu_mr, RISCVIOMMUSpace, iova_m= r); + RISCVIOMMUContext *ctx; + void *ref; + IOMMUTLBEntry iotlb =3D { + .iova =3D addr, + .target_as =3D as->iommu->target_as, + .addr_mask =3D ~0ULL, + .perm =3D flag, + }; + + ctx =3D riscv_iommu_ctx(as->iommu, as->devid, iommu_idx, &ref); + if (ctx =3D=3D NULL) { + /* Translation disabled or invalid. */ + iotlb.addr_mask =3D 0; + iotlb.perm =3D IOMMU_NONE; + } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb)) { + /* Translation disabled or fault reported. */ + iotlb.addr_mask =3D 0; + iotlb.perm =3D IOMMU_NONE; + } + + /* Trace all dma translations with original access flags. */ + trace_riscv_iommu_dma(as->iommu->parent_obj.id, PCI_BUS_NUM(as->devid), + PCI_SLOT(as->devid), PCI_FUNC(as->devid), iommu_= idx, + IOMMU_FLAG_STR[flag & IOMMU_RW], iotlb.iova, + iotlb.translated_addr); + + riscv_iommu_ctx_put(as->iommu, ref); + + return iotlb; +} + +static int riscv_iommu_memory_region_notify( + IOMMUMemoryRegion *iommu_mr, IOMMUNotifierFlag old, + IOMMUNotifierFlag new, Error **errp) +{ + RISCVIOMMUSpace *as =3D container_of(iommu_mr, RISCVIOMMUSpace, iova_m= r); + + if (old =3D=3D IOMMU_NOTIFIER_NONE) { + as->notifier =3D true; + trace_riscv_iommu_notifier_add(iommu_mr->parent_obj.name); + } else if (new =3D=3D IOMMU_NOTIFIER_NONE) { + as->notifier =3D false; + trace_riscv_iommu_notifier_del(iommu_mr->parent_obj.name); + } + + return 0; +} + +static inline bool pci_is_iommu(PCIDevice *pdev) +{ + return pci_get_word(pdev->config + PCI_CLASS_DEVICE) =3D=3D 0x0806; +} + +static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, int de= vfn) +{ + RISCVIOMMUState *s =3D (RISCVIOMMUState *) opaque; + PCIDevice *pdev =3D pci_find_device(bus, pci_bus_num(bus), devfn); + AddressSpace *as =3D NULL; + + if (pdev && pci_is_iommu(pdev)) { + return s->target_as; + } + + /* Find first registered IOMMU device */ + while (s->iommus.le_prev) { + s =3D *(s->iommus.le_prev); + } + + /* Find first matching IOMMU */ + while (s !=3D NULL && as =3D=3D NULL) { + as =3D riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), devfn)= ); + s =3D s->iommus.le_next; + } + + return as ? as : &address_space_memory; +} + +static const PCIIOMMUOps riscv_iommu_ops =3D { + .get_address_space =3D riscv_iommu_find_as, +}; + +void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, + Error **errp) +{ + if (bus->iommu_ops && + bus->iommu_ops->get_address_space =3D=3D riscv_iommu_find_as) { + /* Allow multiple IOMMUs on the same PCIe bus, link known devices = */ + RISCVIOMMUState *last =3D (RISCVIOMMUState *)bus->iommu_opaque; + QLIST_INSERT_AFTER(last, iommu, iommus); + } else if (bus->iommu_ops =3D=3D NULL) { + pci_setup_iommu(bus, &riscv_iommu_ops, iommu); + } else { + error_setg(errp, "can't register secondary IOMMU for PCI bus #%d", + pci_bus_num(bus)); + } +} + +static int riscv_iommu_memory_region_index(IOMMUMemoryRegion *iommu_mr, + MemTxAttrs attrs) +{ + return attrs.unspecified ? RISCV_IOMMU_NOPASID : (int)attrs.pasid; +} + +static int riscv_iommu_memory_region_index_len(IOMMUMemoryRegion *iommu_mr) +{ + RISCVIOMMUSpace *as =3D container_of(iommu_mr, RISCVIOMMUSpace, iova_m= r); + return 1 << as->iommu->pasid_bits; +} + +static void riscv_iommu_memory_region_init(ObjectClass *klass, void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D riscv_iommu_memory_region_translate; + imrc->notify_flag_changed =3D riscv_iommu_memory_region_notify; + imrc->attrs_to_index =3D riscv_iommu_memory_region_index; + imrc->num_indexes =3D riscv_iommu_memory_region_index_len; +} + +static const TypeInfo riscv_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_RISCV_IOMMU_MEMORY_REGION, + .class_init =3D riscv_iommu_memory_region_init, +}; + +static void riscv_iommu_register_mr_types(void) +{ + type_register_static(&riscv_iommu_memory_region_info); + type_register_static(&riscv_iommu_info); +} + +type_init(riscv_iommu_register_mr_types); diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h new file mode 100644 index 0000000000..6f740de690 --- /dev/null +++ b/hw/riscv/riscv-iommu.h @@ -0,0 +1,141 @@ +/* + * QEMU emulation of an RISC-V IOMMU (Ziommu) + * + * Copyright (C) 2022-2023 Rivos Inc. + * + * 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. + * + * 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_RISCV_IOMMU_STATE_H +#define HW_RISCV_IOMMU_STATE_H + +#include "qemu/osdep.h" +#include "qom/object.h" + +#include "hw/riscv/iommu.h" + +struct RISCVIOMMUState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + uint32_t version; /* Reported interface version number */ + uint32_t pasid_bits; /* process identifier width */ + uint32_t bus; /* PCI bus mapping for non-root endpoints */ + + uint64_t cap; /* IOMMU supported capabilities */ + uint64_t fctl; /* IOMMU enabled features */ + + bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ + bool enable_msi; /* Enable MSI remapping */ + + /* IOMMU Internal State */ + uint64_t ddtp; /* Validated Device Directory Tree Root Pointer = */ + + dma_addr_t cq_addr; /* Command queue base physical address */ + dma_addr_t fq_addr; /* Fault/event queue base physical address */ + dma_addr_t pq_addr; /* Page request queue base physical address */ + + uint32_t cq_mask; /* Command queue index bit mask */ + uint32_t fq_mask; /* Fault/event queue index bit mask */ + uint32_t pq_mask; /* Page request queue index bit mask */ + + /* interrupt notifier */ + void (*notify)(RISCVIOMMUState *iommu, unsigned vector); + + /* IOMMU State Machine */ + QemuThread core_proc; /* Background processing thread */ + QemuMutex core_lock; /* Global IOMMU lock, used for cache/regs update= s */ + QemuCond core_cond; /* Background processing wake up signal */ + unsigned core_exec; /* Processing thread execution actions */ + + /* IOMMU target address space */ + AddressSpace *target_as; + MemoryRegion *target_mr; + + /* MSI / MRIF access trap */ + AddressSpace trap_as; + MemoryRegion trap_mr; + + GHashTable *ctx_cache; /* Device translation Context Cache */ + + /* MMIO Hardware Interface */ + MemoryRegion regs_mr; + QemuSpin regs_lock; + uint8_t *regs_rw; /* register state (user write) */ + uint8_t *regs_wc; /* write-1-to-clear mask */ + uint8_t *regs_ro; /* read-only mask */ + + QLIST_ENTRY(RISCVIOMMUState) iommus; + QLIST_HEAD(, RISCVIOMMUSpace) spaces; +}; + +void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, + Error **errp); + +/* private helpers */ + +/* Register helper functions */ +static inline uint32_t riscv_iommu_reg_mod32(RISCVIOMMUState *s, + unsigned idx, uint32_t set, uint32_t clr) +{ + uint32_t val; + qemu_spin_lock(&s->regs_lock); + val =3D ldl_le_p(s->regs_rw + idx); + stl_le_p(s->regs_rw + idx, (val & ~clr) | set); + qemu_spin_unlock(&s->regs_lock); + return val; +} + +static inline void riscv_iommu_reg_set32(RISCVIOMMUState *s, + unsigned idx, uint32_t set) +{ + qemu_spin_lock(&s->regs_lock); + stl_le_p(s->regs_rw + idx, set); + qemu_spin_unlock(&s->regs_lock); +} + +static inline uint32_t riscv_iommu_reg_get32(RISCVIOMMUState *s, + unsigned idx) +{ + return ldl_le_p(s->regs_rw + idx); +} + +static inline uint64_t riscv_iommu_reg_mod64(RISCVIOMMUState *s, + unsigned idx, uint64_t set, uint64_t clr) +{ + uint64_t val; + qemu_spin_lock(&s->regs_lock); + val =3D ldq_le_p(s->regs_rw + idx); + stq_le_p(s->regs_rw + idx, (val & ~clr) | set); + qemu_spin_unlock(&s->regs_lock); + return val; +} + +static inline void riscv_iommu_reg_set64(RISCVIOMMUState *s, + unsigned idx, uint64_t set) +{ + qemu_spin_lock(&s->regs_lock); + stq_le_p(s->regs_rw + idx, set); + qemu_spin_unlock(&s->regs_lock); +} + +static inline uint64_t riscv_iommu_reg_get64(RISCVIOMMUState *s, + unsigned idx) +{ + return ldq_le_p(s->regs_rw + idx); +} + + + +#endif diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events new file mode 100644 index 0000000000..42a97caffa --- /dev/null +++ b/hw/riscv/trace-events @@ -0,0 +1,11 @@ +# See documentation at docs/devel/tracing.rst + +# riscv-iommu.c +riscv_iommu_new(const char *id, unsigned b, unsigned d, unsigned f) "%s: d= evice attached %04x:%02x.%d" +riscv_iommu_flt(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t reason, uint64_t iova) "%s: fault %04x:%02x.%u reason: 0x%"PRIx64" iova:= 0x%"PRIx64 +riscv_iommu_pri(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t iova) "%s: page request %04x:%02x.%u iova: 0x%"PRIx64 +riscv_iommu_dma(const char *id, unsigned b, unsigned d, unsigned f, unsign= ed pasid, const char *dir, uint64_t iova, uint64_t phys) "%s: translate %04= x:%02x.%u #%u %s 0x%"PRIx64" -> 0x%"PRIx64 +riscv_iommu_msi(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t iova, uint64_t phys) "%s: translate %04x:%02x.%u MSI 0x%"PRIx64" -> 0x%"= PRIx64 +riscv_iommu_cmd(const char *id, uint64_t l, uint64_t u) "%s: command 0x%"P= RIx64" 0x%"PRIx64 +riscv_iommu_notifier_add(const char *id) "%s: dev-iotlb notifier added" +riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed" diff --git a/hw/riscv/trace.h b/hw/riscv/trace.h new file mode 100644 index 0000000000..b88504b750 --- /dev/null +++ b/hw/riscv/trace.h @@ -0,0 +1,2 @@ +#include "trace/trace-hw_riscv.h" + diff --git a/include/hw/riscv/iommu.h b/include/hw/riscv/iommu.h new file mode 100644 index 0000000000..403b365893 --- /dev/null +++ b/include/hw/riscv/iommu.h @@ -0,0 +1,36 @@ +/* + * QEMU emulation of an RISC-V IOMMU (Ziommu) + * + * Copyright (C) 2022-2023 Rivos Inc. + * + * 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. + * + * 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_RISCV_IOMMU_H +#define HW_RISCV_IOMMU_H + +#include "qemu/osdep.h" +#include "qom/object.h" + +#define TYPE_RISCV_IOMMU "riscv-iommu" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUState, RISCV_IOMMU) +typedef struct RISCVIOMMUState RISCVIOMMUState; + +#define TYPE_RISCV_IOMMU_MEMORY_REGION "riscv-iommu-mr" +typedef struct RISCVIOMMUSpace RISCVIOMMUSpace; + +#define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI) +typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci; + +#endif diff --git a/meson.build b/meson.build index c59ca496f2..75e56f3282 100644 --- a/meson.build +++ b/meson.build @@ -3361,6 +3361,7 @@ if have_system 'hw/rdma', 'hw/rdma/vmw', 'hw/rtc', + 'hw/riscv', 'hw/s390x', 'hw/scsi', 'hw/sd', --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827525; cv=none; d=zohomail.com; s=zohoarc; b=JLAYDipCLFg0LkasEmrL/8uf2Yl21P/cqAFDl0OCMrIck5JCLOdsMPjbSNaRX8SP31CG9JkTnme8N9awrnrYdpF4w0qSA+T6r+U+E5KtY0ezCL6HH42azIGvLbXF2NLnqovUZyAufngXEVP2YYwaQok1xVVuqFAz88iFN7EseAY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827525; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=IAg1rDO219B0kDzGhaIIF9NH0UHu1hVK1GbBMrUiUzU=; b=hTNdwm4D3dZEAM6idfxucc7TLmg1Cmstegcyn1NhIVFQRMQ3oVTM5IdikUeDxP4zMDEElQlrKyajcPkgwRriISKjsUa05JClzO3njSQEYEOhodb/j+qaneNcJf4zZ/2pAi+k6OLqajhAN48TEHtzCkLFlcW8+ZH83ADcalWgM2s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827525944709.6876625096355; Thu, 7 Mar 2024 08:05:25 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDu-0005GZ-4S; Thu, 07 Mar 2024 11:03:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDo-0005AV-N2 for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:52 -0500 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDk-0006CT-He for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:52 -0500 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-6e4d48a5823so797605b3a.1 for ; Thu, 07 Mar 2024 08:03:48 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827422; x=1710432222; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IAg1rDO219B0kDzGhaIIF9NH0UHu1hVK1GbBMrUiUzU=; b=fX6jwHNceaFy0yicTCPCIa1RX5wWGENqHIMXEJ1W0MhfQbbc1ItDe342dg8y4FPMD6 bMC+cdpPEGpJM3K4jMBdJSs+o7+9xOJhGXqAn7YkyXKI5LX8fVLqf9Z9U0lEaOSjox+2 L7jvVb+eBcs6PndMbDK6HdZxmRwtkYLz5AewDjQExVOwz75irIkTxWAJBKccJZmhrqRD UrPwRTdyiQwKjuMvYz2F1gMSxC3xOFvc2QZ1ccPqFM6AW88EmR21BlUCmPgAI76uJ7Ji rhundcouKsjrkW5xhZzJhsLwuw8998zO/zFEl4IAUAPAvjgNpg8cCX8EX8WTDUBQeJ+p Q9Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827422; x=1710432222; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IAg1rDO219B0kDzGhaIIF9NH0UHu1hVK1GbBMrUiUzU=; b=H5Ivc2kPomsucsFj6K++EUBqgiwhn9aoOtbSeUF9iDa1wKAaE4UXrIP6EoNPF8BX8N abMZsTL1lBJfW2vxBFlTBNYKdr2dzPQ9iVNUoDJ0R1kzQPMWkqCb7vThlI67KePz9ZK8 6il6f8j2CL7nYyU42eDa/COgQkS87S++B6fNWlkjWaxUce3o1Pel/IJcRpfdpAGVZwdB WbN8osBa5sPjorj8GpkH6pTFzCV6ydOfbVMBjhNrIg5OhUK0TU97p/JMfMb93tXoVus1 6rtFbqo3N7nwh38sjv3zHvyyDc2u57LU/9DfepmVP2+OMxUzEiMFsNFI0Lw+91S0Ce0W UG+w== X-Gm-Message-State: AOJu0YzbA5kmeXGsn5UfiF00W55zBlgnlwmUjHYt01viF95z+MIJp8Cb GWhQxmykaK4wTKR648uycBGo77hAgiEjSQJvJ22fZl0kAdyVvkJTYOiRrAyv5ImsguC8qvhFPWK Z X-Google-Smtp-Source: AGHT+IHCQ30en2mDJm3oNzhInfm/NhDYqSrN/qFS/5XakLhZjJmeW+FFiQSzI7WVAA2sLuW3riJ4OQ== X-Received: by 2002:a17:902:eb8a:b0:1dc:84ab:95d with SMTP id q10-20020a170902eb8a00b001dc84ab095dmr11706169plg.45.1709827422260; Thu, 07 Mar 2024 08:03:42 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 04/15] hw/riscv: add riscv-iommu-pci device Date: Thu, 7 Mar 2024 13:03:07 -0300 Message-ID: <20240307160319.675044-5-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=dbarboza@ventanamicro.com; helo=mail-pf1-x42c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827528240100001 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach The RISC-V IOMMU can be modelled as a PCIe device following the guidelines of the RISC-V IOMMU spec, chapter 7.1, "Integrating an IOMMU as a PCIe device". Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza --- hw/riscv/meson.build | 2 +- hw/riscv/riscv-iommu-pci.c | 173 +++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 hw/riscv/riscv-iommu-pci.c diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index ba9eebd605..4674cec6c4 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sif= ive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfs= oc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) -riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c')) +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', '= riscv-iommu-pci.c')) =20 hw_arch +=3D {'riscv': riscv_ss} diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c new file mode 100644 index 0000000000..4eb1057210 --- /dev/null +++ b/hw/riscv/riscv-iommu-pci.c @@ -0,0 +1,173 @@ +/* + * QEMU emulation of an RISC-V IOMMU (Ziommu) + * + * Copyright (C) 2022-2023 Rivos Inc. + * + * 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. + * + * 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/pci/msi.h" +#include "hw/pci/msix.h" +#include "hw/pci/pci_bus.h" +#include "hw/qdev-properties.h" +#include "hw/riscv/riscv_hart.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/host-utils.h" +#include "qom/object.h" + +#include "cpu_bits.h" +#include "riscv-iommu.h" +#include "riscv-iommu-bits.h" + +#ifndef PCI_VENDOR_ID_RIVOS +#define PCI_VENDOR_ID_RIVOS 0x1efd +#endif + +#ifndef PCI_DEVICE_ID_RIVOS_IOMMU +#define PCI_DEVICE_ID_RIVOS_IOMMU 0xedf1 +#endif + +/* RISC-V IOMMU PCI Device Emulation */ + +typedef struct RISCVIOMMUStatePci { + PCIDevice pci; /* Parent PCIe device state */ + MemoryRegion bar0; /* PCI BAR (including MSI-x config) */ + RISCVIOMMUState iommu; /* common IOMMU state */ +} RISCVIOMMUStatePci; + +/* interrupt delivery callback */ +static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector) +{ + RISCVIOMMUStatePci *s =3D container_of(iommu, RISCVIOMMUStatePci, iomm= u); + + if (msix_enabled(&(s->pci))) { + msix_notify(&(s->pci), vector); + } +} + +static void riscv_iommu_pci_realize(PCIDevice *dev, Error **errp) +{ + RISCVIOMMUStatePci *s =3D DO_UPCAST(RISCVIOMMUStatePci, pci, dev); + RISCVIOMMUState *iommu =3D &s->iommu; + Error *err =3D NULL; + + /* Set device id for trace / debug */ + DEVICE(iommu)->id =3D g_strdup_printf("%02x:%02x.%01x", + pci_dev_bus_num(dev), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + qdev_realize(DEVICE(iommu), NULL, errp); + + memory_region_init(&s->bar0, OBJECT(s), "riscv-iommu-bar0", + QEMU_ALIGN_UP(memory_region_size(&iommu->regs_mr), TARGET_PAGE_SIZ= E)); + memory_region_add_subregion(&s->bar0, 0, &iommu->regs_mr); + + pcie_endpoint_cap_init(dev, 0); + + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64, &s->bar0); + + int ret =3D msix_init(dev, RISCV_IOMMU_INTR_COUNT, + &s->bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG, + &s->bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG + 256, 0, = &err); + + if (ret =3D=3D -ENOTSUP) { + /* + * MSI-x is not supported by the platform. + * Driver should use timer/polling based notification handlers. + */ + warn_report_err(err); + } else if (ret < 0) { + error_propagate(errp, err); + return; + } else { + /* mark all allocated MSIx vectors as used. */ + msix_vector_use(dev, RISCV_IOMMU_INTR_CQ); + msix_vector_use(dev, RISCV_IOMMU_INTR_FQ); + msix_vector_use(dev, RISCV_IOMMU_INTR_PM); + msix_vector_use(dev, RISCV_IOMMU_INTR_PQ); + iommu->notify =3D riscv_iommu_pci_notify; + } + + PCIBus *bus =3D pci_device_root_bus(dev); + if (!bus) { + error_setg(errp, "can't find PCIe root port for %02x:%02x.%x", + pci_bus_num(pci_get_bus(dev)), PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + return; + } + + riscv_iommu_pci_setup_iommu(iommu, bus, errp); +} + +static void riscv_iommu_pci_exit(PCIDevice *pci_dev) +{ + pci_setup_iommu(pci_device_root_bus(pci_dev), NULL, NULL); +} + +static const VMStateDescription riscv_iommu_vmstate =3D { + .name =3D "riscv-iommu", + .unmigratable =3D 1 +}; + +static void riscv_iommu_pci_init(Object *obj) +{ + RISCVIOMMUStatePci *s =3D RISCV_IOMMU_PCI(obj); + RISCVIOMMUState *iommu =3D &s->iommu; + + object_initialize_child(obj, "iommu", iommu, TYPE_RISCV_IOMMU); + qdev_alias_all_properties(DEVICE(iommu), obj); +} + +static Property riscv_iommu_pci_properties[] =3D { + DEFINE_PROP_END_OF_LIST(), +}; + +static void riscv_iommu_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *k =3D PCI_DEVICE_CLASS(klass); + + k->realize =3D riscv_iommu_pci_realize; + k->exit =3D riscv_iommu_pci_exit; + k->vendor_id =3D PCI_VENDOR_ID_RIVOS; + k->device_id =3D PCI_DEVICE_ID_RIVOS_IOMMU; + k->revision =3D 0; + k->class_id =3D 0x0806; + dc->desc =3D "RISCV-IOMMU DMA Remapping device"; + dc->vmsd =3D &riscv_iommu_vmstate; + dc->hotpluggable =3D false; + dc->user_creatable =3D true; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + device_class_set_props(dc, riscv_iommu_pci_properties); +} + +static const TypeInfo riscv_iommu_pci =3D { + .name =3D TYPE_RISCV_IOMMU_PCI, + .parent =3D TYPE_PCI_DEVICE, + .class_init =3D riscv_iommu_pci_class_init, + .instance_init =3D riscv_iommu_pci_init, + .instance_size =3D sizeof(RISCVIOMMUStatePci), + .interfaces =3D (InterfaceInfo[]) { + { INTERFACE_PCIE_DEVICE }, + { }, + }, +}; + +static void riscv_iommu_register_pci_types(void) +{ + type_register_static(&riscv_iommu_pci); +} + +type_init(riscv_iommu_register_pci_types); --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827566; cv=none; d=zohomail.com; s=zohoarc; b=m7/ivfd83qWdMDyKQBIwocRBRxZdizuL6zpW6qev47ePdehJjKYrjYvbM6sblfq9wy9xL21q5XYxgeOzynXQAonSVfLfmgP6zZruiF+aTk0nStbeyVU4nG7EEWL6c6/nEx4WE1wXB3IHPbCoO42/cRLdNeWVVD6YY9hbg1G1SVw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827566; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=vhkJJXYBYc+DN7sMxGa2YG7Peqpq43f7HgOQhMshYT8=; b=Iug0yQzEHoOwUqlREBryIbsLOBavTc4f0AYhRzHl3kAi0TPBpvwayYcnRT2uQp8YFfdlMeKYLPP+a+t/+5l3gsMa4J0poeFSVKIOev62iWq0AbbF83kMkljX+INBLFzfKnkbfznyb0kvF0lVn0Zfx8pM6tzzFJfBhYmeM3t4SYc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827566141482.7550310588714; Thu, 7 Mar 2024 08:06:06 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDr-0005Ci-KL; Thu, 07 Mar 2024 11:03:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDo-0005AS-Lq for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:52 -0500 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDk-0006CN-7i for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:51 -0500 Received: by mail-pl1-x62e.google.com with SMTP id d9443c01a7336-1dcb3e6ff3fso8776955ad.2 for ; Thu, 07 Mar 2024 08:03:47 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827426; x=1710432226; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vhkJJXYBYc+DN7sMxGa2YG7Peqpq43f7HgOQhMshYT8=; b=NrOpMpOGXUCnKZrrL13h0A52R4I6cBwccGIeQe9nwSmq3QXBpwAnhvwXId8kOrJHOM tYhNoFocGsZflrtV8bV+MT2iEFwfPFccRzx0jmISBC/UZJoCLDNjgAau/bbxs6cChHmO +euurTsokR3sIXW18XxI9T12VrwOZkT7CjIPdtc2CalYs1mAUbcHGQh8m77PK1gZAXWR Ij6OeTUhU9yxx3ry8XcZon8s0xBbZv/n42Lk/09oWkvcut7QsU8STva9sX39a522yb2V SKmR4trt/mRP2JIJrMUXU2I37RLTUo3+WCSOhO4xY4U8Tm3jXjmZiXO7MhwDQZx2S+zW zLfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827426; x=1710432226; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vhkJJXYBYc+DN7sMxGa2YG7Peqpq43f7HgOQhMshYT8=; b=pi2Ucuzb0YF9POXT0Tn+kIIeaswhZyFRsm7dNdp/TYjqaI0+Cy+GQSHO92gTAsSxLG SQbVaLXBh2yEhsblMdC032wtefE/2kikji1IDI2pzWA8RorZLP6Tvtxo3pdL4PTXkTgk sVac7MiCOkvyU5K7mHeVPIQMiLzvFQi/geBo/XnoRhh/Q4bq97nnnIsAtNq+F1AUEfkS fUnlvE7X+cU9tTuBUhQG6OOLVMELzWOIGln2FljFre3xdQFBXmL1wwPvRppbZVd3mFBD y2FwqNOwsyDaj5rQIlreCZlDyXJZr917t61Qzw+8wzQsqd/3O+9kLCg2oQjBL17CFUVl 8C/Q== X-Gm-Message-State: AOJu0YzwuAkwrc8p5L/2noify2l1A7vyqQNZVX6RRApv7bwYjQXxsraF EQcLfPMTWEipH2MkTkrGfo8Oc5L4hqR2MBd+9nLMwCgcqgzOAQIP3BBKrb35eB6kNqjwmkNVSeV b X-Google-Smtp-Source: AGHT+IHvXzRLTMjy3t2Jpn9Ky44AhmCy8U5YGQdB2RHgyIBtuOqVkKKVsQT2V2YkYm9tlFWwRHNIhg== X-Received: by 2002:a17:902:c081:b0:1dc:a282:365f with SMTP id j1-20020a170902c08100b001dca282365fmr7817500pld.40.1709827425435; Thu, 07 Mar 2024 08:03:45 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 05/15] hw/riscv: add riscv-iommu-sys platform device Date: Thu, 7 Mar 2024 13:03:08 -0300 Message-ID: <20240307160319.675044-6-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62e; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827568423100005 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach This device models the RISC-V IOMMU as a sysbus device. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- hw/riscv/meson.build | 2 +- hw/riscv/riscv-iommu-sys.c | 93 ++++++++++++++++++++++++++++++++++++++ include/hw/riscv/iommu.h | 4 ++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 hw/riscv/riscv-iommu-sys.c diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 4674cec6c4..e37c5d78e2 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sif= ive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfs= oc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) -riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', '= riscv-iommu-pci.c')) +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', '= riscv-iommu-pci.c', 'riscv-iommu-sys.c')) =20 hw_arch +=3D {'riscv': riscv_ss} diff --git a/hw/riscv/riscv-iommu-sys.c b/hw/riscv/riscv-iommu-sys.c new file mode 100644 index 0000000000..4305cf8d79 --- /dev/null +++ b/hw/riscv/riscv-iommu-sys.c @@ -0,0 +1,93 @@ +/* + * QEMU emulation of an RISC-V IOMMU (Ziommu) - Platform Device + * + * Copyright (C) 2022-2023 Rivos Inc. + * + * 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. + * + * 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/pci/pci_bus.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "qapi/error.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/host-utils.h" +#include "qemu/module.h" +#include "qemu/osdep.h" +#include "qom/object.h" + +#include "riscv-iommu.h" + +/* RISC-V IOMMU System Platform Device Emulation */ + +struct RISCVIOMMUStateSys { + SysBusDevice parent; + uint64_t addr; + RISCVIOMMUState iommu; +}; + +static void riscv_iommu_sys_realize(DeviceState *dev, Error **errp) +{ + RISCVIOMMUStateSys *s =3D RISCV_IOMMU_SYS(dev); + PCIBus *pci_bus; + + qdev_realize(DEVICE(&s->iommu), NULL, errp); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iommu.regs_mr); + if (s->addr) { + sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, s->addr); + } + + pci_bus =3D (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL= ); + if (pci_bus) { + riscv_iommu_pci_setup_iommu(&s->iommu, pci_bus, errp); + } +} + +static void riscv_iommu_sys_init(Object *obj) +{ + RISCVIOMMUStateSys *s =3D RISCV_IOMMU_SYS(obj); + RISCVIOMMUState *iommu =3D &s->iommu; + + object_initialize_child(obj, "iommu", iommu, TYPE_RISCV_IOMMU); + qdev_alias_all_properties(DEVICE(iommu), obj); +} + +static Property riscv_iommu_sys_properties[] =3D { + DEFINE_PROP_UINT64("addr", RISCVIOMMUStateSys, addr, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void riscv_iommu_sys_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + dc->realize =3D riscv_iommu_sys_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + device_class_set_props(dc, riscv_iommu_sys_properties); +} + +static const TypeInfo riscv_iommu_sys =3D { + .name =3D TYPE_RISCV_IOMMU_SYS, + .parent =3D TYPE_SYS_BUS_DEVICE, + .class_init =3D riscv_iommu_sys_class_init, + .instance_init =3D riscv_iommu_sys_init, + .instance_size =3D sizeof(RISCVIOMMUStateSys), +}; + +static void riscv_iommu_register_sys(void) +{ + type_register_static(&riscv_iommu_sys); +} + +type_init(riscv_iommu_register_sys) diff --git a/include/hw/riscv/iommu.h b/include/hw/riscv/iommu.h index 403b365893..c8d28a79a1 100644 --- a/include/hw/riscv/iommu.h +++ b/include/hw/riscv/iommu.h @@ -33,4 +33,8 @@ typedef struct RISCVIOMMUSpace RISCVIOMMUSpace; OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI) typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci; =20 +#define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS) +typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys; + #endif --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827517; cv=none; d=zohomail.com; s=zohoarc; b=CB2tr8q9/zgIriwkReRRwl/EugTm2eJjF1OhLT/+5wgIFBcIZu9XnAYVc7klrB24odDecEDPe9b1pkZUASZEZ0+Vv6Fd0DUDVuB4+nPyYrcZ8yzpaMqfXtj4co2IlADFVex1OL6yL83CV3P7sbZsxMAYo5HUWpbXa6hd80dL7Yk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827517; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=9qRmnU76/UCmmp+A+boOm+CPDeqxgW4n/Bjq20j2Tb8=; b=YCwb48MhKGaAWmO3PXH4sLYRSGWH/IwBXVW+JSji02/ym1pZjzAdZF/IW0U4MI34athSNjqoHPDxXVs0CXVB2DjN7bYgZHos3I/yRz6KVUUGY1ZDKbgrJYlxF71EpvYqnrbIQg60BQHiFmanofE+ZaM5ZVITepiB4j3GCjqqryU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827517146959.1831730025032; Thu, 7 Mar 2024 08:05:17 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDt-0005DS-JC; Thu, 07 Mar 2024 11:03:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDp-0005Bs-Vm for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:54 -0500 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDn-0006DH-Ft for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:53 -0500 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-1dcab44747bso8775595ad.1 for ; Thu, 07 Mar 2024 08:03:49 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827428; x=1710432228; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9qRmnU76/UCmmp+A+boOm+CPDeqxgW4n/Bjq20j2Tb8=; b=l4mHtViy85Of523V9Cvrw0NaIZDUdU2SmVTtcyqajV9s31VBdIHiumuywgw1TiR4w4 ky4q5gfb5qlxI2pT3UYnxnDJ9ORbXefF+O9hUw/E8oJQ+pAx5a5aHq+/Yy0UK3rlktVE Q0hiq8S4szcbkVlfDRDp22qUSfe99qernoenb8kqlWussZCaHXRvR/lQPgcmDDWKSz2M Tv8wEr7X3v1mSbIXM1bJOC69Qc1f1T548dFtwzQRrL8dRsyG63jjZR/By3rW0Q1zyJGf aDntmh5Osu3sOYtu9EBE/FrC4BkkuiX4lcikcDBVAw/kRZBXMy9C2/JBqNsZA9bPIXM9 VGJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827428; x=1710432228; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9qRmnU76/UCmmp+A+boOm+CPDeqxgW4n/Bjq20j2Tb8=; b=Gu9+t35z57MGkAWohx73fpmSdOy8XtYKfw4BD60wYHvT9ichXf25r//3WBt6yYqLkq D7DOpoYZaEaineeA1DT2/hZdisOXCqrrDT48sluuSYcHW29/IOmjmQ/BXn7ZpAbBXNfH 0iNfM9oOa2PuodNS6hr8UrqnEnP+c/cO6h69+MjB3KcxQwjnVu3vEnAtYtlAxHINYjNF yzwFoghER7CRe60UDpRBiJ6j+q5kXSjECTvpqLaSXGdpK7Tej+yZpPJYSxtHk9Sc5TT+ iDFBii/B5+fY8EUHnYaGPBDWbwFJ0kswzw7RFJgSggVUV+XPDI03Lo7Q7dNv7qnSc/Pc 6azg== X-Gm-Message-State: AOJu0YwljFwhhxKGBIqozjaG/nH/IvB2OvQSyOycQm3hdf7jN6yu+t/8 orGEK2l6SAoYK8nSPIsO0DgncBDl/6wPbhsMz1oCTH6iYXlSxyp4FUlIORqReRv3V9CAaPICInH A X-Google-Smtp-Source: AGHT+IEQXFJxW2qiw239mRIxAT9uV5fFqfLPoC/vALE7OVlVWjokmyK2bDy3uQjKOcw2OR42WPf6/w== X-Received: by 2002:a17:902:7c0f:b0:1dc:ce55:e6fa with SMTP id x15-20020a1709027c0f00b001dcce55e6famr7265302pll.29.1709827428550; Thu, 07 Mar 2024 08:03:48 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 06/15] hw/riscv/virt.c: support for RISC-V IOMMU PCIDevice hotplug Date: Thu, 7 Mar 2024 13:03:09 -0300 Message-ID: <20240307160319.675044-7-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x634.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827517958100001 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Generate device tree entry for riscv-iommu PCI device, along with mapping all PCI device identifiers to the single IOMMU device instance. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- hw/riscv/virt.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index a094af97c3..67a8267747 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -32,6 +32,7 @@ #include "hw/core/sysbus-fdt.h" #include "target/riscv/pmu.h" #include "hw/riscv/riscv_hart.h" +#include "hw/riscv/iommu.h" #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" @@ -1004,6 +1005,30 @@ static void create_fdt_virtio_iommu(RISCVVirtState *= s, uint16_t bdf) bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf); } =20 +static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf) +{ + const char comp[] =3D "riscv,pci-iommu"; + void *fdt =3D MACHINE(s)->fdt; + uint32_t iommu_phandle; + g_autofree char *iommu_node =3D NULL; + g_autofree char *pci_node =3D NULL; + + pci_node =3D g_strdup_printf("/soc/pci@%lx", + (long) virt_memmap[VIRT_PCIE_ECAM].base); + iommu_node =3D g_strdup_printf("%s/iommu@%x", pci_node, bdf); + iommu_phandle =3D qemu_fdt_alloc_phandle(fdt); + qemu_fdt_add_subnode(fdt, iommu_node); + + qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp)); + qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1); + qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle); + qemu_fdt_setprop_cells(fdt, iommu_node, "reg", + bdf << 8, 0, 0, 0, 0); + qemu_fdt_setprop_cells(fdt, pci_node, "iommu-map", + 0, iommu_phandle, 0, bdf, + bdf + 1, iommu_phandle, bdf + 1, 0xffff - bdf); +} + static void finalize_fdt(RISCVVirtState *s) { uint32_t phandle =3D 1, irq_mmio_phandle =3D 1, msi_pcie_phandle =3D 1; @@ -1712,9 +1737,11 @@ static HotplugHandler *virt_machine_get_hotplug_hand= ler(MachineState *machine, MachineClass *mc =3D MACHINE_GET_CLASS(machine); =20 if (device_is_dynamic_sysbus(mc, dev) || - object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) || + object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) { return HOTPLUG_HANDLER(machine); } + return NULL; } =20 @@ -1735,6 +1762,10 @@ static void virt_machine_device_plug_cb(HotplugHandl= er *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { create_fdt_virtio_iommu(s, pci_get_bdf(PCI_DEVICE(dev))); } + + if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) { + create_fdt_iommu(s, pci_get_bdf(PCI_DEVICE(dev))); + } } =20 static void virt_machine_class_init(ObjectClass *oc, void *data) --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827494; cv=none; d=zohomail.com; s=zohoarc; b=T+LVuCDceqkFM57plPuzITmilYlEvE6rwUEW3dDlyzoxTzjIK2thp2fkcAx9YJQGSe01zU6y12GQg8hwvqKDS5igvemxII5COtIm4v1FCR2bFYygMoK6ga4YLe2VHOzVB7A2KR16Jf/oHkkSVvIxnMPJaIC7sBhZT+pwEXS7l5E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827494; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KLo75RFNZf+AAEHs9/Y6byV6ou2OhX+ofhVXr0PVmoc=; b=NhaclzWVDhMeoYnA4vo1OGnpGIW3aF4gjDDixtstEXxFKF8cb1nBPJMaVXqrcXilEfeogLtx8RSGiaVnz+9Po5nAI3YwY+hFNEE8AiUj4ViXgGpa82YBSL+6XvIN4ojo/Q96dbIS/F31kEGWQhbZcXKP2jRy/IgkiVruCCOuIEM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827494217512.670463840255; Thu, 7 Mar 2024 08:04:54 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDy-0005KL-MP; Thu, 07 Mar 2024 11:04:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDs-0005Dg-4I for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:57 -0500 Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDq-0006Ey-1F for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:55 -0500 Received: by mail-pg1-x536.google.com with SMTP id 41be03b00d2f7-53fbf2c42bfso807091a12.3 for ; Thu, 07 Mar 2024 08:03:53 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827432; x=1710432232; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KLo75RFNZf+AAEHs9/Y6byV6ou2OhX+ofhVXr0PVmoc=; b=ew3FZniBsA4fsOwhDNNWMQxt8rHpYvKXTD53vy9fCJ/d3tuszkN6cFV+WObzA0icaH xcXx4enTSzLxJf99dFZl5paEHh/N9BAvKc412lOEprEJj2MMik16lGON4mESceALLNDN YUzXog27mNMa0AC3TZkejswBn9teIu6F2AzXz2fpgmRllILFdnQ7JFr+4gPmgZfgCni3 quwAjQVZtfvwJPf4iUz5LdP9eNbSmdeGxAR+E745w/ptrfN0xKAE7zHYXwJLIcfj1PqF Jd/oBdGwW5katY6T3nlwJHAQ+HAOrUDTUhvoGkN8qkPzvYDGEWyd8E2d24m0V3+28TBf l3yQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827432; x=1710432232; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KLo75RFNZf+AAEHs9/Y6byV6ou2OhX+ofhVXr0PVmoc=; b=HRdoMtvPiaZc99Btk4Xiz/1dkCz+qWO9bgz4yqj9fQxTloQPhO/pGEY7fT9dK8DtNi 8GU40rGWePETSzUR+nexsOwCGQglMOmBaYk4+Dd/LnT2cfbU62N9OnzaxIN4jnG+mDCW 2qpwDmm4ozP1fMC1lSTSnc/wkkfjoWZDgTJiTVni9vvryGvpY7DWpUofPmejpKHrPXjP bske4XlHvC9q7/vCYKRwdrolt3KdriaPO/XgKXlPMJ2Jlr5Fhq4gOCSyCDJX6A3npve0 erEMlpwADwPnM5nT0GVFHym6a1WNRmJWzLifqXy55eMUTOx1YBFLGr8V8FByiV6qcb0Q JSVw== X-Gm-Message-State: AOJu0YyycKdNLqy03cqJW3IWvCqzgDPWddEUZzbNtD8hL8tBWcUxQnXC jegCKRkuQbVCJ33fcSI/Od8dPTY3c4hdVeBPtC9YhO1JdcMcxNCB80/p9AMYclWwWBy4LaH2byc 4 X-Google-Smtp-Source: AGHT+IFZmqtYkWjeFnBiNWz/D9wjVsqnr5u7r0z954JMR79a+c79TUUOSy6xgBsAiGCtM/ZPFdKC+A== X-Received: by 2002:a17:902:720c:b0:1dc:cf38:3a77 with SMTP id ba12-20020a170902720c00b001dccf383a77mr7311805plb.55.1709827431741; Thu, 07 Mar 2024 08:03:51 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 07/15] test/qtest: add riscv-iommu-pci tests Date: Thu, 7 Mar 2024 13:03:10 -0300 Message-ID: <20240307160319.675044-8-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::536; envelope-from=dbarboza@ventanamicro.com; helo=mail-pg1-x536.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827496004100001 Content-Type: text/plain; charset="utf-8" To test the RISC-V IOMMU emulation we'll use its PCI representation. Create a new 'riscv-iommu-pci' libqos device that will be present with CONFIG_RISCV_IOMMU. This config is only available for RISC-V, so this device will only be consumed by the RISC-V libqos machine. Start with basic tests: a PCI sanity check and a reset state register test. The reset test was taken from the RISC-V IOMMU spec chapter 5.2, "Reset behavior". More tests will be added later. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- tests/qtest/libqos/meson.build | 4 ++ tests/qtest/libqos/riscv-iommu.c | 79 +++++++++++++++++++++++++++ tests/qtest/libqos/riscv-iommu.h | 67 +++++++++++++++++++++++ tests/qtest/meson.build | 1 + tests/qtest/riscv-iommu-test.c | 93 ++++++++++++++++++++++++++++++++ 5 files changed, 244 insertions(+) create mode 100644 tests/qtest/libqos/riscv-iommu.c create mode 100644 tests/qtest/libqos/riscv-iommu.h create mode 100644 tests/qtest/riscv-iommu-test.c diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index 3aed6efcb8..07fe20eacb 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -67,6 +67,10 @@ if have_virtfs libqos_srcs +=3D files('virtio-9p.c', 'virtio-9p-client.c') endif =20 +if config_all_devices.has_key('CONFIG_RISCV_IOMMU') + libqos_srcs +=3D files('riscv-iommu.c') +endif + libqos =3D static_library('qos', libqos_srcs + genh, name_suffix: 'fa', build_by_default: false) diff --git a/tests/qtest/libqos/riscv-iommu.c b/tests/qtest/libqos/riscv-io= mmu.c new file mode 100644 index 0000000000..8ae7d4888c --- /dev/null +++ b/tests/qtest/libqos/riscv-iommu.c @@ -0,0 +1,79 @@ +/* + * libqos driver riscv-iommu-pci framework + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at = your + * option) any later version. See the COPYING file in the top-level direc= tory. + * + */ + +#include "qemu/osdep.h" +#include "../libqtest.h" +#include "qemu/module.h" +#include "qgraph.h" +#include "pci.h" +#include "riscv-iommu.h" + +#define PCI_VENDOR_ID_RIVOS 0x1efd +#define PCI_DEVICE_ID_RIVOS_IOMMU 0xedf1 + +static void *riscv_iommu_pci_get_driver(void *obj, const char *interface) +{ + QRISCVIOMMU *r_iommu_pci =3D obj; + + if (!g_strcmp0(interface, "pci-device")) { + return &r_iommu_pci->dev; + } + + fprintf(stderr, "%s not present in riscv_iommu_pci\n", interface); + g_assert_not_reached(); +} + +static void riscv_iommu_pci_start_hw(QOSGraphObject *obj) +{ + QRISCVIOMMU *pci =3D (QRISCVIOMMU *)obj; + qpci_device_enable(&pci->dev); +} + +static void riscv_iommu_pci_destructor(QOSGraphObject *obj) +{ + QRISCVIOMMU *pci =3D (QRISCVIOMMU *)obj; + qpci_iounmap(&pci->dev, pci->reg_bar); +} + +static void *riscv_iommu_pci_create(void *pci_bus, QGuestAllocator *alloc, + void *addr) +{ + QRISCVIOMMU *r_iommu_pci =3D g_new0(QRISCVIOMMU, 1); + QPCIBus *bus =3D pci_bus; + + qpci_device_init(&r_iommu_pci->dev, bus, addr); + r_iommu_pci->reg_bar =3D qpci_iomap(&r_iommu_pci->dev, 0, NULL); + + r_iommu_pci->obj.get_driver =3D riscv_iommu_pci_get_driver; + r_iommu_pci->obj.start_hw =3D riscv_iommu_pci_start_hw; + r_iommu_pci->obj.destructor =3D riscv_iommu_pci_destructor; + return &r_iommu_pci->obj; +} + +static void riscv_iommu_pci_register_nodes(void) +{ + QPCIAddress addr =3D { + .vendor_id =3D PCI_VENDOR_ID_RIVOS, + .device_id =3D PCI_DEVICE_ID_RIVOS_IOMMU, + .devfn =3D QPCI_DEVFN(1, 0), + }; + + QOSGraphEdgeOptions opts =3D { + .extra_device_opts =3D "addr=3D01.0", + }; + + add_qpci_address(&opts, &addr); + + qos_node_create_driver("riscv-iommu-pci", riscv_iommu_pci_create); + qos_node_produces("riscv-iommu-pci", "pci-device"); + qos_node_consumes("riscv-iommu-pci", "pci-bus", &opts); +} + +libqos_init(riscv_iommu_pci_register_nodes); diff --git a/tests/qtest/libqos/riscv-iommu.h b/tests/qtest/libqos/riscv-io= mmu.h new file mode 100644 index 0000000000..8c056caa7b --- /dev/null +++ b/tests/qtest/libqos/riscv-iommu.h @@ -0,0 +1,67 @@ +/* + * libqos driver riscv-iommu-pci framework + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at = your + * option) any later version. See the COPYING file in the top-level direc= tory. + * + */ + +#ifndef TESTS_LIBQOS_RISCV_IOMMU_H +#define TESTS_LIBQOS_RISCV_IOMMU_H + +#include "qgraph.h" +#include "pci.h" +#include "qemu/bitops.h" + +#ifndef GENMASK_ULL +#define GENMASK_ULL(h, l) (((~0ULL) >> (63 - (h) + (l))) << (l)) +#endif + +#define RISCV_IOMMU_PCI_VENDOR_ID_RIVOS 0x1efd +#define RISCV_IOMMU_PCI_DEVICE_ID_RIVOS 0xedf1 +#define RISCV_IOMMU_PCI_DEVICE_CLASS 0x0806 + +/* Common field positions */ +#define RISCV_IOMMU_QUEUE_ENABLE BIT(0) +#define RISCV_IOMMU_QUEUE_INTR_ENABLE BIT(1) +#define RISCV_IOMMU_QUEUE_MEM_FAULT BIT(8) +#define RISCV_IOMMU_QUEUE_ACTIVE BIT(16) +#define RISCV_IOMMU_QUEUE_BUSY BIT(17) + +#define RISCV_IOMMU_REG_CAP 0x0000 +#define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0) + +#define RISCV_IOMMU_REG_DDTP 0x0010 +#define RISCV_IOMMU_DDTP_BUSY BIT_ULL(4) +#define RISCV_IOMMU_DDTP_MODE GENMASK_ULL(3, 0) +#define RISCV_IOMMU_DDTP_MODE_OFF 0 + +#define RISCV_IOMMU_REG_CQCSR 0x0048 +#define RISCV_IOMMU_CQCSR_CQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_CQCSR_CIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_CQCSR_CQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_CQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +#define RISCV_IOMMU_REG_FQCSR 0x004C +#define RISCV_IOMMU_FQCSR_FQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_FQCSR_FIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_FQCSR_FQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_FQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +#define RISCV_IOMMU_REG_PQCSR 0x0050 +#define RISCV_IOMMU_PQCSR_PQEN RISCV_IOMMU_QUEUE_ENABLE +#define RISCV_IOMMU_PQCSR_PIE RISCV_IOMMU_QUEUE_INTR_ENABLE +#define RISCV_IOMMU_PQCSR_PQON RISCV_IOMMU_QUEUE_ACTIVE +#define RISCV_IOMMU_PQCSR_BUSY RISCV_IOMMU_QUEUE_BUSY + +#define RISCV_IOMMU_REG_IPSR 0x0054 + +typedef struct QRISCVIOMMU { + QOSGraphObject obj; + QPCIDevice dev; + QPCIBar reg_bar; +} QRISCVIOMMU; + +#endif diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 31b9f4ede4..aeb7346840 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -285,6 +285,7 @@ qos_test_ss.add( 'vmxnet3-test.c', 'igb-test.c', 'ufs-test.c', + 'riscv-iommu-test.c', ) =20 if config_all_devices.has_key('CONFIG_VIRTIO_SERIAL') diff --git a/tests/qtest/riscv-iommu-test.c b/tests/qtest/riscv-iommu-test.c new file mode 100644 index 0000000000..13b887d15e --- /dev/null +++ b/tests/qtest/riscv-iommu-test.c @@ -0,0 +1,93 @@ +/* + * QTest testcase for RISC-V IOMMU + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at = your + * option) any later version. See the COPYING file in the top-level direc= tory. + * + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" +#include "qemu/module.h" +#include "libqos/qgraph.h" +#include "libqos/riscv-iommu.h" +#include "hw/pci/pci_regs.h" + +static uint32_t riscv_iommu_read_reg32(QRISCVIOMMU *r_iommu, int reg_offse= t) +{ + uint32_t reg; + + qpci_memread(&r_iommu->dev, r_iommu->reg_bar, reg_offset, + ®, sizeof(reg)); + return reg; +} + +static uint64_t riscv_iommu_read_reg64(QRISCVIOMMU *r_iommu, int reg_offse= t) +{ + uint64_t reg; + + qpci_memread(&r_iommu->dev, r_iommu->reg_bar, reg_offset, + ®, sizeof(reg)); + return reg; +} + +static void test_pci_config(void *obj, void *data, QGuestAllocator *t_allo= c) +{ + QRISCVIOMMU *r_iommu =3D obj; + QPCIDevice *dev =3D &r_iommu->dev; + uint16_t vendorid, deviceid, classid; + + vendorid =3D qpci_config_readw(dev, PCI_VENDOR_ID); + deviceid =3D qpci_config_readw(dev, PCI_DEVICE_ID); + classid =3D qpci_config_readw(dev, PCI_CLASS_DEVICE); + + g_assert_cmpuint(vendorid, =3D=3D, RISCV_IOMMU_PCI_VENDOR_ID_RIVOS); + g_assert_cmpuint(deviceid, =3D=3D, RISCV_IOMMU_PCI_DEVICE_ID_RIVOS); + g_assert_cmpuint(classid, =3D=3D, RISCV_IOMMU_PCI_DEVICE_CLASS); +} + +static void test_reg_reset(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QRISCVIOMMU *r_iommu =3D obj; + uint64_t cap; + uint32_t reg; + + cap =3D riscv_iommu_read_reg64(r_iommu, RISCV_IOMMU_REG_CAP); + g_assert_cmpuint(cap & RISCV_IOMMU_CAP_VERSION, =3D=3D, 0x10); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_CQCSR); + g_assert_cmpuint(reg & RISCV_IOMMU_CQCSR_CQEN, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_CQCSR_CIE, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_CQCSR_CQON, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_CQCSR_BUSY, =3D=3D, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_FQCSR); + g_assert_cmpuint(reg & RISCV_IOMMU_FQCSR_FQEN, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_FQCSR_FIE, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_FQCSR_FQON, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_FQCSR_BUSY, =3D=3D, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_PQCSR); + g_assert_cmpuint(reg & RISCV_IOMMU_PQCSR_PQEN, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_PQCSR_PIE, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_PQCSR_PQON, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_PQCSR_BUSY, =3D=3D, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_DDTP); + g_assert_cmpuint(reg & RISCV_IOMMU_DDTP_BUSY, =3D=3D, 0); + g_assert_cmpuint(reg & RISCV_IOMMU_DDTP_MODE, =3D=3D, + RISCV_IOMMU_DDTP_MODE_OFF); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_IPSR); + g_assert_cmpuint(reg, =3D=3D, 0); +} + +static void register_riscv_iommu_test(void) +{ + qos_add_test("pci_config", "riscv-iommu-pci", test_pci_config, NULL); + qos_add_test("reg_reset", "riscv-iommu-pci", test_reg_reset, NULL); +} + +libqos_init(register_riscv_iommu_test); --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827816; cv=none; d=zohomail.com; s=zohoarc; b=UkMTzJU9qE+3qp/Ec79lH0985LXGIp2JqTriynHr7DwCy+r0QZy+pdaG8F15eSU4wUmhoo2U/gYQDc5y4lYHXA7f5Q7P4kya8THTxtXeRAe6dxNK69NvVGSpOPq8sAIQc0cQI1GovId2B58+RRoq6Y8GNGx3xk35Vl4ErzQzp/M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827816; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=W6XmQECwl+p49vDAdPSAJcyJQQZerr475rOdlfge4lM=; b=h+azYAjkGFSGyzSMiW8j6bSRvTIhk0eiFOSWk1BvcPowSN3n9Nlhi+hL5m+HEJNXiPvHvnKGOIH6E8UGetPq7/1wY5L1xDnK7AGQBRa5cV0j2fcKwKMNfZKq8w1S5xkNj+EwH5XV6GfJcwrLs6EK8LLxSyUHs8eUHZUvU0y+Ls0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827816201781.3036967380231; Thu, 7 Mar 2024 08:10:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGDx-0005JT-DM; Thu, 07 Mar 2024 11:04:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDv-0005HQ-LE for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:59 -0500 Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDs-0006G3-Hm for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:03:59 -0500 Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-1dca160163dso9969215ad.3 for ; Thu, 07 Mar 2024 08:03:56 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827435; x=1710432235; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=W6XmQECwl+p49vDAdPSAJcyJQQZerr475rOdlfge4lM=; b=JeCW+fTThz1cdolYLjyn5SMmsfIdJqt7Oln7YaHmyOLu0aTtI7leKah8P5hyYpR91O w64g4UTGDlWVJjBCg9j/h7FCKnjJ+bp/ugu0F8AtryCUR+av+XvJpqWEmhTI6xN88yoy 5kCXYN1/DMOG08flZnupkLFrrjBmYBL4K2udJXfDX4PZLocldgGFlxvLGJW95lQPoXwc TWTxqzmAHjuHRpzEdwTFi+qmBNx3X06an0kzjT33nB5aknED4GHYtwPtZh0Rw370pwCU 1FjvzbWrVSO3u5N0zx2M/hewZ050nyPNPpar1EeajzeBdw+jAhI9An3dxbKaDfqiueWZ g0Cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827435; x=1710432235; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W6XmQECwl+p49vDAdPSAJcyJQQZerr475rOdlfge4lM=; b=wfA2e3ocCRugRb3DXvt6a/8tgiSje+r7m5lkIphZnBAqAGmfHQwGhDX6HFF4JPd23j 4vCLhKgLDmfrc5c3XCwUXyP7XgPjSHgKF9uhSOLKLtgbbunSouK2t85CApoDjFCVDCyW Lvzp9cl7UevB6Cbvr2HLpuZbwuwBqyl/mDFYH2TFSKrIu4g027ih3Nv9faZPKNph7t2A v4lYCcsnkouhAWuL8CAc9+2qvdtmZZtjIoC+hdZlkKrIQwW2INYi5Ff05cHzA5vVsAiz VUuEW2iMEVoNWq7hbTFZjRZThJ2suAQgYXL+gXCp67dR/cbXLALenQZweALjhCGSO89j iz7Q== X-Gm-Message-State: AOJu0YxPCSZEa1XDEHuRfgfM3LEMpHea4VuxsV8ZKqZq5qrgg1wZrp5U pCXR2ROmwfl7bhCXzgxYP7ZyDU1w75UBjmv+Fdjq6DsMljJHJrFq3thrJXvsr63t5/271cuVxxl w X-Google-Smtp-Source: AGHT+IGwJ5+iGqDrQWLuc1lpCB9X91birSUNfs6pOBODgpOfJbc0dTKx/pHFb0xU6jOklEaPbIr2Eg== X-Received: by 2002:a17:903:41c2:b0:1dc:ccd3:29e5 with SMTP id u2-20020a17090341c200b001dcccd329e5mr10887503ple.2.1709827434881; Thu, 07 Mar 2024 08:03:54 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 08/15] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC) Date: Thu, 7 Mar 2024 13:03:11 -0300 Message-ID: <20240307160319.675044-9-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::636; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x636.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827817771100002 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach The RISC-V IOMMU spec predicts that the IOMMU can use translation caches to hold entries from the DDT. This includes implementation for all cache commands that are marked as 'not implemented'. There are some artifacts included in the cache that predicts s-stage and g-stage elements, although we don't support it yet. We'll introduce them next. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- hw/riscv/riscv-iommu.c | 190 ++++++++++++++++++++++++++++++++++++++++- hw/riscv/riscv-iommu.h | 2 + 2 files changed, 188 insertions(+), 4 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index df534b99b0..0b93146327 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -63,6 +63,16 @@ struct RISCVIOMMUContext { uint64_t msiptp; /* MSI redirection page table pointer */ }; =20 +/* Address translation cache entry */ +struct RISCVIOMMUEntry { + uint64_t iova:44; /* IOVA Page Number */ + uint64_t pscid:20; /* Process Soft-Context identifier */ + uint64_t phys:44; /* Physical Page Number */ + uint64_t gscid:16; /* Guest Soft-Context identifier */ + uint64_t perm:2; /* IOMMU_RW flags */ + uint64_t __rfu:2; +}; + /* IOMMU index for transactions without PASID specified. */ #define RISCV_IOMMU_NOPASID 0 =20 @@ -629,14 +639,127 @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUSta= te *s, uint32_t devid) return &as->iova_as; } =20 +/* Translation Object cache support */ +static gboolean __iot_equal(gconstpointer v1, gconstpointer v2) +{ + RISCVIOMMUEntry *t1 =3D (RISCVIOMMUEntry *) v1; + RISCVIOMMUEntry *t2 =3D (RISCVIOMMUEntry *) v2; + return t1->gscid =3D=3D t2->gscid && t1->pscid =3D=3D t2->pscid && + t1->iova =3D=3D t2->iova; +} + +static guint __iot_hash(gconstpointer v) +{ + RISCVIOMMUEntry *t =3D (RISCVIOMMUEntry *) v; + return (guint)t->iova; +} + +/* GV: 1 PSCV: 1 AV: 1 */ +static void __iot_inval_pscid_iova(gpointer key, gpointer value, gpointer = data) +{ + RISCVIOMMUEntry *iot =3D (RISCVIOMMUEntry *) value; + RISCVIOMMUEntry *arg =3D (RISCVIOMMUEntry *) data; + if (iot->gscid =3D=3D arg->gscid && + iot->pscid =3D=3D arg->pscid && + iot->iova =3D=3D arg->iova) { + iot->perm =3D 0; + } +} + +/* GV: 1 PSCV: 1 AV: 0 */ +static void __iot_inval_pscid(gpointer key, gpointer value, gpointer data) +{ + RISCVIOMMUEntry *iot =3D (RISCVIOMMUEntry *) value; + RISCVIOMMUEntry *arg =3D (RISCVIOMMUEntry *) data; + if (iot->gscid =3D=3D arg->gscid && + iot->pscid =3D=3D arg->pscid) { + iot->perm =3D 0; + } +} + +/* GV: 1 GVMA: 1 */ +static void __iot_inval_gscid_gpa(gpointer key, gpointer value, gpointer d= ata) +{ + RISCVIOMMUEntry *iot =3D (RISCVIOMMUEntry *) value; + RISCVIOMMUEntry *arg =3D (RISCVIOMMUEntry *) data; + if (iot->gscid =3D=3D arg->gscid) { + /* simplified cache, no GPA matching */ + iot->perm =3D 0; + } +} + +/* GV: 1 GVMA: 0 */ +static void __iot_inval_gscid(gpointer key, gpointer value, gpointer data) +{ + RISCVIOMMUEntry *iot =3D (RISCVIOMMUEntry *) value; + RISCVIOMMUEntry *arg =3D (RISCVIOMMUEntry *) data; + if (iot->gscid =3D=3D arg->gscid) { + iot->perm =3D 0; + } +} + +/* GV: 0 */ +static void __iot_inval_all(gpointer key, gpointer value, gpointer data) +{ + RISCVIOMMUEntry *iot =3D (RISCVIOMMUEntry *) value; + iot->perm =3D 0; +} + +/* caller should keep ref-count for iot_cache object */ +static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx, + GHashTable *iot_cache, hwaddr iova) +{ + RISCVIOMMUEntry key =3D { + .pscid =3D get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID), + .iova =3D PPN_DOWN(iova), + }; + return g_hash_table_lookup(iot_cache, &key); +} + +/* caller should keep ref-count for iot_cache object */ +static void riscv_iommu_iot_update(RISCVIOMMUState *s, + GHashTable *iot_cache, RISCVIOMMUEntry *iot) +{ + if (!s->iot_limit) { + return; + } + + if (g_hash_table_size(s->iot_cache) >=3D s->iot_limit) { + iot_cache =3D g_hash_table_new_full(__iot_hash, __iot_equal, + g_free, NULL); + g_hash_table_unref(qatomic_xchg(&s->iot_cache, iot_cache)); + } + g_hash_table_add(iot_cache, iot); +} + +static void riscv_iommu_iot_inval(RISCVIOMMUState *s, GHFunc func, + uint32_t gscid, uint32_t pscid, hwaddr iova) +{ + GHashTable *iot_cache; + RISCVIOMMUEntry key =3D { + .gscid =3D gscid, + .pscid =3D pscid, + .iova =3D PPN_DOWN(iova), + }; + + iot_cache =3D g_hash_table_ref(s->iot_cache); + g_hash_table_foreach(iot_cache, func, &key); + g_hash_table_unref(iot_cache); +} + static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x, - IOMMUTLBEntry *iotlb) + IOMMUTLBEntry *iotlb, bool enable_cache) { + RISCVIOMMUEntry *iot; + IOMMUAccessFlags perm; bool enable_faults; bool enable_pasid; bool enable_pri; + GHashTable *iot_cache; int fault; =20 + iot_cache =3D g_hash_table_ref(s->iot_cache); + enable_faults =3D !(ctx->tc & RISCV_IOMMU_DC_TC_DTF); /* * TC[32] is reserved for custom extensions, used here to temporarily @@ -645,9 +768,36 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, R= ISCVIOMMUContext *ctx, enable_pri =3D (iotlb->perm =3D=3D IOMMU_NONE) && (ctx->tc & BIT_ULL(3= 2)); enable_pasid =3D (ctx->tc & RISCV_IOMMU_DC_TC_PDTV); =20 + iot =3D riscv_iommu_iot_lookup(ctx, iot_cache, iotlb->iova); + perm =3D iot ? iot->perm : IOMMU_NONE; + if (perm !=3D IOMMU_NONE) { + iotlb->translated_addr =3D PPN_PHYS(iot->phys); + iotlb->addr_mask =3D ~TARGET_PAGE_MASK; + iotlb->perm =3D perm; + fault =3D 0; + goto done; + } + /* Translate using device directory / page table information. */ fault =3D riscv_iommu_spa_fetch(s, ctx, iotlb); =20 + if (!fault && iotlb->target_as =3D=3D &s->trap_as) { + /* Do not cache trapped MSI translations */ + goto done; + } + + if (!fault && iotlb->translated_addr !=3D iotlb->iova && enable_cache)= { + iot =3D g_new0(RISCVIOMMUEntry, 1); + iot->iova =3D PPN_DOWN(iotlb->iova); + iot->phys =3D PPN_DOWN(iotlb->translated_addr); + iot->pscid =3D get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID); + iot->perm =3D iotlb->perm; + riscv_iommu_iot_update(s, iot_cache, iot); + } + +done: + g_hash_table_unref(iot_cache); + if (enable_pri && fault) { struct riscv_iommu_pq_record pr =3D {0}; if (enable_pasid) { @@ -794,13 +944,40 @@ static void riscv_iommu_process_cq_tail(RISCVIOMMUSta= te *s) if (cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_PSCV) { /* illegal command arguments IOTINVAL.GVMA & PSCV =3D=3D 1= */ goto cmd_ill; + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_GV)) { + /* invalidate all cache mappings */ + func =3D __iot_inval_all; + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_AV)) { + /* invalidate cache matching GSCID */ + func =3D __iot_inval_gscid; + } else { + /* invalidate cache matching GSCID and ADDR (GPA) */ + func =3D __iot_inval_gscid_gpa; } - /* translation cache not implemented yet */ + riscv_iommu_iot_inval(s, func, + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_GSCID), 0, + cmd.dword1 & TARGET_PAGE_MASK); break; =20 case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA, RISCV_IOMMU_CMD_IOTINVAL_OPCODE): - /* translation cache not implemented yet */ + if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_GV)) { + /* invalidate all cache mappings, simplified model */ + func =3D __iot_inval_all; + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_PSCV)) { + /* invalidate cache matching GSCID, simplified model */ + func =3D __iot_inval_gscid; + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_AV)) { + /* invalidate cache matching GSCID and PSCID */ + func =3D __iot_inval_pscid; + } else { + /* invalidate cache matching GSCID and PSCID and ADDR (IOV= A) */ + func =3D __iot_inval_pscid_iova; + } + riscv_iommu_iot_inval(s, func, + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_GSCID), + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_PSCID), + cmd.dword1 & TARGET_PAGE_MASK); break; =20 case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT, @@ -1290,6 +1467,8 @@ static void riscv_iommu_realize(DeviceState *dev, Err= or **errp) /* Device translation context cache */ s->ctx_cache =3D g_hash_table_new_full(__ctx_hash, __ctx_equal, g_free, NULL); + s->iot_cache =3D g_hash_table_new_full(__iot_hash, __iot_equal, + g_free, NULL); =20 s->iommus.le_next =3D NULL; s->iommus.le_prev =3D NULL; @@ -1313,6 +1492,7 @@ static void riscv_iommu_unrealize(DeviceState *dev) qemu_thread_join(&s->core_proc); qemu_cond_destroy(&s->core_cond); qemu_mutex_destroy(&s->core_lock); + g_hash_table_unref(s->iot_cache); g_hash_table_unref(s->ctx_cache); } =20 @@ -1320,6 +1500,8 @@ static Property riscv_iommu_properties[] =3D { DEFINE_PROP_UINT32("version", RISCVIOMMUState, version, RISCV_IOMMU_SPEC_DOT_VER), DEFINE_PROP_UINT32("bus", RISCVIOMMUState, bus, 0x0), + DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit, + LIMIT_CACHE_IOT), DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE), DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE), DEFINE_PROP_LINK("downstream-mr", RISCVIOMMUState, target_mr, @@ -1372,7 +1554,7 @@ static IOMMUTLBEntry riscv_iommu_memory_region_transl= ate( /* Translation disabled or invalid. */ iotlb.addr_mask =3D 0; iotlb.perm =3D IOMMU_NONE; - } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb)) { + } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb, true)) { /* Translation disabled or fault reported. */ iotlb.addr_mask =3D 0; iotlb.perm =3D IOMMU_NONE; diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h index 6f740de690..eea2123686 100644 --- a/hw/riscv/riscv-iommu.h +++ b/hw/riscv/riscv-iommu.h @@ -68,6 +68,8 @@ struct RISCVIOMMUState { MemoryRegion trap_mr; =20 GHashTable *ctx_cache; /* Device translation Context Cache */ + GHashTable *iot_cache; /* IO Translated Address Cache */ + unsigned iot_limit; /* IO Translation Cache size limit */ =20 /* MMIO Hardware Interface */ MemoryRegion regs_mr; --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827740; cv=none; d=zohomail.com; s=zohoarc; b=Dpc/fmkOzlF7BoRNnQBtR0snSdx9RPJadIXjqBwW/E+1BKYHSnQ9QLvryuLrnWbx/8EJtiEsHStPv9s3P3l6HGuPJgP1tJ3q8Rp+PTFw3UeruLTjGtD8zSEpwYMabjHDLeF7rEOuWFw4I4O+C+uugBZhL+ofpFi5+pUmXGn7dh4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827740; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cMb6NoUEmqBYjF16yAIQs0kDHoFu+HxAwpO1ohhcIj4=; b=mJWI5+4u8G24g93YJnNtUXgNINV6g3ThXjqwAltgbA9S1Wor4FDAhiYvatBw8t8DwjePrFWEciF+m4WxkkncYFIfKW65R+p8x8754shhKm5sba1rZ3/mf+/2ygkIw/6RQSUEMKxCEahl/m0CKZhqEyOFyBHIt+zyxQoS+4rp3ck= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827740397985.4377441226242; Thu, 7 Mar 2024 08:09:00 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGE0-0005Og-Vs; Thu, 07 Mar 2024 11:04:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGDz-0005Ki-2o for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:03 -0500 Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGDw-0006JM-JI for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:02 -0500 Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-1dd01ea35b5so6875925ad.0 for ; Thu, 07 Mar 2024 08:04:00 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:03:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827438; x=1710432238; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cMb6NoUEmqBYjF16yAIQs0kDHoFu+HxAwpO1ohhcIj4=; b=GHpaLCy90k0DY0xJcMDbSzvy7kIzHJrTck3IA//zFEGyE76Yv7tznCtUKJJ7nFZ7Ea 9WeGyMtN6wF8FH5+tZaaScn03ZFLS6KX7gCNc43x0IPVkpxThAOe9qesMaUwTJoIHHRp /vCcEWaRmayaSRwTF/Fa0vYQUGFRJNN2RDRA0LE0/y5Shf0BUJ1cjzbwkAOAgf5Cz1w5 amQ4tF88Ppx79viOmbuTp4dqax6dK8M+KheJRU1SayJQuh/5osk2frOuNFBybd9/FXfS /CNAJmamtBMcLqyQiTzi5nIYq74Z32GpDPwU9N8jHV8+1XorMsTH9pxqLpW9MFAvY7PT Hm0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827438; x=1710432238; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cMb6NoUEmqBYjF16yAIQs0kDHoFu+HxAwpO1ohhcIj4=; b=AcCXfA9ECMpFKI5JWUrS4H1kMRUynqVuLAV+avechmbdS7K3TfxqW0lKvdwbY7ejmP a/eYKAVUrtq/y4g9Le0NKcmbOGkpdj+/r5KBF48sdHstQW8zZFokhoXwxd71Fnj8lTZ/ ZBI2YCELAB4vG7hgUkUsHJeEjaJ9kkgYLbb4S15mMmXyOEQCMkJzwG8Z0au7uYrjubkp wc8T3dTXTjG/YcGfTBELn9Yv4RWTTGqCPAlgbWViAs+yVbDMNJ5FGQ92mWyLLrekhe3i IQ/QqCnNqlPtSPg/+W4BT9tf0YA8amA015mF8wkL2VZx6fpxLQSyZcGADvs1/362ZZW8 dCKg== X-Gm-Message-State: AOJu0Yzd8GWwsYO1auILmOG8TZBGHyFPv41MfjlEXGsMVU7v0DZxS863 94B8BIfj3tFHtlTQBJnzYwf1RBOK3LkAWOVL64CFaM/fNTYz2gruMdSo/X+XxwufstEfm9ucfW7 C X-Google-Smtp-Source: AGHT+IFdUNwwOlFSuUuYxM1y+cGSLf1HinsJj2K5zBtLKEFHp2PVmiQxtBDV5MpUUfAkUkKpx2zPfA== X-Received: by 2002:a17:902:b612:b0:1db:f941:c9a with SMTP id b18-20020a170902b61200b001dbf9410c9amr8610287pls.45.1709827438052; Thu, 07 Mar 2024 08:03:58 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 09/15] hw/riscv/riscv-iommu: add s-stage and g-stage support Date: Thu, 7 Mar 2024 13:03:12 -0300 Message-ID: <20240307160319.675044-10-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62a; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827741519100001 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Add support for s-stage (sv32, sv39, sv48, sv57 caps) and g-stage (sv32x4, sv39x4, sv48x4, sv57x4 caps). Most of the work is done in the riscv_iommu_spa_fetch() function that now has to consider how many translation stages we need to walk the page table. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza --- hw/riscv/riscv-iommu-bits.h | 11 ++ hw/riscv/riscv-iommu.c | 282 ++++++++++++++++++++++++++++++++++-- hw/riscv/riscv-iommu.h | 2 + 3 files changed, 286 insertions(+), 9 deletions(-) diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h index 8e80b1e52a..9d645d69ea 100644 --- a/hw/riscv/riscv-iommu-bits.h +++ b/hw/riscv/riscv-iommu-bits.h @@ -71,6 +71,14 @@ struct riscv_iommu_pq_record { /* 5.3 IOMMU Capabilities (64bits) */ #define RISCV_IOMMU_REG_CAP 0x0000 #define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0) +#define RISCV_IOMMU_CAP_SV32 BIT_ULL(8) +#define RISCV_IOMMU_CAP_SV39 BIT_ULL(9) +#define RISCV_IOMMU_CAP_SV48 BIT_ULL(10) +#define RISCV_IOMMU_CAP_SV57 BIT_ULL(11) +#define RISCV_IOMMU_CAP_SV32X4 BIT_ULL(16) +#define RISCV_IOMMU_CAP_SV39X4 BIT_ULL(17) +#define RISCV_IOMMU_CAP_SV48X4 BIT_ULL(18) +#define RISCV_IOMMU_CAP_SV57X4 BIT_ULL(19) #define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22) #define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) @@ -79,6 +87,7 @@ struct riscv_iommu_pq_record { =20 /* 5.4 Features control register (32bits) */ #define RISCV_IOMMU_REG_FCTL 0x0008 +#define RISCV_IOMMU_FCTL_GXL BIT(2) =20 /* 5.5 Device-directory-table pointer (64bits) */ #define RISCV_IOMMU_REG_DDTP 0x0010 @@ -195,6 +204,8 @@ struct riscv_iommu_dc { #define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4) #define RISCV_IOMMU_DC_TC_PDTV BIT_ULL(5) #define RISCV_IOMMU_DC_TC_PRPR BIT_ULL(6) +#define RISCV_IOMMU_DC_TC_GADE BIT_ULL(7) +#define RISCV_IOMMU_DC_TC_SADE BIT_ULL(8) #define RISCV_IOMMU_DC_TC_DPE BIT_ULL(9) #define RISCV_IOMMU_DC_TC_SXL BIT_ULL(11) =20 diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index 0b93146327..03a610fa75 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -58,6 +58,8 @@ struct RISCVIOMMUContext { uint64_t __rfu:20; /* reserved */ uint64_t tc; /* Translation Control */ uint64_t ta; /* Translation Attributes */ + uint64_t satp; /* S-Stage address translation and protect= ion */ + uint64_t gatp; /* G-Stage address translation and protect= ion */ uint64_t msi_addr_mask; /* MSI filtering - address mask */ uint64_t msi_addr_pattern; /* MSI filtering - address pattern */ uint64_t msiptp; /* MSI redirection page table pointer */ @@ -194,12 +196,46 @@ static bool riscv_iommu_msi_check(RISCVIOMMUState *s,= RISCVIOMMUContext *ctx, return true; } =20 -/* RISCV IOMMU Address Translation Lookup - Page Table Walk */ +/* + * RISCV IOMMU Address Translation Lookup - Page Table Walk + * + * Note: Code is based on get_physical_address() from target/riscv/cpu_hel= per.c + * Both implementation can be merged into single helper function in future. + * Keeping them separate for now, as error reporting and flow specifics are + * sufficiently different for separate implementation. + * + * @s : IOMMU Device State + * @ctx : Translation context for device id and process address space= id. + * @iotlb : translation data: physical address and access mode. + * @gpa : provided IOVA is a guest physical address, use G-Stage only. + * @return : success or fault cause code. + */ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ct= x, - IOMMUTLBEntry *iotlb) + IOMMUTLBEntry *iotlb, bool gpa) { + dma_addr_t addr, base; + uint64_t satp, gatp, pte; + bool en_s, en_g; + struct { + unsigned char step; + unsigned char levels; + unsigned char ptidxbits; + unsigned char ptesize; + } sc[2]; + /* Translation stage phase */ + enum { + S_STAGE =3D 0, + G_STAGE =3D 1, + } pass; + + satp =3D get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD); + gatp =3D get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD); + + en_s =3D satp !=3D RISCV_IOMMU_DC_FSC_MODE_BARE && !gpa; + en_g =3D gatp !=3D RISCV_IOMMU_DC_IOHGATP_MODE_BARE; + /* Early check for MSI address match when IOVA =3D=3D GPA */ - if (iotlb->perm & IOMMU_WO && + if (!en_s && (iotlb->perm & IOMMU_WO) && riscv_iommu_msi_check(s, ctx, iotlb->iova)) { iotlb->target_as =3D &s->trap_as; iotlb->translated_addr =3D iotlb->iova; @@ -208,11 +244,196 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s,= RISCVIOMMUContext *ctx, } =20 /* Exit early for pass-through mode. */ - iotlb->translated_addr =3D iotlb->iova; - iotlb->addr_mask =3D ~TARGET_PAGE_MASK; - /* Allow R/W in pass-through mode */ - iotlb->perm =3D IOMMU_RW; - return 0; + if (!(en_s || en_g)) { + iotlb->translated_addr =3D iotlb->iova; + iotlb->addr_mask =3D ~TARGET_PAGE_MASK; + /* Allow R/W in pass-through mode */ + iotlb->perm =3D IOMMU_RW; + return 0; + } + + /* S/G translation parameters. */ + for (pass =3D 0; pass < 2; pass++) { + uint32_t sv_mode; + + sc[pass].step =3D 0; + if (pass ? (s->fctl & RISCV_IOMMU_FCTL_GXL) : + (ctx->tc & RISCV_IOMMU_DC_TC_SXL)) { + /* 32bit mode for GXL/SXL =3D=3D 1 */ + switch (pass ? gatp : satp) { + case RISCV_IOMMU_DC_IOHGATP_MODE_BARE: + sc[pass].levels =3D 0; + sc[pass].ptidxbits =3D 0; + sc[pass].ptesize =3D 0; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV32X4: + sv_mode =3D pass ? RISCV_IOMMU_CAP_SV32X4 : RISCV_IOMMU_CA= P_SV32; + if (!(s->cap & sv_mode)) { + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + sc[pass].levels =3D 2; + sc[pass].ptidxbits =3D 10; + sc[pass].ptesize =3D 4; + break; + default: + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + } else { + /* 64bit mode for GXL/SXL =3D=3D 0 */ + switch (pass ? gatp : satp) { + case RISCV_IOMMU_DC_IOHGATP_MODE_BARE: + sc[pass].levels =3D 0; + sc[pass].ptidxbits =3D 0; + sc[pass].ptesize =3D 0; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4: + sv_mode =3D pass ? RISCV_IOMMU_CAP_SV39X4 : RISCV_IOMMU_CA= P_SV39; + if (!(s->cap & sv_mode)) { + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + sc[pass].levels =3D 3; + sc[pass].ptidxbits =3D 9; + sc[pass].ptesize =3D 8; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4: + sv_mode =3D pass ? RISCV_IOMMU_CAP_SV48X4 : RISCV_IOMMU_CA= P_SV48; + if (!(s->cap & sv_mode)) { + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + sc[pass].levels =3D 4; + sc[pass].ptidxbits =3D 9; + sc[pass].ptesize =3D 8; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4: + sv_mode =3D pass ? RISCV_IOMMU_CAP_SV57X4 : RISCV_IOMMU_CA= P_SV57; + if (!(s->cap & sv_mode)) { + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + sc[pass].levels =3D 5; + sc[pass].ptidxbits =3D 9; + sc[pass].ptesize =3D 8; + break; + default: + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + } + }; + + /* S/G stages translation tables root pointers */ + gatp =3D PPN_PHYS(get_field(ctx->gatp, RISCV_IOMMU_ATP_PPN_FIELD)); + satp =3D PPN_PHYS(get_field(ctx->satp, RISCV_IOMMU_ATP_PPN_FIELD)); + addr =3D (en_s && en_g) ? satp : iotlb->iova; + base =3D en_g ? gatp : satp; + pass =3D en_g ? G_STAGE : S_STAGE; + + do { + const unsigned widened =3D (pass && !sc[pass].step) ? 2 : 0; + const unsigned va_bits =3D widened + sc[pass].ptidxbits; + const unsigned va_skip =3D TARGET_PAGE_BITS + sc[pass].ptidxbits * + (sc[pass].levels - 1 - sc[pass].step); + const unsigned idx =3D (addr >> va_skip) & ((1 << va_bits) - 1); + const dma_addr_t pte_addr =3D base + idx * sc[pass].ptesize; + const bool ade =3D + ctx->tc & (pass ? RISCV_IOMMU_DC_TC_GADE : RISCV_IOMMU_DC_TC_S= ADE); + + /* Address range check before first level lookup */ + if (!sc[pass].step) { + const uint64_t va_mask =3D (1ULL << (va_skip + va_bits)) - 1; + if ((addr & va_mask) !=3D addr) { + return RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED; + } + } + + /* Read page table entry */ + if (dma_memory_read(s->target_as, pte_addr, &pte, + sc[pass].ptesize, MEMTXATTRS_UNSPECIFIED) !=3D MEMTX_OK) { + return (iotlb->perm & IOMMU_WO) ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT + : RISCV_IOMMU_FQ_CAUSE_RD_FAUL= T; + } + + if (sc[pass].ptesize =3D=3D 4) { + pte =3D (uint64_t) le32_to_cpu(*((uint32_t *)&pte)); + } else { + pte =3D le64_to_cpu(pte); + } + + sc[pass].step++; + hwaddr ppn =3D pte >> PTE_PPN_SHIFT; + + if (!(pte & PTE_V)) { + break; /* Invalid PTE */ + } else if (!(pte & (PTE_R | PTE_W | PTE_X))) { + base =3D PPN_PHYS(ppn); /* Inner PTE, continue walking */ + } else if ((pte & (PTE_R | PTE_W | PTE_X)) =3D=3D PTE_W) { + break; /* Reserved leaf PTE flags: PTE_W */ + } else if ((pte & (PTE_R | PTE_W | PTE_X)) =3D=3D (PTE_W | PTE_X))= { + break; /* Reserved leaf PTE flags: PTE_W + PTE_= X */ + } else if (ppn & ((1ULL << (va_skip - TARGET_PAGE_BITS)) - 1)) { + break; /* Misaligned PPN */ + } else if ((iotlb->perm & IOMMU_RO) && !(pte & PTE_R)) { + break; /* Read access check failed */ + } else if ((iotlb->perm & IOMMU_WO) && !(pte & PTE_W)) { + break; /* Write access check failed */ + } else if ((iotlb->perm & IOMMU_RO) && !ade && !(pte & PTE_A)) { + break; /* Access bit not set */ + } else if ((iotlb->perm & IOMMU_WO) && !ade && !(pte & PTE_D)) { + break; /* Dirty bit not set */ + } else { + /* Leaf PTE, translation completed. */ + sc[pass].step =3D sc[pass].levels; + base =3D PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + /* Update address mask based on smallest translation granulari= ty */ + iotlb->addr_mask &=3D (1ULL << va_skip) - 1; + /* Continue with S-Stage translation? */ + if (pass && sc[0].step !=3D sc[0].levels) { + pass =3D S_STAGE; + addr =3D iotlb->iova; + continue; + } + /* Translation phase completed (GPA or SPA) */ + iotlb->translated_addr =3D base; + iotlb->perm =3D (pte & PTE_W) ? ((pte & PTE_R) ? IOMMU_RW : IO= MMU_WO) + : IOMMU_RO; + + /* Check MSI GPA address match */ + if (pass =3D=3D S_STAGE && (iotlb->perm & IOMMU_WO) && + riscv_iommu_msi_check(s, ctx, base)) { + /* Trap MSI writes and return GPA address. */ + iotlb->target_as =3D &s->trap_as; + iotlb->addr_mask =3D ~TARGET_PAGE_MASK; + return 0; + } + + /* Continue with G-Stage translation? */ + if (!pass && en_g) { + pass =3D G_STAGE; + addr =3D base; + base =3D gatp; + sc[pass].step =3D 0; + continue; + } + + return 0; + } + + if (sc[pass].step =3D=3D sc[pass].levels) { + break; /* Can't find leaf PTE */ + } + + /* Continue with G-Stage translation? */ + if (!pass && en_g) { + pass =3D G_STAGE; + addr =3D base; + base =3D gatp; + sc[pass].step =3D 0; + } + } while (1); + + return (iotlb->perm & IOMMU_WO) ? + (pass ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS : + RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S) : + (pass ? RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS : + RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S); } =20 /* Redirect MSI write for given GPA. */ @@ -351,6 +572,10 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, R= ISCVIOMMUContext *ctx) =20 case RISCV_IOMMU_DDTP_MODE_BARE: /* mock up pass-through translation context */ + ctx->gatp =3D set_field(0, RISCV_IOMMU_ATP_MODE_FIELD, + RISCV_IOMMU_DC_IOHGATP_MODE_BARE); + ctx->satp =3D set_field(0, RISCV_IOMMU_ATP_MODE_FIELD, + RISCV_IOMMU_DC_FSC_MODE_BARE); ctx->tc =3D RISCV_IOMMU_DC_TC_V; ctx->ta =3D 0; ctx->msiptp =3D 0; @@ -424,6 +649,8 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx) =20 /* Set translation context. */ ctx->tc =3D le64_to_cpu(dc.tc); + ctx->gatp =3D le64_to_cpu(dc.iohgatp); + ctx->satp =3D le64_to_cpu(dc.fsc); ctx->ta =3D le64_to_cpu(dc.ta); ctx->msiptp =3D le64_to_cpu(dc.msiptp); ctx->msi_addr_mask =3D le64_to_cpu(dc.msi_addr_mask); @@ -433,14 +660,38 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, = RISCVIOMMUContext *ctx) return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; } =20 + /* FSC field checks */ + mode =3D get_field(ctx->satp, RISCV_IOMMU_DC_FSC_MODE); + addr =3D PPN_PHYS(get_field(ctx->satp, RISCV_IOMMU_DC_FSC_PPN)); + + if (mode =3D=3D RISCV_IOMMU_DC_FSC_MODE_BARE) { + /* No S-Stage translation, done. */ + return 0; + } + if (!(ctx->tc & RISCV_IOMMU_DC_TC_PDTV)) { if (ctx->pasid !=3D RISCV_IOMMU_NOPASID) { /* PASID is disabled */ return RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED; } + if (mode > RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV57) { + /* Invalid translation mode */ + return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID; + } return 0; } =20 + if (ctx->pasid =3D=3D RISCV_IOMMU_NOPASID) { + if (!(ctx->tc & RISCV_IOMMU_DC_TC_DPE)) { + /* No default PASID enabled, set BARE mode */ + ctx->satp =3D 0ULL; + return 0; + } else { + /* Use default PASID #0 */ + ctx->pasid =3D 0; + } + } + /* FSC.TC.PDTV enabled */ if (mode > RISCV_IOMMU_DC_FSC_PDTP_MODE_PD20) { /* Invalid PDTP.MODE */ @@ -474,6 +725,7 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx) =20 /* Use FSC and TA from process directory entry. */ ctx->ta =3D le64_to_cpu(dc.ta); + ctx->satp =3D le64_to_cpu(dc.fsc); =20 return 0; } @@ -710,6 +962,7 @@ static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOM= MUContext *ctx, GHashTable *iot_cache, hwaddr iova) { RISCVIOMMUEntry key =3D { + .gscid =3D get_field(ctx->gatp, RISCV_IOMMU_DC_IOHGATP_GSCID), .pscid =3D get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID), .iova =3D PPN_DOWN(iova), }; @@ -779,7 +1032,7 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, R= ISCVIOMMUContext *ctx, } =20 /* Translate using device directory / page table information. */ - fault =3D riscv_iommu_spa_fetch(s, ctx, iotlb); + fault =3D riscv_iommu_spa_fetch(s, ctx, iotlb, false); =20 if (!fault && iotlb->target_as =3D=3D &s->trap_as) { /* Do not cache trapped MSI translations */ @@ -790,6 +1043,7 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, R= ISCVIOMMUContext *ctx, iot =3D g_new0(RISCVIOMMUEntry, 1); iot->iova =3D PPN_DOWN(iotlb->iova); iot->phys =3D PPN_DOWN(iotlb->translated_addr); + iot->gscid =3D get_field(ctx->gatp, RISCV_IOMMU_DC_IOHGATP_GSCID); iot->pscid =3D get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID); iot->perm =3D iotlb->perm; riscv_iommu_iot_update(s, iot_cache, iot); @@ -1394,6 +1648,14 @@ static void riscv_iommu_realize(DeviceState *dev, Er= ror **errp) if (s->enable_msi) { s->cap |=3D RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF; } + if (s->enable_s_stage) { + s->cap |=3D RISCV_IOMMU_CAP_SV32 | RISCV_IOMMU_CAP_SV39 | + RISCV_IOMMU_CAP_SV48 | RISCV_IOMMU_CAP_SV57; + } + if (s->enable_g_stage) { + s->cap |=3D RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 | + RISCV_IOMMU_CAP_SV48X4 | RISCV_IOMMU_CAP_SV57X4; + } /* Report QEMU target physical address space limits */ s->cap =3D set_field(s->cap, RISCV_IOMMU_CAP_PAS, TARGET_PHYS_ADDR_SPACE_BITS); @@ -1504,6 +1766,8 @@ static Property riscv_iommu_properties[] =3D { LIMIT_CACHE_IOT), DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE), DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE), + DEFINE_PROP_BOOL("s-stage", RISCVIOMMUState, enable_s_stage, TRUE), + DEFINE_PROP_BOOL("g-stage", RISCVIOMMUState, enable_g_stage, TRUE), DEFINE_PROP_LINK("downstream-mr", RISCVIOMMUState, target_mr, TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h index eea2123686..9b33fb97ef 100644 --- a/hw/riscv/riscv-iommu.h +++ b/hw/riscv/riscv-iommu.h @@ -38,6 +38,8 @@ struct RISCVIOMMUState { =20 bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ bool enable_msi; /* Enable MSI remapping */ + bool enable_s_stage; /* Enable S/VS-Stage translation */ + bool enable_g_stage; /* Enable G-Stage translation */ =20 /* IOMMU Internal State */ uint64_t ddtp; /* Validated Device Directory Tree Root Pointer = */ --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827688; cv=none; d=zohomail.com; s=zohoarc; b=OnSXCeZXFSqq3mvGNbe0sQj6rsXdhgY6Q72LpTO7RVbDrS67QC30J/Ycl9Td3nMiL2VK81YMwo9zISMNaO6FXKBzheiwrUiEUvFYcI31bLjdYgoHpYx16RLeFgia9wXnP/rvMmMgTfa7Qc7XMZboN3sCzVR0+zIV0QIUR9v1Slk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827688; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=DXvSa8C+BXkOe83nsw1vLVz6jeTfH0D/qmyUUWWTv1c=; b=nIrJ0W2kmQ5aMnBemgPz+66TgSCovA9n+cf4+F8syLQXRme2pAf3ERYlm9nE1SK3UQa4T1KZ2KIlnzvWaDm3zTOi0mydoy/E2qeOsLs8DipbpZCRcQH/D0Q8gMVlrAfrgtgJjCRDHGIDViN3qKC1BGnT1VSEKZeRoqkiZc9KBOA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827688508789.3145916614507; Thu, 7 Mar 2024 08:08:08 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGE5-0005SI-6o; Thu, 07 Mar 2024 11:04:09 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGE3-0005RX-JN for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:07 -0500 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGE1-0006Lv-I3 for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:07 -0500 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-1dd59b95677so5116695ad.1 for ; Thu, 07 Mar 2024 08:04:05 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.03.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827444; x=1710432244; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DXvSa8C+BXkOe83nsw1vLVz6jeTfH0D/qmyUUWWTv1c=; b=D7EdNnENEEAxIrheGKowQzMhNPPamX/sZfqr2WEjjz+8AgbccukcicUmekTQihyou/ NKDcgIXCEtYmtKuMBy/rs4rG/Iye8lBhKQd/RlZwlT5ubQTOr6ofMsxgvV6b86G34oKw PaJ3uo1UgvrPWnEDGuYrtuvY1ECuMRY/iRXSgoOhPTRLkQlqDhGV24Kvk4QYcO/2IGx+ g0hGjqPuxyVg1+gFJ2hUnos6MG7qEZ97I7Lrn8jp4uBdasXmLRsnw8FAUJW/vrzZmddP J4SZrQPtyVpXnZssv4RKvozPZ3xzm1FYaa4j4Ut/SBcsgJ34nAxrDPjkvEiHHpAS2xLi /rdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827444; x=1710432244; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DXvSa8C+BXkOe83nsw1vLVz6jeTfH0D/qmyUUWWTv1c=; b=pTS7ueoInnElGqi+xKN/uo8vobGXHXFJxvuvJ32vyRiY4sZXZNs1TdGdVf404cDACM M3WvVnKGMZJvm0uM6bnWrFO+rki00AZKUmeT0OWh8tNEJp14UUXS7h8W9Zs62YM/RJI1 ZFXG05+LcuBQvnlWqxVWeG5GVoFvwWDT78Y6/qSi6Qby77mPriNxRwZsxnGQmRQkGuyH +udV5An/TYzjNorzy40h8FRDQ+NNUOuXYw2+supRVTt/EDPiNbH2L6iP6ZefUOzLrcyM fwCDOE9d3bBne3i0KC+rVp4p+eaAfb/SHCf6qKWr/0cD7VdQ49zkCrWGGFMb2CrpLasC iIzA== X-Gm-Message-State: AOJu0YySYXC1Rq2X3+7CVpYpwAgGs7TihNDyYl2p2mqX303yFsxLT8Te 1AZKtjbQk0THPzbUDgeoNeRL0kFX7tTwrWOQcFOqqnNnI0LkGETJWBXoZhHs1XimYtyXHn1CkoU z X-Google-Smtp-Source: AGHT+IHjLSJ5UIjmzOqGS92eCFc9Zt2TmEfuG/xfViUzeywujktTaN6ss0MUHOvvaKo/8o1T7l5GUg== X-Received: by 2002:a17:903:2349:b0:1d7:4353:aba5 with SMTP id c9-20020a170903234900b001d74353aba5mr8300970plh.58.1709827443664; Thu, 07 Mar 2024 08:04:03 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 10/15] hw/riscv/riscv-iommu: add ATS support Date: Thu, 7 Mar 2024 13:03:13 -0300 Message-ID: <20240307160319.675044-11-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62f; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827689026100003 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Add PCIe Address Translation Services (ATS) capabilities to the IOMMU. This will add support for ATS translation requests in Fault/Event queues, Page-request queue and IOATC invalidations. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza --- hw/riscv/riscv-iommu-bits.h | 43 ++++++++++++++- hw/riscv/riscv-iommu.c | 107 +++++++++++++++++++++++++++++++++--- hw/riscv/riscv-iommu.h | 1 + hw/riscv/trace-events | 3 + 4 files changed, 145 insertions(+), 9 deletions(-) diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h index 9d645d69ea..0994f5ce48 100644 --- a/hw/riscv/riscv-iommu-bits.h +++ b/hw/riscv/riscv-iommu-bits.h @@ -81,6 +81,7 @@ struct riscv_iommu_pq_record { #define RISCV_IOMMU_CAP_SV57X4 BIT_ULL(19) #define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22) #define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) +#define RISCV_IOMMU_CAP_ATS BIT_ULL(25) #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32) #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38) @@ -201,6 +202,7 @@ struct riscv_iommu_dc { =20 /* Translation control fields */ #define RISCV_IOMMU_DC_TC_V BIT_ULL(0) +#define RISCV_IOMMU_DC_TC_EN_ATS BIT_ULL(1) #define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4) #define RISCV_IOMMU_DC_TC_PDTV BIT_ULL(5) #define RISCV_IOMMU_DC_TC_PRPR BIT_ULL(6) @@ -259,6 +261,20 @@ struct riscv_iommu_command { #define RISCV_IOMMU_CMD_IODIR_DV BIT_ULL(33) #define RISCV_IOMMU_CMD_IODIR_DID GENMASK_ULL(63, 40) =20 +/* 3.1.4 I/O MMU PCIe ATS */ +#define RISCV_IOMMU_CMD_ATS_OPCODE 4 +#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL 0 +#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR 1 +#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_CMD_ATS_PV BIT_ULL(32) +#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33) +#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40) +#define RISCV_IOMMU_CMD_ATS_DSEG GENMASK_ULL(63, 56) +/* dword1 is the ATS payload, two different payload types for INVAL and PR= GR */ + +/* ATS.PRGR payload */ +#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE GENMASK_ULL(47, 44) + enum riscv_iommu_dc_fsc_atp_modes { RISCV_IOMMU_DC_FSC_MODE_BARE =3D 0, RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 =3D 8, @@ -322,7 +338,32 @@ enum riscv_iommu_fq_ttypes { RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH =3D 5, RISCV_IOMMU_FQ_TTYPE_TADDR_RD =3D 6, RISCV_IOMMU_FQ_TTYPE_TADDR_WR =3D 7, - RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ =3D 8, + RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ =3D 8, + RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ =3D 9, +}; + +/* Header fields */ +#define RISCV_IOMMU_PREQ_HDR_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32) +#define RISCV_IOMMU_PREQ_HDR_PRIV BIT_ULL(33) +#define RISCV_IOMMU_PREQ_HDR_EXEC BIT_ULL(34) +#define RISCV_IOMMU_PREQ_HDR_DID GENMASK_ULL(63, 40) + +/* Payload fields */ +#define RISCV_IOMMU_PREQ_PAYLOAD_R BIT_ULL(0) +#define RISCV_IOMMU_PREQ_PAYLOAD_W BIT_ULL(1) +#define RISCV_IOMMU_PREQ_PAYLOAD_L BIT_ULL(2) +#define RISCV_IOMMU_PREQ_PAYLOAD_M GENMASK_ULL(2, 0) +#define RISCV_IOMMU_PREQ_PRG_INDEX GENMASK_ULL(11, 3) +#define RISCV_IOMMU_PREQ_UADDR GENMASK_ULL(63, 12) + + +/* + * struct riscv_iommu_msi_pte - MSI Page Table Entry + */ +struct riscv_iommu_msi_pte { + uint64_t pte; + uint64_t mrif_info; }; =20 /* Fields on pte */ diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index 03a610fa75..7af5929b10 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -576,7 +576,7 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RI= SCVIOMMUContext *ctx) RISCV_IOMMU_DC_IOHGATP_MODE_BARE); ctx->satp =3D set_field(0, RISCV_IOMMU_ATP_MODE_FIELD, RISCV_IOMMU_DC_FSC_MODE_BARE); - ctx->tc =3D RISCV_IOMMU_DC_TC_V; + ctx->tc =3D RISCV_IOMMU_DC_TC_EN_ATS | RISCV_IOMMU_DC_TC_V; ctx->ta =3D 0; ctx->msiptp =3D 0; return 0; @@ -1021,6 +1021,18 @@ static int riscv_iommu_translate(RISCVIOMMUState *s,= RISCVIOMMUContext *ctx, enable_pri =3D (iotlb->perm =3D=3D IOMMU_NONE) && (ctx->tc & BIT_ULL(3= 2)); enable_pasid =3D (ctx->tc & RISCV_IOMMU_DC_TC_PDTV); =20 + /* Check for ATS request. */ + if (iotlb->perm =3D=3D IOMMU_NONE) { + /* Check if ATS is disabled. */ + if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS)) { + enable_pri =3D false; + fault =3D RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED; + goto done; + } + trace_riscv_iommu_ats(s->parent_obj.id, PCI_BUS_NUM(ctx->devid), + PCI_SLOT(ctx->devid), PCI_FUNC(ctx->devid), iotlb->iova); + } + iot =3D riscv_iommu_iot_lookup(ctx, iot_cache, iotlb->iova); perm =3D iot ? iot->perm : IOMMU_NONE; if (perm !=3D IOMMU_NONE) { @@ -1067,13 +1079,10 @@ done: =20 if (enable_faults && fault) { struct riscv_iommu_fq_record ev; - unsigned ttype; - - if (iotlb->perm & IOMMU_RW) { - ttype =3D RISCV_IOMMU_FQ_TTYPE_UADDR_WR; - } else { - ttype =3D RISCV_IOMMU_FQ_TTYPE_UADDR_RD; - } + const unsigned ttype =3D + (iotlb->perm & IOMMU_RW) ? RISCV_IOMMU_FQ_TTYPE_UADDR_WR : + ((iotlb->perm & IOMMU_RO) ? RISCV_IOMMU_FQ_TTYPE_UADDR_RD : + RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ); ev.hdr =3D set_field(0, RISCV_IOMMU_FQ_HDR_CAUSE, fault); ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE, ttype); ev.hdr =3D set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PV, enable_pasid); @@ -1105,6 +1114,73 @@ static MemTxResult riscv_iommu_iofence(RISCVIOMMUSta= te *s, bool notify, MEMTXATTRS_UNSPECIFIED); } =20 +static void riscv_iommu_ats(RISCVIOMMUState *s, + struct riscv_iommu_command *cmd, IOMMUNotifierFlag flag, + IOMMUAccessFlags perm, + void (*trace_fn)(const char *id)) +{ + RISCVIOMMUSpace *as =3D NULL; + IOMMUNotifier *n; + IOMMUTLBEvent event; + uint32_t pasid; + uint32_t devid; + const bool pv =3D cmd->dword0 & RISCV_IOMMU_CMD_ATS_PV; + + if (cmd->dword0 & RISCV_IOMMU_CMD_ATS_DSV) { + /* Use device segment and requester id */ + devid =3D get_field(cmd->dword0, + RISCV_IOMMU_CMD_ATS_DSEG | RISCV_IOMMU_CMD_ATS_RID); + } else { + devid =3D get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_RID); + } + + pasid =3D get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_PID); + + qemu_mutex_lock(&s->core_lock); + QLIST_FOREACH(as, &s->spaces, list) { + if (as->devid =3D=3D devid) { + break; + } + } + qemu_mutex_unlock(&s->core_lock); + + if (!as || !as->notifier) { + return; + } + + event.type =3D flag; + event.entry.perm =3D perm; + event.entry.target_as =3D s->target_as; + + IOMMU_NOTIFIER_FOREACH(n, &as->iova_mr) { + if (!pv || n->iommu_idx =3D=3D pasid) { + event.entry.iova =3D n->start; + event.entry.addr_mask =3D n->end - n->start; + trace_fn(as->iova_mr.parent_obj.name); + memory_region_notify_iommu_one(n, &event); + } + } +} + +static void riscv_iommu_ats_inval(RISCVIOMMUState *s, + struct riscv_iommu_command *cmd) +{ + return riscv_iommu_ats(s, cmd, IOMMU_NOTIFIER_DEVIOTLB_UNMAP, IOMMU_NO= NE, + trace_riscv_iommu_ats_inval); +} + +static void riscv_iommu_ats_prgr(RISCVIOMMUState *s, + struct riscv_iommu_command *cmd) +{ + unsigned resp_code =3D get_field(cmd->dword1, + RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE); + + /* Using the access flag to carry response code information */ + IOMMUAccessFlags perm =3D resp_code ? IOMMU_NONE : IOMMU_RW; + return riscv_iommu_ats(s, cmd, IOMMU_NOTIFIER_MAP, perm, + trace_riscv_iommu_ats_prgr); +} + static void riscv_iommu_process_ddtp(RISCVIOMMUState *s) { uint64_t old_ddtp =3D s->ddtp; @@ -1260,6 +1336,17 @@ static void riscv_iommu_process_cq_tail(RISCVIOMMUSt= ate *s) get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_PID)); break; =20 + /* ATS commands */ + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_ATS_FUNC_INVAL, + RISCV_IOMMU_CMD_ATS_OPCODE): + riscv_iommu_ats_inval(s, &cmd); + break; + + case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_ATS_FUNC_PRGR, + RISCV_IOMMU_CMD_ATS_OPCODE): + riscv_iommu_ats_prgr(s, &cmd); + break; + default: cmd_ill: /* Invalid instruction, do not advance instruction index. */ @@ -1648,6 +1735,9 @@ static void riscv_iommu_realize(DeviceState *dev, Err= or **errp) if (s->enable_msi) { s->cap |=3D RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF; } + if (s->enable_ats) { + s->cap |=3D RISCV_IOMMU_CAP_ATS; + } if (s->enable_s_stage) { s->cap |=3D RISCV_IOMMU_CAP_SV32 | RISCV_IOMMU_CAP_SV39 | RISCV_IOMMU_CAP_SV48 | RISCV_IOMMU_CAP_SV57; @@ -1765,6 +1855,7 @@ static Property riscv_iommu_properties[] =3D { DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit, LIMIT_CACHE_IOT), DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE), + DEFINE_PROP_BOOL("ats", RISCVIOMMUState, enable_ats, TRUE), DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE), DEFINE_PROP_BOOL("s-stage", RISCVIOMMUState, enable_s_stage, TRUE), DEFINE_PROP_BOOL("g-stage", RISCVIOMMUState, enable_g_stage, TRUE), diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h index 9b33fb97ef..47f3fdad58 100644 --- a/hw/riscv/riscv-iommu.h +++ b/hw/riscv/riscv-iommu.h @@ -38,6 +38,7 @@ struct RISCVIOMMUState { =20 bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ bool enable_msi; /* Enable MSI remapping */ + bool enable_ats; /* Enable ATS support */ bool enable_s_stage; /* Enable S/VS-Stage translation */ bool enable_g_stage; /* Enable G-Stage translation */ =20 diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events index 42a97caffa..4b486b6420 100644 --- a/hw/riscv/trace-events +++ b/hw/riscv/trace-events @@ -9,3 +9,6 @@ riscv_iommu_msi(const char *id, unsigned b, unsigned d, uns= igned f, uint64_t iov riscv_iommu_cmd(const char *id, uint64_t l, uint64_t u) "%s: command 0x%"P= RIx64" 0x%"PRIx64 riscv_iommu_notifier_add(const char *id) "%s: dev-iotlb notifier added" riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed" +riscv_iommu_ats(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t iova) "%s: translate request %04x:%02x.%u iova: 0x%"PRIx64 +riscv_iommu_ats_inval(const char *id) "%s: dev-iotlb invalidate" +riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group res= ponse" --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827629; cv=none; d=zohomail.com; s=zohoarc; b=Il55fN+mNdOw2lB+PSDp92mE1E1eMdB1C174KKxyMre8+MwA8sRTx0cGz/w6pjJTKsyyVNJUFWjFbJz6lMbYxn9AKQqTAVwybprJRPqx9FWW/gmJQhzaUbvSB5gXc8XNctg80mkNR/cRLfxrwiCrZpwFrG45zu+WR0Qx6m69drw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827629; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=YrjPn4v+JMxdhMjAUatZPIMLuNqO+d8n4xVa7+AkjLA=; b=NeVYiFY35Uu4sEJXi3sYDclc6PF7Ixo6Ht7nBneR/jC9Ic2pPEmjA6Sq+ndLwrxivlvhrk0KFK/la1jCG+xUsmAYPY85gW7iOE3/h/1RXeCRINCbE2zKwWNnoNB2DUkPzz2htsAj4nZRBp1/k5ot9bZdlDuW93qnMCgkwP1l42Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827629852507.14493458920435; Thu, 7 Mar 2024 08:07:09 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGE8-0005UD-RQ; Thu, 07 Mar 2024 11:04:12 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGE7-0005TZ-71 for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:11 -0500 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGE5-0006NZ-FT for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:10 -0500 Received: by mail-pl1-x62e.google.com with SMTP id d9443c01a7336-1dcad814986so8823915ad.0 for ; Thu, 07 Mar 2024 08:04:08 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.04.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827447; x=1710432247; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YrjPn4v+JMxdhMjAUatZPIMLuNqO+d8n4xVa7+AkjLA=; b=a7lRHN421jzhKViYwtPr2D5dTPzrI8JnJcE+cOLkdFPLatUWILYGYWHo4wZLCUmTxF GmYmqUiBxQh5ic2HSMJdEIw/1FM6zn40b8eHmUF+xtEjpPC9JR+RPdnyH8fXWKgGxjCA JywmCt+lUsDXMfgXGNRYOPghq9VW61kODzQralGKsAX2tLTCQxckUMlg/4XeY0YE05WB E3lWmMHN1BghxWEj2NmOOM745iaZoRT9qYf4isz/9o4RmNWuTzXoT83PPXFknZ4f9H8H LAlAGbwOQekM0UtD+HUMbyGegK5n8QYg0eYeQzmiFb72BB+V9jMBgZcCLlMgw/PLZYsV BHyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827447; x=1710432247; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YrjPn4v+JMxdhMjAUatZPIMLuNqO+d8n4xVa7+AkjLA=; b=grlG8k2q8HOMmGrueGjqrJXMOqpwxriKPJm4cVntiNYUfFz/VeADBaISkmKfR60JkI 6DTaiBpM3NGoMNxUMorLt/Cr2F+swtgEBJVLOugKdrR9IQ55iobZ/UwgET6w0brtisBR F04OrECm1rYh7HI9q4j59+jpWf6BvJX6fjUrZ7CDSO6XTzit8dMlM8wLe5FCLEXYU40u jeZHuxOrZhMDth1iyFB3jKkqD/OrPBzrAs8IHhATLAZIMyZLYPdgeJtErNesmOdkCGnH MQNH+5SmFum6/kiQws70/lDxHy7AY5DrW8xMPpsYewx08PENiPV9XelBjSNDtR6a9xeA bkCQ== X-Gm-Message-State: AOJu0YwRhADXund78v7xGfs8qhuzV6z7gPNAqm9rNNbP94scvrRiPe2D NBQcYTjK4/3OL3dbs1lBw8XpILQxIwBLJaswDEsAPOnsR1SCeBWmewoyNKfnIPkkVrAU0SHiE1M i X-Google-Smtp-Source: AGHT+IG8pVQ09YsIJZ1mR5WL74lYX/wlEfOVZa2g2WvwZ2SpfBF1HLp1YWffGFn0ef61R+FZ/T8ktg== X-Received: by 2002:a17:902:d490:b0:1dd:2b94:17d3 with SMTP id c16-20020a170902d49000b001dd2b9417d3mr11783522plg.43.1709827446829; Thu, 07 Mar 2024 08:04:06 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 11/15] hw/riscv/riscv-iommu: add DBG support Date: Thu, 7 Mar 2024 13:03:14 -0300 Message-ID: <20240307160319.675044-12-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62e; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827630699100005 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach DBG support adds three additional registers: tr_req_iova, tr_req_ctl and tr_response. The DBG cap is always enabled. No on/off toggle is provided for it. Signed-off-by: Tomasz Jeznach Signed-off-by: Daniel Henrique Barboza --- hw/riscv/riscv-iommu-bits.h | 20 +++++++++++++ hw/riscv/riscv-iommu.c | 57 ++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h index 0994f5ce48..b3f92411bb 100644 --- a/hw/riscv/riscv-iommu-bits.h +++ b/hw/riscv/riscv-iommu-bits.h @@ -83,6 +83,7 @@ struct riscv_iommu_pq_record { #define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) #define RISCV_IOMMU_CAP_ATS BIT_ULL(25) #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) +#define RISCV_IOMMU_CAP_DBG BIT_ULL(31) #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32) #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38) =20 @@ -177,6 +178,25 @@ enum { RISCV_IOMMU_INTR_COUNT }; =20 +#define RISCV_IOMMU_IPSR_CIP BIT(RISCV_IOMMU_INTR_CQ) +#define RISCV_IOMMU_IPSR_FIP BIT(RISCV_IOMMU_INTR_FQ) +#define RISCV_IOMMU_IPSR_PMIP BIT(RISCV_IOMMU_INTR_PM) +#define RISCV_IOMMU_IPSR_PIP BIT(RISCV_IOMMU_INTR_PQ) + +/* 5.24 Translation request IOVA (64bits) */ +#define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258 + +/* 5.25 Translation request control (64bits) */ +#define RISCV_IOMMU_REG_TR_REQ_CTL 0x0260 +#define RISCV_IOMMU_TR_REQ_CTL_GO_BUSY BIT_ULL(0) +#define RISCV_IOMMU_TR_REQ_CTL_PID GENMASK_ULL(31, 12) +#define RISCV_IOMMU_TR_REQ_CTL_DID GENMASK_ULL(63, 40) + +/* 5.26 Translation request response (64bits) */ +#define RISCV_IOMMU_REG_TR_RESPONSE 0x0268 +#define RISCV_IOMMU_TR_RESPONSE_FAULT BIT_ULL(0) +#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD + /* 5.27 Interrupt cause to vector (64bits) */ #define RISCV_IOMMU_REG_IVEC 0x02F8 =20 diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index 7af5929b10..1fa1286d07 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -1457,6 +1457,46 @@ static void riscv_iommu_process_pq_control(RISCVIOMM= UState *s) riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr); } =20 +static void riscv_iommu_process_dbg(RISCVIOMMUState *s) +{ + uint64_t iova =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_IOVA= ); + uint64_t ctrl =3D riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_CTL); + unsigned devid =3D get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_DID); + unsigned pid =3D get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_PID); + RISCVIOMMUContext *ctx; + void *ref; + + if (!(ctrl & RISCV_IOMMU_TR_REQ_CTL_GO_BUSY)) { + return; + } + + ctx =3D riscv_iommu_ctx(s, devid, pid, &ref); + if (ctx =3D=3D NULL) { + riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, + RISCV_IOMMU_TR_RESPONSE_FAULT | + (RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED << 10)= ); + } else { + IOMMUTLBEntry iotlb =3D { + .iova =3D iova, + .perm =3D IOMMU_NONE, + .addr_mask =3D ~0, + .target_as =3D NULL, + }; + int fault =3D riscv_iommu_translate(s, ctx, &iotlb, false); + if (fault) { + iova =3D RISCV_IOMMU_TR_RESPONSE_FAULT | (((uint64_t) fault) <= < 10); + } else { + iova =3D ((iotlb.translated_addr & ~iotlb.addr_mask) >> 2) & + RISCV_IOMMU_TR_RESPONSE_PPN; + } + riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, iova); + } + + riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0, + RISCV_IOMMU_TR_REQ_CTL_GO_BUSY); + riscv_iommu_ctx_put(s, ref); +} + /* Core IOMMU execution activation */ enum { RISCV_IOMMU_EXEC_DDTP, @@ -1502,7 +1542,7 @@ static void *riscv_iommu_core_proc(void* arg) /* NOP */ break; case BIT(RISCV_IOMMU_EXEC_TR_REQUEST): - /* DBG support not implemented yet */ + riscv_iommu_process_dbg(s); break; } exec &=3D ~mask; @@ -1574,6 +1614,12 @@ static MemTxResult riscv_iommu_mmio_write(void *opaq= ue, hwaddr addr, exec =3D BIT(RISCV_IOMMU_EXEC_PQCSR); busy =3D RISCV_IOMMU_PQCSR_BUSY; break; + + case RISCV_IOMMU_REG_TR_REQ_CTL: + exec =3D BIT(RISCV_IOMMU_EXEC_TR_REQUEST); + regb =3D RISCV_IOMMU_REG_TR_REQ_CTL; + busy =3D RISCV_IOMMU_TR_REQ_CTL_GO_BUSY; + break; } =20 /* @@ -1746,6 +1792,9 @@ static void riscv_iommu_realize(DeviceState *dev, Err= or **errp) s->cap |=3D RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 | RISCV_IOMMU_CAP_SV48X4 | RISCV_IOMMU_CAP_SV57X4; } + /* Enable translation debug interface */ + s->cap |=3D RISCV_IOMMU_CAP_DBG; + /* Report QEMU target physical address space limits */ s->cap =3D set_field(s->cap, RISCV_IOMMU_CAP_PAS, TARGET_PHYS_ADDR_SPACE_BITS); @@ -1800,6 +1849,12 @@ static void riscv_iommu_realize(DeviceState *dev, Er= ror **errp) stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_IPSR], ~0); stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_IVEC], 0); stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_DDTP], s->ddtp); + /* If debug registers enabled. */ + if (s->cap & RISCV_IOMMU_CAP_DBG) { + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_TR_REQ_IOVA], 0); + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_TR_REQ_CTL], + RISCV_IOMMU_TR_REQ_CTL_GO_BUSY); + } =20 /* Memory region for downstream access, if specified. */ if (s->target_mr) { --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827533; cv=none; d=zohomail.com; s=zohoarc; b=fRozQtixFhmymXYAigfBi2LHdPiXn4B2DmbpoJGBA3cSdDoHSjdpIOT5pldLlwZ/nreeVNca9mbnQtLczK1Mvnmu33dixNA9Lq/HEqmaJ5fsqlDR8fLjbSOHZh+MnbnC9nQ2nbBWUDnWijme062uaOkwq6TiheL/dUgHI/vSTZE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827533; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=1npuklC5aEdofdL53vX8HPX3oehGBOj2ZxbYnQl0d8Q=; b=Do/VHjCj04z9UCQWqWPfOARwM4/94aNxgrptZYv2AdlPuKGMsA0SQH+nz+9gmkzyYLOpTmEQbnHiFverNLEeFUzuZWHga+OPETgzi08pvCmdcf+4k8XgjAk98KU5wCb3HU3B7z3l2AiLyZcLhL5VMwzwOUogjq85gwPTfKR2HY4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827533983659.5456587907578; Thu, 7 Mar 2024 08:05:33 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGED-0005YJ-3o; Thu, 07 Mar 2024 11:04:17 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGEC-0005Xg-3l for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:16 -0500 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGE8-0006Og-2J for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:15 -0500 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-6e5a50d91b4so1013983b3a.2 for ; Thu, 07 Mar 2024 08:04:11 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.04.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827450; x=1710432250; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1npuklC5aEdofdL53vX8HPX3oehGBOj2ZxbYnQl0d8Q=; b=Pyqq9zWtMdCk1VDDJPLavCkH1c6y5+UQ1ZR6l2rkyiDVFsgGVwdrCJG2alEip09aij OLYlJOMrcNNGXJhqjyDmoXuJZ2CbVs9l0X1ltnwxKFQAGiia7i9lkS0FRUy9gbQ+mHqm XPDaa2nRwGKGX2cPd+niNdqHcFNumhYGxSAS8YBaQsp9ttmkZlXW4XMmgb1FDSN9eQRu meJpIa6Ohw+GGLx6FNeJq/gghRp97+jKWZqhDiqiQSJj5MWO3SlEtKaUSrT1twPeFOAl LZ2keX5hJLlH38ViMWQ7NkO7kglddKEXhyNkXxpjoKDddcNyR9CuyZt6XK8iivp5Vnu9 /LAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827450; x=1710432250; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1npuklC5aEdofdL53vX8HPX3oehGBOj2ZxbYnQl0d8Q=; b=od6M3NjuHUzFOGWKG9+Jo/icyhoM6uB0Q/yaMa1iSsWdvoGyCUMdQ9xH5QxkLvdYxX 5zwTUwVyPZOibWgeO8usIHcgKtyzCWZaTnTvItdYSc5Vng/1JbI0gJGO3Las6WwtLjo+ Yohuq+93rNRexM6XZMdx+E6OuWJD3lTBHozRGBIz9jXd/Nt4HJvOaVyybw4SAZoiib94 f9zM3iPlhKAVN9GM/unxFTelDTMaW8U3OgEsOcq2oWxbh0lvLRQVlyu8GUuTkTf4Kh1g jvHm4L0fdx8Zhaf04CCdfQo3fZtZsO3ebYo0qM+befyIURlBac+w0THAmvOyy0aO43pZ NU8A== X-Gm-Message-State: AOJu0YwZriKuyifYAvXQVMovljspFvPoxgvU2OobO0AH9m5RJeaGZvYc esFPGyzmQeczl6BcflVT5YK4rlb/5TLaVfMS7uIAEAfOD02sJxWI5EQ/+f0rhY1RR1vrcA/Wx+s Y X-Google-Smtp-Source: AGHT+IFtgKfyaxfyOJhkGgUbmZHlfgDqHWUnUT/+OPQg/MXRVIEzsTIWLe1v2YTY2LKJT94wP814Zg== X-Received: by 2002:a17:902:f552:b0:1dd:6092:743f with SMTP id h18-20020a170902f55200b001dd6092743fmr1264098plf.56.1709827450058; Thu, 07 Mar 2024 08:04:10 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 12/15] hw/riscv/riscv-iommu: Add another irq for mrif notifications Date: Thu, 7 Mar 2024 13:03:15 -0300 Message-ID: <20240307160319.675044-13-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::429; envelope-from=dbarboza@ventanamicro.com; helo=mail-pf1-x429.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827536323100003 Content-Type: text/plain; charset="utf-8" From: Andrew Jones And add mrif notification trace. Signed-off-by: Andrew Jones Reviewed-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- hw/riscv/riscv-iommu-pci.c | 2 +- hw/riscv/riscv-iommu.c | 1 + hw/riscv/trace-events | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c index 4eb1057210..8a7b71166c 100644 --- a/hw/riscv/riscv-iommu-pci.c +++ b/hw/riscv/riscv-iommu-pci.c @@ -78,7 +78,7 @@ static void riscv_iommu_pci_realize(PCIDevice *dev, Error= **errp) pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, &s->bar0); =20 - int ret =3D msix_init(dev, RISCV_IOMMU_INTR_COUNT, + int ret =3D msix_init(dev, RISCV_IOMMU_INTR_COUNT + 1, &s->bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG, &s->bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG + 256, 0, = &err); =20 diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index 1fa1286d07..954a6892c2 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -543,6 +543,7 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUStat= e *s, if (res !=3D MEMTX_OK) { return res; } + trace_riscv_iommu_mrif_notification(s->parent_obj.id, n190, addr); =20 return MEMTX_OK; } diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events index 4b486b6420..d69719a27a 100644 --- a/hw/riscv/trace-events +++ b/hw/riscv/trace-events @@ -6,6 +6,7 @@ riscv_iommu_flt(const char *id, unsigned b, unsigned d, uns= igned f, uint64_t rea riscv_iommu_pri(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t iova) "%s: page request %04x:%02x.%u iova: 0x%"PRIx64 riscv_iommu_dma(const char *id, unsigned b, unsigned d, unsigned f, unsign= ed pasid, const char *dir, uint64_t iova, uint64_t phys) "%s: translate %04= x:%02x.%u #%u %s 0x%"PRIx64" -> 0x%"PRIx64 riscv_iommu_msi(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t iova, uint64_t phys) "%s: translate %04x:%02x.%u MSI 0x%"PRIx64" -> 0x%"= PRIx64 +riscv_iommu_mrif_notification(const char *id, uint32_t nid, uint64_t phys)= "%s: sent MRIF notification 0x%x to 0x%"PRIx64 riscv_iommu_cmd(const char *id, uint64_t l, uint64_t u) "%s: command 0x%"P= RIx64" 0x%"PRIx64 riscv_iommu_notifier_add(const char *id) "%s: dev-iotlb notifier added" riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed" --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827552; cv=none; d=zohomail.com; s=zohoarc; b=Mw5RCAGxXjAUmrkYIa9CKhIB3UMKvUhRZwfVsZwn03gp75mJKvK0te9qdYvaIDCJ7FcuPTbVdQZzDqtCepwe3uyLDPb5z4j/+pW3a2P3xMMuKDrRef3ZpIuX2amFTGNKA29nUyLFn1sAOV5K/+7U6uKW9GdbWDxRU2cu5sCz17s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827552; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=gZsCAjxGaHiffZ85MO/0fACZgHsaZTv8YjKn+gPOMkQ=; b=QyynFI0rZnkknCZiY5wZLS4pY3WzA6B1Sy+WEingGFWs2IlkShxIDDXW1+JsQm7jV7ULmaQPuDGwCJMCNz0XOCfZ7Bi5eQ8A56MnI1nocZk5Bdwv5QEf0T06LrK2efv6HwCdN6PYdhlIL+zpJ3iDpISGaeetgcsMT731tJ4ralU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827552348866.0236230808603; Thu, 7 Mar 2024 08:05:52 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGEI-0005fB-S9; Thu, 07 Mar 2024 11:04:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGED-0005ZE-NV for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:17 -0500 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGEB-0006QN-DW for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:17 -0500 Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-1dc09556599so9548395ad.1 for ; Thu, 07 Mar 2024 08:04:15 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.04.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827454; x=1710432254; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gZsCAjxGaHiffZ85MO/0fACZgHsaZTv8YjKn+gPOMkQ=; b=DY7ELOpteLvWPHxnPeaP6FaqsDbWF9hDxKaoxUTdGAytiNfdSGJUZAlifjhokeY2G+ szlO8svIxn7ifBjHX2OIUWrFEBWXvlG3C80ljWRo+5eqKT0QCt6Cw6qcqmf9RBz/sZTM PgcwyCztF5XZKRwYtIn4KEHUquecm+d9GQII2kGqeT4RrEvxkLdp8hyF3djbrBfrssyz 1t0seXp4fk4lshtMm7F8mGf6xrSGW1c3oZWx/Hv804C3rBF4vcLfUPPRgvbJJo9NeV+t BRLhFhqC7s8aqBNNIENGDt5nONtJDoAUxI0pcZipyLvBaW4UttxDraHqJiZEyagbW+IK aXFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827454; x=1710432254; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gZsCAjxGaHiffZ85MO/0fACZgHsaZTv8YjKn+gPOMkQ=; b=PInf96diME64Rqrn0en9mIO7+ZiGiJ0m+3e1glAvt9gagRF78CPoFTcfkOieBbc+cj JmEBlBOAusTw8qBWvDIUvdm1yPZ7F48P5NCnlLmUwC7wGMhO3Zq3HQHOc1VnEeoBNBMw 6NABdwsUTfuHPMQHrCObK5aE2+Ybq/Rv95vXc7eH2Ti9OW0zqIuTlELYtUU9yWrnzJ73 MzsLXeVdsnqw42lm2whbzFeIcOCLPUzEL/dDnlF3yzz3d4HH6xe8TKH9fWWmVtsnTpBc ARaEPZRMCY69AQwS2mQKsf+DjwrteownAyUTXexaDnq+k/TbfWsG2MDYv0HnDF2EAzcr bVhg== X-Gm-Message-State: AOJu0YxADyK6rHrEdpJ7FiEzzZWk6b+1gDs4KC9llmgtjRQS8iways+y NeLoPKbV52IJmBxr3uuxFZt6KRSLLhOQAeuRju3BFKfXL3uQTyiHxMXj/p47TxPztMTgoF/2TQF o X-Google-Smtp-Source: AGHT+IFY/nlH22bS2alhWbr9/4QQyViIoKkz4D9RziEzcI9HovHXb1rAnzxWmSl0nrmxB2hDPAiQfw== X-Received: by 2002:a17:902:eccc:b0:1dc:b3bc:b7e1 with SMTP id a12-20020a170902eccc00b001dcb3bcb7e1mr10944027plh.1.1709827453583; Thu, 07 Mar 2024 08:04:13 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com, Daniel Henrique Barboza Subject: [PATCH v2 13/15] qtest/riscv-iommu-test: add init queues test Date: Thu, 7 Mar 2024 13:03:16 -0300 Message-ID: <20240307160319.675044-14-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62c; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827554260100002 Content-Type: text/plain; charset="utf-8" Add an additional test to further exercise the IOMMU where we attempt to initialize the command, fault and page-request queues. These steps are taken from chapter 6.2 of the RISC-V IOMMU spec, "Guidelines for initialization". It emulates what we expect from the software/OS when initializing the IOMMU. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frank Chang --- tests/qtest/libqos/riscv-iommu.h | 29 +++++++ tests/qtest/riscv-iommu-test.c | 141 +++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/tests/qtest/libqos/riscv-iommu.h b/tests/qtest/libqos/riscv-io= mmu.h index 8c056caa7b..aeaa5fb8b8 100644 --- a/tests/qtest/libqos/riscv-iommu.h +++ b/tests/qtest/libqos/riscv-iommu.h @@ -58,6 +58,35 @@ =20 #define RISCV_IOMMU_REG_IPSR 0x0054 =20 +#define RISCV_IOMMU_REG_IVEC 0x02F8 +#define RISCV_IOMMU_REG_IVEC_CIV GENMASK_ULL(3, 0) +#define RISCV_IOMMU_REG_IVEC_FIV GENMASK_ULL(7, 4) +#define RISCV_IOMMU_REG_IVEC_PIV GENMASK_ULL(15, 12) + +#define RISCV_IOMMU_REG_CQB 0x0018 +#define RISCV_IOMMU_CQB_PPN_START 10 +#define RISCV_IOMMU_CQB_PPN_LEN 44 +#define RISCV_IOMMU_CQB_LOG2SZ_START 0 +#define RISCV_IOMMU_CQB_LOG2SZ_LEN 5 + +#define RISCV_IOMMU_REG_CQT 0x0024 + +#define RISCV_IOMMU_REG_FQB 0x0028 +#define RISCV_IOMMU_FQB_PPN_START 10 +#define RISCV_IOMMU_FQB_PPN_LEN 44 +#define RISCV_IOMMU_FQB_LOG2SZ_START 0 +#define RISCV_IOMMU_FQB_LOG2SZ_LEN 5 + +#define RISCV_IOMMU_REG_FQT 0x0034 + +#define RISCV_IOMMU_REG_PQB 0x0038 +#define RISCV_IOMMU_PQB_PPN_START 10 +#define RISCV_IOMMU_PQB_PPN_LEN 44 +#define RISCV_IOMMU_PQB_LOG2SZ_START 0 +#define RISCV_IOMMU_PQB_LOG2SZ_LEN 5 + +#define RISCV_IOMMU_REG_PQT 0x0044 + typedef struct QRISCVIOMMU { QOSGraphObject obj; QPCIDevice dev; diff --git a/tests/qtest/riscv-iommu-test.c b/tests/qtest/riscv-iommu-test.c index 13b887d15e..64f3f092f2 100644 --- a/tests/qtest/riscv-iommu-test.c +++ b/tests/qtest/riscv-iommu-test.c @@ -33,6 +33,20 @@ static uint64_t riscv_iommu_read_reg64(QRISCVIOMMU *r_io= mmu, int reg_offset) return reg; } =20 +static void riscv_iommu_write_reg32(QRISCVIOMMU *r_iommu, int reg_offset, + uint32_t val) +{ + qpci_memwrite(&r_iommu->dev, r_iommu->reg_bar, reg_offset, + &val, sizeof(val)); +} + +static void riscv_iommu_write_reg64(QRISCVIOMMU *r_iommu, int reg_offset, + uint64_t val) +{ + qpci_memwrite(&r_iommu->dev, r_iommu->reg_bar, reg_offset, + &val, sizeof(val)); +} + static void test_pci_config(void *obj, void *data, QGuestAllocator *t_allo= c) { QRISCVIOMMU *r_iommu =3D obj; @@ -84,10 +98,137 @@ static void test_reg_reset(void *obj, void *data, QGue= stAllocator *t_alloc) g_assert_cmpuint(reg, =3D=3D, 0); } =20 +/* + * Common timeout-based poll for CQCSR, FQCSR and PQCSR. All + * their ON bits are mapped as RISCV_IOMMU_QUEUE_ACTIVE (16), + */ +static void qtest_wait_for_queue_active(QRISCVIOMMU *r_iommu, + uint32_t queue_csr) +{ + QTestState *qts =3D global_qtest; + guint64 timeout_us =3D 2 * 1000 * 1000; + gint64 start_time =3D g_get_monotonic_time(); + uint32_t reg; + + for (;;) { + qtest_clock_step(qts, 100); + + reg =3D riscv_iommu_read_reg32(r_iommu, queue_csr); + if (reg & RISCV_IOMMU_QUEUE_ACTIVE) { + break; + } + g_assert(g_get_monotonic_time() - start_time <=3D timeout_us); + } +} + +/* + * Goes through the queue activation procedures of chapter 6.2, + * "Guidelines for initialization", of the RISCV-IOMMU spec. + */ +static void test_iommu_init_queues(void *obj, void *data, + QGuestAllocator *t_alloc) +{ + QRISCVIOMMU *r_iommu =3D obj; + uint64_t reg64, q_addr; + uint32_t reg; + int k; + + reg64 =3D riscv_iommu_read_reg64(r_iommu, RISCV_IOMMU_REG_CAP); + g_assert_cmpuint(reg64 & RISCV_IOMMU_CAP_VERSION, =3D=3D, 0x10); + + /* + * Program the command queue. Write 0xF to civ, assert that + * we have 4 writable bits (k =3D 4). The amount of entries N in the + * command queue is 2^4 =3D 16. We need to alloc a N*16 bytes + * buffer and use it to set cqb. + */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_IVEC, + 0xFFFF & RISCV_IOMMU_REG_IVEC_CIV); + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_IVEC); + g_assert_cmpuint(reg & RISCV_IOMMU_REG_IVEC_CIV, =3D=3D, 0xF); + + q_addr =3D guest_alloc(t_alloc, 16 * 16); + reg64 =3D 0; + k =3D 4; + deposit64(reg64, RISCV_IOMMU_CQB_PPN_START, + RISCV_IOMMU_CQB_PPN_LEN, q_addr); + deposit64(reg64, RISCV_IOMMU_CQB_LOG2SZ_START, + RISCV_IOMMU_CQB_LOG2SZ_LEN, k - 1); + riscv_iommu_write_reg64(r_iommu, RISCV_IOMMU_REG_CQB, reg64); + + /* cqt =3D 0, cqcsr.cqen =3D 1, poll cqcsr.cqon until it reads 1 */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_CQT, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_CQCSR); + reg |=3D RISCV_IOMMU_CQCSR_CQEN; + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_CQCSR, reg); + + qtest_wait_for_queue_active(r_iommu, RISCV_IOMMU_REG_CQCSR); + + /* + * Program the fault queue. Similar to the above: + * - Write 0xF to fiv, assert that we have 4 writable bits (k =3D 4) + * - Alloc a 16*32 bytes (instead of 16*16) buffer and use it to set + * fqb + */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_IVEC, + 0xFFFF & RISCV_IOMMU_REG_IVEC_FIV); + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_IVEC); + g_assert_cmpuint(reg & RISCV_IOMMU_REG_IVEC_FIV, =3D=3D, 0xF0); + + q_addr =3D guest_alloc(t_alloc, 16 * 32); + reg64 =3D 0; + k =3D 4; + deposit64(reg64, RISCV_IOMMU_FQB_PPN_START, + RISCV_IOMMU_FQB_PPN_LEN, q_addr); + deposit64(reg64, RISCV_IOMMU_FQB_LOG2SZ_START, + RISCV_IOMMU_FQB_LOG2SZ_LEN, k - 1); + riscv_iommu_write_reg64(r_iommu, RISCV_IOMMU_REG_FQB, reg64); + + /* fqt =3D 0, fqcsr.fqen =3D 1, poll fqcsr.fqon until it reads 1 */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_FQT, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_FQCSR); + reg |=3D RISCV_IOMMU_FQCSR_FQEN; + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_FQCSR, reg); + + qtest_wait_for_queue_active(r_iommu, RISCV_IOMMU_REG_FQCSR); + + /* + * Program the page-request queue: + - Write 0xF to piv, assert that we have 4 writable bits (k =3D 4) + - Alloc a 16*16 bytes buffer and use it to set pqb. + */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_IVEC, + 0xFFFF & RISCV_IOMMU_REG_IVEC_PIV); + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_IVEC); + g_assert_cmpuint(reg & RISCV_IOMMU_REG_IVEC_PIV, =3D=3D, 0xF000); + + q_addr =3D guest_alloc(t_alloc, 16 * 16); + reg64 =3D 0; + k =3D 4; + deposit64(reg64, RISCV_IOMMU_PQB_PPN_START, + RISCV_IOMMU_PQB_PPN_LEN, q_addr); + deposit64(reg64, RISCV_IOMMU_PQB_LOG2SZ_START, + RISCV_IOMMU_PQB_LOG2SZ_LEN, k - 1); + riscv_iommu_write_reg64(r_iommu, RISCV_IOMMU_REG_PQB, reg64); + + /* pqt =3D 0, pqcsr.pqen =3D 1, poll pqcsr.pqon until it reads 1 */ + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_PQT, 0); + + reg =3D riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_PQCSR); + reg |=3D RISCV_IOMMU_PQCSR_PQEN; + riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_PQCSR, reg); + + qtest_wait_for_queue_active(r_iommu, RISCV_IOMMU_REG_PQCSR); +} + static void register_riscv_iommu_test(void) { qos_add_test("pci_config", "riscv-iommu-pci", test_pci_config, NULL); qos_add_test("reg_reset", "riscv-iommu-pci", test_reg_reset, NULL); + qos_add_test("iommu_init_queues", "riscv-iommu-pci", + test_iommu_init_queues, NULL); } =20 libqos_init(register_riscv_iommu_test); --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827566; cv=none; d=zohomail.com; s=zohoarc; b=QpOoxxEJ9ltNhiPPuWXN8DC1dR8HGrLRzBTGiPSA4cI7zF12sRXH7Slg6ZVnQ77cNAUknU9W6soDffK8yrq+S9iZHjQFb2HlZHkB27Ko59Qbjg1WDsX9RnxhlKSE/bu7t5rJEAsSRxwG8PAklMmiisEAAAdqYaO/9A6mg5Ghsp4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827566; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=JHMZVEtvnnHB22u3wYO9ijDTPlEvnoumvWUlGS7sTog=; b=huAjhxY3dhci0fNuCj2Pw1HZeJfFciChi7zFPk/ZfOEOd8RMv5w+oVETRWXfTl8CVrmFR6m3+WJikpLzu0rfKGzmnwyxQBmJEtop/lL9JL3y1ScPD+hKMr49xR+1cMWyqiUzmDWn4PNjTtd5zoK2NPEwWwujUeQqPzMoUJ/i98w= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827566151705.5685600699537; Thu, 7 Mar 2024 08:06:06 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGEI-0005vi-9g; Thu, 07 Mar 2024 11:04:22 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGEG-0005kR-Gw for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:20 -0500 Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGEE-0006S6-Ka for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:20 -0500 Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-1dd3bdb6e9eso7686205ad.3 for ; Thu, 07 Mar 2024 08:04:18 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.04.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827456; x=1710432256; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JHMZVEtvnnHB22u3wYO9ijDTPlEvnoumvWUlGS7sTog=; b=lVIEl45No1FSalpmtCRh/l8yTRFHGkOatHVVog6IdIm4x87g2qt1OsBMq7cJ2tLRYj fAwzjaOnQIV7Cfswwc4ACXvCi9qQ4Ss+XR1/FvduiDTlwVXHPkHBp0EdIzztFINn3Py9 fN7qdVSEgoCQo6enNgQlspTnaebNBu0vMGHY3tvtYJhOB2gyCSxOG/+EPNpeBcGqUdub 7kt7pVAhaVYJb5/xDsuoz9DCf9Js/2DS1YcQBM7bmD+Uz9LWxgUo1ZwilGugrIC3eiOG GhGhJm03JCs3dhWTuPEbWwJoVOoFisXEpKQk1/aMPHCGKVqOg8IRpnMXFmjmx0NLxXVM rZfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827456; x=1710432256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JHMZVEtvnnHB22u3wYO9ijDTPlEvnoumvWUlGS7sTog=; b=LIpLv2r3+Vjtzv7ABJLr00AgaOcocbvVnLirFcqxE5Z8+VRAB9TMEDikecYG5Lco+9 pqAU4a4VY5fSAVkH4qI2DYAusx+/3sRGAtA8mk9qjpi3h/6CAVghltvSOVZakfZw/6On tJb+uTFcw9FQN2ZtG8EPy4nAagLAD7kV0QB3xG5bN9q4YJ3p3EuESdL/XHlovfJdF8j0 cTRo/RrGi1WlMYDzeMa6CFTpNRUpW06zAe1XA7t5Bp0DTIgHwLu8UWqQj7HprunJKjN2 dpzyZ/C5LowVmRYbbmiJso8hDXMmWoVogp07ChNnSOBh5g9KWboqadTk50Afe8pBlcMa q9gQ== X-Gm-Message-State: AOJu0YzniH3nsmJ8f3OGQFb6Jtrdh9EZSgyAuQCyWfk0VtSr9wd+f2Lg vOXC5ocXMBgG2E19ewzSieNbyPdEN0chOqAsjGmc8DsUAl6I8uLymA3b18+VrT1gusOROU5JK5L B X-Google-Smtp-Source: AGHT+IH3sacDa5WP/Fv5WL5BCxw9dQlYgN6QXUgcMp9f5MNNnX5VrayQIaVWQXaShMc37lIpQTWP8g== X-Received: by 2002:a17:903:11c3:b0:1dc:fb5:6f36 with SMTP id q3-20020a17090311c300b001dc0fb56f36mr9994831plh.32.1709827456543; Thu, 07 Mar 2024 08:04:16 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com Subject: [PATCH v2 14/15] hw/misc: EDU: added PASID support Date: Thu, 7 Mar 2024 13:03:17 -0300 Message-ID: <20240307160319.675044-15-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::636; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x636.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827569004100007 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Extension to support DMA with PASID identifier and reporting PASID extended PCIe capabilities. Signed-off-by: Tomasz Jeznach --- hw/misc/edu.c | 57 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 2a976ca2b1..522cec85b3 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "hw/pci/pci.h" #include "hw/hw.h" +#include "hw/qdev-properties.h" #include "hw/pci/msi.h" #include "qemu/timer.h" #include "qom/object.h" @@ -53,6 +54,8 @@ struct EduState { QemuCond thr_cond; bool stopping; =20 + bool enable_pasid; + uint32_t addr4; uint32_t fact; #define EDU_STATUS_COMPUTING 0x01 @@ -66,6 +69,9 @@ struct EduState { # define EDU_DMA_FROM_PCI 0 # define EDU_DMA_TO_PCI 1 #define EDU_DMA_IRQ 0x4 +#define EDU_DMA_PV 0x8 +#define EDU_DMA_PASID(cmd) (((cmd) >> 8) & ((1U << 20) - 1)) + struct dma_state { dma_addr_t src; dma_addr_t dst; @@ -126,12 +132,7 @@ static void edu_check_range(uint64_t addr, uint64_t si= ze1, uint64_t start, =20 static dma_addr_t edu_clamp_addr(const EduState *edu, dma_addr_t addr) { - dma_addr_t res =3D addr & edu->dma_mask; - - if (addr !=3D res) { - printf("EDU: clamping DMA %#.16"PRIx64" to %#.16"PRIx64"!\n", addr= , res); - } - + dma_addr_t res =3D addr; return res; } =20 @@ -139,23 +140,33 @@ static void edu_dma_timer(void *opaque) { EduState *edu =3D opaque; bool raise_irq =3D false; + MemTxAttrs attrs =3D MEMTXATTRS_UNSPECIFIED; =20 if (!(edu->dma.cmd & EDU_DMA_RUN)) { return; } =20 + if (edu->enable_pasid && (edu->dma.cmd & EDU_DMA_PV)) { + attrs.unspecified =3D 0; + attrs.pasid =3D EDU_DMA_PASID(edu->dma.cmd); + attrs.requester_id =3D pci_requester_id(&edu->pdev); + attrs.secure =3D 0; + } + if (EDU_DMA_DIR(edu->dma.cmd) =3D=3D EDU_DMA_FROM_PCI) { uint64_t dst =3D edu->dma.dst; edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE); dst -=3D DMA_START; - pci_dma_read(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), - edu->dma_buf + dst, edu->dma.cnt); + pci_dma_rw(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), + edu->dma_buf + dst, edu->dma.cnt, + DMA_DIRECTION_TO_DEVICE, attrs); } else { uint64_t src =3D edu->dma.src; edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE); src -=3D DMA_START; - pci_dma_write(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), - edu->dma_buf + src, edu->dma.cnt); + pci_dma_rw(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), + edu->dma_buf + src, edu->dma.cnt, + DMA_DIRECTION_FROM_DEVICE, attrs); } =20 edu->dma.cmd &=3D ~EDU_DMA_RUN; @@ -255,7 +266,8 @@ static void edu_mmio_write(void *opaque, hwaddr addr, u= int64_t val, if (qatomic_read(&edu->status) & EDU_STATUS_COMPUTING) { break; } - /* EDU_STATUS_COMPUTING cannot go 0->1 concurrently, because it is= only + /* + * EDU_STATUS_COMPUTING cannot go 0->1 concurrently, because it is= only * set in this function and it is under the iothread mutex. */ qemu_mutex_lock(&edu->thr_mutex); @@ -368,9 +380,21 @@ static void pci_edu_realize(PCIDevice *pdev, Error **e= rrp) { EduState *edu =3D EDU(pdev); uint8_t *pci_conf =3D pdev->config; + int pos; =20 pci_config_set_interrupt_pin(pci_conf, 1); =20 + pcie_endpoint_cap_init(pdev, 0); + + /* PCIe extended capability for PASID */ + pos =3D PCI_CONFIG_SPACE_SIZE; + if (edu->enable_pasid) { + /* PCIe Spec 7.8.9 PASID Extended Capability Structure */ + pcie_add_capability(pdev, 0x1b, 1, pos, 8); + pci_set_long(pdev->config + pos + 4, 0x00001400); + pci_set_long(pdev->wmask + pos + 4, 0xfff0ffff); + } + if (msi_init(pdev, 0, 1, true, false, errp)) { return; } @@ -404,20 +428,27 @@ static void pci_edu_uninit(PCIDevice *pdev) msi_uninit(pdev); } =20 + static void edu_instance_init(Object *obj) { EduState *edu =3D EDU(obj); =20 - edu->dma_mask =3D (1UL << 28) - 1; + edu->dma_mask =3D ~0ULL; object_property_add_uint64_ptr(obj, "dma_mask", &edu->dma_mask, OBJ_PROP_FLAG_READWRITE= ); } =20 +static Property edu_properties[] =3D { + DEFINE_PROP_BOOL("pasid", EduState, enable_pasid, TRUE), + DEFINE_PROP_END_OF_LIST(), +}; + static void edu_class_init(ObjectClass *class, void *data) { DeviceClass *dc =3D DEVICE_CLASS(class); PCIDeviceClass *k =3D PCI_DEVICE_CLASS(class); =20 + device_class_set_props(dc, edu_properties); k->realize =3D pci_edu_realize; k->exit =3D pci_edu_uninit; k->vendor_id =3D PCI_VENDOR_ID_QEMU; @@ -430,7 +461,7 @@ static void edu_class_init(ObjectClass *class, void *da= ta) static void pci_edu_register_types(void) { static InterfaceInfo interfaces[] =3D { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { INTERFACE_PCIE_DEVICE }, { }, }; static const TypeInfo edu_info =3D { --=20 2.43.2 From nobody Sun May 12 07:02:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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 ARC-Seal: i=1; a=rsa-sha256; t=1709827731; cv=none; d=zohomail.com; s=zohoarc; b=DAa0ZS6DPGtWqR8blGsBMfWzhoAUNeU4sLQXd/ZUm/LH5mAWUqe6dpg/e13bFgk+CDFBwKBFJ/qzcd+52NshzLIQEdQvn0q+AO1+ag78OKlzAaryB7lbPMIHnaeQ6obvbSbROo0tdohHZ9+5mNm+4y++mq9eEBag24cFJw3lwUo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1709827731; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=1aXRP2KVTe35bDOq459aCYA3XDBPGwRmCn+nfWu9Dtg=; b=BTutqGHCcuC0XGKQo3IsHcbrEmsESNlNM97XJCbQh6j2j2NyoKwOSk32cu//Rrhzi6h9QTFhcc5FAqdiihQ3x3IqcFF1xKHBe6P8C745Lfu/VF4zdK3zFGHN9zjT01h3lpGy7Ab6xy9fEbrt1ZooVc53FiEkwGOtRBihpqqPYXc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1709827731205390.0425074680536; Thu, 7 Mar 2024 08:08:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1riGEd-0006Kg-BI; Thu, 07 Mar 2024 11:04:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1riGET-0006E9-7x for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:33 -0500 Received: from mail-pl1-x62d.google.com ([2607:f8b0:4864:20::62d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1riGEK-0006TV-Ob for qemu-devel@nongnu.org; Thu, 07 Mar 2024 11:04:31 -0500 Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1dc5d0162bcso9386705ad.0 for ; Thu, 07 Mar 2024 08:04:24 -0800 (PST) Received: from grind.dc1.ventanamicro.com ([177.94.15.159]) by smtp.gmail.com with ESMTPSA id u11-20020a170903124b00b001db2b8b2da7sm14663136plh.122.2024.03.07.08.04.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 08:04:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1709827460; x=1710432260; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1aXRP2KVTe35bDOq459aCYA3XDBPGwRmCn+nfWu9Dtg=; b=K2L8Ji48bxE+Tf21r93ixkNye5ZgEwesNZrDQRieyvwplDZSq+N133WLQSVhpmMiVF RaLuVpETuSRtS0x81m9zzaLhLRpUcbIerW6xbPp70PGTmYqo8thl/mTiI+Law+zVjzIS FHki9PYt6S2vusWW3d85LBQy0HM+jtHEcMvdW90YRVgB9ACmNJsADoc2qKsZXt03soLK 4dOYKyKag+Vmr5jY6useJwQ8Z1JBHJ3D9t9wdR3/jqq5Dqu1sdSkpBuaa+hEpCKFdzB7 npGUbXg6uar3DCBaAvCn6cuEACI6z7sQR4MdW/tGrwB++7zDab/ZfiXKjlZ4hHw++L4I 3hBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709827460; x=1710432260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1aXRP2KVTe35bDOq459aCYA3XDBPGwRmCn+nfWu9Dtg=; b=U0HbA+HGZjaEz7AMvVLtqxe/aN0yL1QRSUwdpjhdcYhY0WtUtAn8/VW2xBDnjR13I/ iP08p0YhcXYtaL9OsAZfBoRuaemk7FlvC8jAq21+dBkN9MLvZ131S5DFJLnwVHcIZgUH QvGjQebfstYkB3DTWGIhQpC+5JcS5dt0zQ9ATdPlhBCGqa+kyvonuwdlaa9rih7Wlg6G OYjhoFgwrXHaYkebwbJjGWIriIPFzTIUCe6ldhFuXYkz95xBxaemRj43zyPUX+NiS7wm TeMm6EDb+YmtL1UprvR7mxo1XnsvPnw/TrJHZBVwPF+VBDo5y+z5BRph2p7Az8CfSPMG vicA== X-Gm-Message-State: AOJu0YzR/Z6Quqye2mVEHxaj2Jievi7rOf1ENx9lm0J5nXKIKJPU8L+1 rEzKuIBLpzz3EpKS0Jf/S1R0ZdPqlCly1oUxnIxTJ/0YS3rudYrFt1HOP/UHKBpcoT29oB/bStu d X-Google-Smtp-Source: AGHT+IGoFS2MF0reIo/AKEmeI92FN3H728A+uxneGTTHUYFyLi7GdBPRQBQNqP0YBROznPlPMSgQKQ== X-Received: by 2002:a17:902:7c92:b0:1dc:cc09:ebad with SMTP id y18-20020a1709027c9200b001dccc09ebadmr6875109pll.28.1709827459524; Thu, 07 Mar 2024 08:04:19 -0800 (PST) From: Daniel Henrique Barboza To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com, zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com, ajones@ventanamicro.com, tjeznach@rivosinc.com Subject: [PATCH v2 15/15] hw/misc: EDU: add ATS/PRI capability Date: Thu, 7 Mar 2024 13:03:18 -0300 Message-ID: <20240307160319.675044-16-dbarboza@ventanamicro.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240307160319.675044-1-dbarboza@ventanamicro.com> References: <20240307160319.675044-1-dbarboza@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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; Received-SPF: pass client-ip=2607:f8b0:4864:20::62d; envelope-from=dbarboza@ventanamicro.com; helo=mail-pl1-x62d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @ventanamicro.com) X-ZM-MESSAGEID: 1709827733340100003 Content-Type: text/plain; charset="utf-8" From: Tomasz Jeznach Mimic ATS interface with IOMMU translate request with IOMMU_NONE. If mapping exists, translation service will return current permission flags, otherwise will report no permissions. Implement and register the IOMMU memory region listener to be notified whenever an ATS invalidation request is sent from the IOMMU. Implement and register the IOMMU memory region listener to be notified whenever an ATS page request group response is triggered from the IOMMU. Introduces a retry mechanism to the timer design so that any page that's not available should be only accessed after the PRGR notification has been received. Signed-off-by: Tomasz Jeznach Signed-off-by: Sebastien Boeuf --- hw/misc/edu.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 251 insertions(+), 7 deletions(-) diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 522cec85b3..f4f6c15ec6 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -45,6 +45,14 @@ DECLARE_INSTANCE_CHECKER(EduState, EDU, #define DMA_START 0x40000 #define DMA_SIZE 4096 =20 +/* + * Number of tries before giving up on page request group response. + * Given the timer callback is scheduled to be run again after 100ms, + * 10 tries give roughly a second for the PRGR notification to be + * received. + */ +#define NUM_TRIES 10 + struct EduState { PCIDevice pdev; MemoryRegion mmio; @@ -55,6 +63,7 @@ struct EduState { bool stopping; =20 bool enable_pasid; + uint32_t try; =20 uint32_t addr4; uint32_t fact; @@ -81,6 +90,20 @@ struct EduState { QEMUTimer dma_timer; char dma_buf[DMA_SIZE]; uint64_t dma_mask; + + MemoryListener iommu_listener; + QLIST_HEAD(, edu_iommu) iommu_list; + + bool prgr_rcvd; + bool prgr_success; +}; + +struct edu_iommu { + EduState *edu; + IOMMUMemoryRegion *iommu_mr; + hwaddr iommu_offset; + IOMMUNotifier n; + QLIST_ENTRY(edu_iommu) iommu_next; }; =20 static bool edu_msi_enabled(EduState *edu) @@ -136,11 +159,65 @@ static dma_addr_t edu_clamp_addr(const EduState *edu,= dma_addr_t addr) return res; } =20 +static bool __find_iommu_mr_cb(Int128 start, Int128 len, const MemoryRegio= n *mr, + hwaddr offset_in_region, void *opaque) +{ + IOMMUMemoryRegion **iommu_mr =3D opaque; + *iommu_mr =3D memory_region_get_iommu((MemoryRegion *)mr); + return *iommu_mr !=3D NULL; +} + +static int pci_dma_perm(PCIDevice *pdev, dma_addr_t iova, MemTxAttrs attrs) +{ + IOMMUMemoryRegion *iommu_mr =3D NULL; + IOMMUMemoryRegionClass *imrc; + int iommu_idx; + FlatView *fv; + EduState *edu =3D EDU(pdev); + struct edu_iommu *iommu; + + RCU_READ_LOCK_GUARD(); + + fv =3D address_space_to_flatview(pci_get_address_space(pdev)); + + /* Find first IOMMUMemoryRegion */ + flatview_for_each_range(fv, __find_iommu_mr_cb, &iommu_mr); + + if (iommu_mr) { + imrc =3D memory_region_get_iommu_class_nocheck(iommu_mr); + + /* IOMMU Index is mapping to memory attributes (PASID, etc) */ + iommu_idx =3D imrc->attrs_to_index ? + imrc->attrs_to_index(iommu_mr, attrs) : 0; + + /* Update IOMMU notifiers with proper index */ + QLIST_FOREACH(iommu, &edu->iommu_list, iommu_next) { + if (iommu->iommu_mr =3D=3D iommu_mr && + iommu->n.iommu_idx !=3D iommu_idx) { + memory_region_unregister_iommu_notifier( + MEMORY_REGION(iommu->iommu_mr), &iommu->n); + iommu->n.iommu_idx =3D iommu_idx; + memory_region_register_iommu_notifier( + MEMORY_REGION(iommu->iommu_mr), &iommu->n, NULL); + } + } + + /* Translate request with IOMMU_NONE is an ATS request */ + IOMMUTLBEntry iotlb =3D imrc->translate(iommu_mr, iova, IOMMU_NONE, + iommu_idx); + + return iotlb.perm; + } + + return IOMMU_NONE; +} + static void edu_dma_timer(void *opaque) { EduState *edu =3D opaque; bool raise_irq =3D false; MemTxAttrs attrs =3D MEMTXATTRS_UNSPECIFIED; + MemTxResult res; =20 if (!(edu->dma.cmd & EDU_DMA_RUN)) { return; @@ -155,18 +232,70 @@ static void edu_dma_timer(void *opaque) =20 if (EDU_DMA_DIR(edu->dma.cmd) =3D=3D EDU_DMA_FROM_PCI) { uint64_t dst =3D edu->dma.dst; + uint64_t src =3D edu_clamp_addr(edu, edu->dma.src); edu_check_range(dst, edu->dma.cnt, DMA_START, DMA_SIZE); dst -=3D DMA_START; - pci_dma_rw(&edu->pdev, edu_clamp_addr(edu, edu->dma.src), - edu->dma_buf + dst, edu->dma.cnt, - DMA_DIRECTION_TO_DEVICE, attrs); + if (edu->try-- =3D=3D NUM_TRIES) { + edu->prgr_rcvd =3D false; + if (!(pci_dma_perm(&edu->pdev, src, attrs) & IOMMU_RO)) { + timer_mod(&edu->dma_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + return; + } + } else if (edu->try) { + if (!edu->prgr_rcvd) { + timer_mod(&edu->dma_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + return; + } + if (!edu->prgr_success) { + /* PRGR failure, fail DMA. */ + edu->dma.cmd &=3D ~EDU_DMA_RUN; + return; + } + } else { + /* timeout, fail DMA. */ + edu->dma.cmd &=3D ~EDU_DMA_RUN; + return; + } + res =3D pci_dma_rw(&edu->pdev, src, edu->dma_buf + dst, edu->dma.c= nt, + DMA_DIRECTION_TO_DEVICE, attrs); + if (res !=3D MEMTX_OK) { + hw_error("EDU: DMA transfer TO 0x%"PRIx64" failed.\n", dst); + } } else { uint64_t src =3D edu->dma.src; + uint64_t dst =3D edu_clamp_addr(edu, edu->dma.dst); edu_check_range(src, edu->dma.cnt, DMA_START, DMA_SIZE); src -=3D DMA_START; - pci_dma_rw(&edu->pdev, edu_clamp_addr(edu, edu->dma.dst), - edu->dma_buf + src, edu->dma.cnt, - DMA_DIRECTION_FROM_DEVICE, attrs); + if (edu->try-- =3D=3D NUM_TRIES) { + edu->prgr_rcvd =3D false; + if (!(pci_dma_perm(&edu->pdev, dst, attrs) & IOMMU_WO)) { + timer_mod(&edu->dma_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + return; + } + } else if (edu->try) { + if (!edu->prgr_rcvd) { + timer_mod(&edu->dma_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + return; + } + if (!edu->prgr_success) { + /* PRGR failure, fail DMA. */ + edu->dma.cmd &=3D ~EDU_DMA_RUN; + return; + } + } else { + /* timeout, fail DMA. */ + edu->dma.cmd &=3D ~EDU_DMA_RUN; + return; + } + res =3D pci_dma_rw(&edu->pdev, dst, edu->dma_buf + src, edu->dma.c= nt, + DMA_DIRECTION_FROM_DEVICE, attrs); + if (res !=3D MEMTX_OK) { + hw_error("EDU: DMA transfer FROM 0x%"PRIx64" failed.\n", src); + } } =20 edu->dma.cmd &=3D ~EDU_DMA_RUN; @@ -193,6 +322,7 @@ static void dma_rw(EduState *edu, bool write, dma_addr_= t *val, dma_addr_t *dma, } =20 if (timer) { + edu->try =3D NUM_TRIES; timer_mod(&edu->dma_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) += 100); } } @@ -376,9 +506,92 @@ static void *edu_fact_thread(void *opaque) return NULL; } =20 +static void edu_iommu_ats_prgr_notify(IOMMUNotifier *n, IOMMUTLBEntry *iot= lb) +{ + struct edu_iommu *iommu =3D container_of(n, struct edu_iommu, n); + EduState *edu =3D iommu->edu; + edu->prgr_success =3D (iotlb->perm !=3D IOMMU_NONE); + barrier(); + edu->prgr_rcvd =3D true; +} + +static void edu_iommu_ats_inval_notify(IOMMUNotifier *n, + IOMMUTLBEntry *iotlb) +{ + +} + +static void edu_iommu_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + EduState *edu =3D container_of(listener, EduState, iommu_listener); + struct edu_iommu *iommu; + Int128 end; + int iommu_idx; + IOMMUMemoryRegion *iommu_mr; + + if (!memory_region_is_iommu(section->mr)) { + return; + } + + iommu_mr =3D IOMMU_MEMORY_REGION(section->mr); + + /* Register ATS.INVAL notifier */ + iommu =3D g_malloc0(sizeof(*iommu)); + iommu->iommu_mr =3D iommu_mr; + iommu->iommu_offset =3D section->offset_within_address_space - + section->offset_within_region; + iommu->edu =3D edu; + end =3D int128_add(int128_make64(section->offset_within_region), + section->size); + end =3D int128_sub(end, int128_one()); + iommu_idx =3D memory_region_iommu_attrs_to_index(iommu_mr, + MEMTXATTRS_UNSPECIFIED); + iommu_notifier_init(&iommu->n, edu_iommu_ats_inval_notify, + IOMMU_NOTIFIER_DEVIOTLB_UNMAP, + section->offset_within_region, + int128_get64(end), + iommu_idx); + memory_region_register_iommu_notifier(section->mr, &iommu->n, NULL); + QLIST_INSERT_HEAD(&edu->iommu_list, iommu, iommu_next); + + /* Register ATS.PRGR notifier */ + iommu =3D g_memdup2(iommu, sizeof(*iommu)); + iommu_notifier_init(&iommu->n, edu_iommu_ats_prgr_notify, + IOMMU_NOTIFIER_MAP, + section->offset_within_region, + int128_get64(end), + iommu_idx); + memory_region_register_iommu_notifier(section->mr, &iommu->n, NULL); + QLIST_INSERT_HEAD(&edu->iommu_list, iommu, iommu_next); +} + +static void edu_iommu_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + EduState *edu =3D container_of(listener, EduState, iommu_listener); + struct edu_iommu *iommu; + + if (!memory_region_is_iommu(section->mr)) { + return; + } + + QLIST_FOREACH(iommu, &edu->iommu_list, iommu_next) { + if (MEMORY_REGION(iommu->iommu_mr) =3D=3D section->mr && + iommu->n.start =3D=3D section->offset_within_region) { + memory_region_unregister_iommu_notifier(section->mr, + &iommu->n); + QLIST_REMOVE(iommu, iommu_next); + g_free(iommu); + break; + } + } +} + static void pci_edu_realize(PCIDevice *pdev, Error **errp) { EduState *edu =3D EDU(pdev); + AddressSpace *dma_as =3D NULL; uint8_t *pci_conf =3D pdev->config; int pos; =20 @@ -390,9 +603,28 @@ static void pci_edu_realize(PCIDevice *pdev, Error **e= rrp) pos =3D PCI_CONFIG_SPACE_SIZE; if (edu->enable_pasid) { /* PCIe Spec 7.8.9 PASID Extended Capability Structure */ - pcie_add_capability(pdev, 0x1b, 1, pos, 8); + pcie_add_capability(pdev, PCI_EXT_CAP_ID_PASID, 1, pos, 8); pci_set_long(pdev->config + pos + 4, 0x00001400); pci_set_long(pdev->wmask + pos + 4, 0xfff0ffff); + pos +=3D 8; + + /* ATS Capability */ + pcie_ats_init(pdev, pos, true); + pos +=3D PCI_EXT_CAP_ATS_SIZEOF; + + /* PRI Capability */ + pcie_add_capability(pdev, PCI_EXT_CAP_ID_PRI, 1, pos, 16); + /* PRI STOPPED */ + pci_set_long(pdev->config + pos + 4, 0x01000000); + /* PRI ENABLE bit writable */ + pci_set_long(pdev->wmask + pos + 4, 0x00000001); + /* PRI Capacity Supported */ + pci_set_long(pdev->config + pos + 8, 0x00000080); + /* PRI Allocations Allowed, 32 */ + pci_set_long(pdev->config + pos + 12, 0x00000040); + pci_set_long(pdev->wmask + pos + 12, 0x0000007f); + + pos +=3D 8; } =20 if (msi_init(pdev, 0, 1, true, false, errp)) { @@ -409,12 +641,24 @@ static void pci_edu_realize(PCIDevice *pdev, Error **= errp) memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, "edu-mmio", 1 * MiB); pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio); + + /* Register IOMMU listener */ + edu->iommu_listener =3D (MemoryListener) { + .name =3D "edu-iommu", + .region_add =3D edu_iommu_region_add, + .region_del =3D edu_iommu_region_del, + }; + + dma_as =3D pci_device_iommu_address_space(pdev); + memory_listener_register(&edu->iommu_listener, dma_as); } =20 static void pci_edu_uninit(PCIDevice *pdev) { EduState *edu =3D EDU(pdev); =20 + memory_listener_unregister(&edu->iommu_listener); + qemu_mutex_lock(&edu->thr_mutex); edu->stopping =3D true; qemu_mutex_unlock(&edu->thr_mutex); --=20 2.43.2