From patchwork Wed Feb 1 12:53:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 13124282 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 68F69C636CD for ; Wed, 1 Feb 2023 13:23:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=VrVE18CUp+2oppYxXXcVo+zRYXIcNOjichWM1z79Vz8=; b=rjyWokirdQmjr6 5mksfON1bNB/J+vldZmiFiM3qu9BNSFkxZQKZ3rJMa7RVlsnOEsJj4+A1gG3i9e48wbcu5SiWUkhx Qj2IC+KcjLhA5b8a0yL7zcZoxg1MsbqiLoMDV8L9HqjzL/KITgzx8prFCJSeYwL2QWSbZsp4MDAFD Y61f8ztD8RlkdoJ24yPdQsPWlUjVmD1uHo2mc0AZeVVGDI/aOWyw7YWQ1oivuptdIbgoZlFK3mOld ucy4PaNo8FuQE9ZwGPzOTGSnIFrVxAk3n1rBoVea68hmCjS69CnxYvaHw6EPhfhBRvvO7gm5FwVTC Ah3wUvmGX5cDsURfriVQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pND4Q-00C1nf-CF; Wed, 01 Feb 2023 13:22:38 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pND4I-00C1id-BI for linux-arm-kernel@bombadil.infradead.org; Wed, 01 Feb 2023 13:22:30 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=ZemYmGEwO1gb7z6YKtNUBIsszZurcCZTkm3NxNyR8KY=; b=VF66RYuiSNSQzysjVrD4XmZp1r KwrvEXlB3Cg9yaKy1Zj4JIbOR2l+I+CcLSGNHKnSWIJIoZdt1l3QeYp5SCQ78EVplCEnCjj2Rgeko MZdh/AMxoRa8UNy3ADwiVvVUwsV5OZ++FBo29HyKZt0nIRW2gGwL8pS9z2oSz1ohCz2saNt+SGvET HkKxg7BJyjwaBHWS637gf9QDYkdGbKl442ocXYtmPE+kXLRlfTksoNpMrd5HMSad1+QlmQiT0q7Dn whN7t6yqEP+RAGjOHzBZyZw7s33VtPw4r25F8DG9+Nbe3J1oa/wrWU3Jymh75Feu/uqT08FRKFw0Y IbYE8TTw==; Received: from mail-wr1-x42d.google.com ([2a00:1450:4864:20::42d]) by casper.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pNCiQ-00CIyN-4a for linux-arm-kernel@lists.infradead.org; Wed, 01 Feb 2023 12:59:56 +0000 Received: by mail-wr1-x42d.google.com with SMTP id r2so17219568wrv.7 for ; Wed, 01 Feb 2023 04:59:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; 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=ZemYmGEwO1gb7z6YKtNUBIsszZurcCZTkm3NxNyR8KY=; b=JOD8m4yzhH9gPfdkJLa+7RNLQC7WIcJKjPQe2frqePj3MBMrnCqzRD8MnDLYyAJrI/ Sg6Sbu8gNVeKJMv9yIUPA0lfo7Aie2omWbfh5YXJZbVUOKZL/DAneVLlWJdqDAMeaC1y rt2gbxdwPcUDyWQue47pDhzBpMR8EIcp6xqnOz+OyULHG4gI7L3PuBoNhffsm/JJXmzN U2m7KVpH3hkYk4tNgNgBr4V0gW1hOSVX7R1i4YPkmllBg2AMkelRDVo4m4/NYXGs1lPc Y3M5oZWSzjMx5G1IYBHDukSiGPsJqeK/YQJf+C7BbbeTCW42VGlJlC2miKsxNH4pSDqj XApw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=ZemYmGEwO1gb7z6YKtNUBIsszZurcCZTkm3NxNyR8KY=; b=2J1862SNmQDIDlngS2/OGvE8Mv+Xap5z2hAhVNw5P/JuDPutMjJh5YZjzrzeD7FPOB gw6qkQrgyE6dZhENjxBZOTGqp7FX9O5dPR4Mg8Qt36SDSC0pl6UESScnI/AVZjfzupvT GXfz8sXWznbVaUWt6Kn13mzeD0WRbO/WQSxITyGFIoFzjC2S/SmUQbm+zmFmYZhlFVJk v7k5hJdiwE7I7CIQOWnLNWTaBd5xazb+BftMtwJO6B7HQk48ZMNYwX4z3KBP/1TNjMpk CGozQIzxKyufKQBPJODOmLTBd/cbgvjneo4dhvNoS0GP+YNWaShCbSTX6sH1ovvYnDnk PZHA== X-Gm-Message-State: AO0yUKVrR46m1tyvIe/IuZ0k5H1yxlqGbcIn9WvLAST0WAoeWCS8Ol8z 7cKDi2PA8wjDJyOwKvSaBpAgvQ== X-Google-Smtp-Source: AK7set/TyPhNoqKUzXf4QDTT+ly131TfiVmHNekKz3oVZiuW5PpzJGZ8W/3imN/eBr/WwOkzC5/vTA== X-Received: by 2002:a5d:6110:0:b0:2bf:b9a4:f688 with SMTP id v16-20020a5d6110000000b002bfb9a4f688mr2377463wrt.23.1675256393453; Wed, 01 Feb 2023 04:59:53 -0800 (PST) Received: from localhost.localdomain (054592b0.skybroadband.com. [5.69.146.176]) by smtp.gmail.com with ESMTPSA id m15-20020a056000024f00b002bfae16ee2fsm17972811wrz.111.2023.02.01.04.59.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Feb 2023 04:59:53 -0800 (PST) From: Jean-Philippe Brucker To: maz@kernel.org, catalin.marinas@arm.com, will@kernel.org, joro@8bytes.org Cc: robin.murphy@arm.com, james.morse@arm.com, suzuki.poulose@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, smostafa@google.com, dbrazdil@google.com, ryan.roberts@arm.com, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, iommu@lists.linux.dev, Jean-Philippe Brucker Subject: [RFC PATCH 43/45] KVM: arm64: smmu-v3: Support power management Date: Wed, 1 Feb 2023 12:53:27 +0000 Message-Id: <20230201125328.2186498-44-jean-philippe@linaro.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230201125328.2186498-1-jean-philippe@linaro.org> References: <20230201125328.2186498-1-jean-philippe@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230201_125954_725385_16B3AF15 X-CRM114-Status: GOOD ( 19.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add power domain ops to the hypervisor IOMMU driver. We currently make these assumptions: * The register state is retained across power off. * The TLBs are clean on power on. * Another privileged software (EL3 or SCP FW) handles dependencies between SMMU and endpoints. So we just need to make sure that the CPU does not touch the SMMU registers while it is powered off. Signed-off-by: Jean-Philippe Brucker --- include/kvm/arm_smmu_v3.h | 4 +++ include/kvm/iommu.h | 4 +++ arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c | 12 +++++++ arch/arm64/kvm/hyp/nvhe/iommu/iommu.c | 36 +++++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/include/kvm/arm_smmu_v3.h b/include/kvm/arm_smmu_v3.h index 373b915b6661..d345cd616407 100644 --- a/include/kvm/arm_smmu_v3.h +++ b/include/kvm/arm_smmu_v3.h @@ -12,6 +12,9 @@ * Parameters from the trusted host: * @mmio_addr base address of the SMMU registers * @mmio_size size of the registers resource + * @caches_clean_on_power_on + * is it safe to elide cache and TLB invalidation commands + * while the SMMU is OFF * * Other members are filled and used at runtime by the SMMU driver. */ @@ -20,6 +23,7 @@ struct hyp_arm_smmu_v3_device { phys_addr_t mmio_addr; size_t mmio_size; unsigned long features; + bool caches_clean_on_power_on; void __iomem *base; u32 cmdq_prod; diff --git a/include/kvm/iommu.h b/include/kvm/iommu.h index 2bbe5f7bf726..ab888da731bc 100644 --- a/include/kvm/iommu.h +++ b/include/kvm/iommu.h @@ -3,6 +3,7 @@ #define __KVM_IOMMU_H #include +#include #include /* @@ -10,6 +11,7 @@ * @pgtable_cfg: page table configuration * @domains: root domain table * @nr_domains: max number of domains (exclusive) + * @power_domain: power domain information * * Other members are filled and used at runtime by the IOMMU driver. */ @@ -17,8 +19,10 @@ struct kvm_hyp_iommu { struct io_pgtable_cfg pgtable_cfg; void **domains; size_t nr_domains; + struct kvm_power_domain power_domain; struct io_pgtable_params *pgtable; + bool power_is_off; }; struct kvm_hyp_iommu_memcache { diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c index 56e313203a16..20610ebf04c2 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c @@ -83,6 +83,9 @@ static int smmu_add_cmd(struct hyp_arm_smmu_v3_device *smmu, int idx = Q_IDX(smmu, smmu->cmdq_prod); u64 *slot = smmu->cmdq_base + idx * CMDQ_ENT_DWORDS; + if (smmu->iommu.power_is_off) + return -EPIPE; + ret = smmu_wait_event(smmu, !smmu_cmdq_full(smmu)); if (ret) return ret; @@ -160,6 +163,9 @@ static int smmu_sync_ste(struct hyp_arm_smmu_v3_device *smmu, u32 sid) .cfgi.leaf = true, }; + if (smmu->iommu.power_is_off && smmu->caches_clean_on_power_on) + return 0; + return smmu_send_cmd(smmu, &cmd); } @@ -394,6 +400,9 @@ static void smmu_tlb_flush_all(void *cookie) .tlbi.vmid = data->domain_id, }; + if (smmu->iommu.power_is_off && smmu->caches_clean_on_power_on) + return; + WARN_ON(smmu_send_cmd(smmu, &cmd)); } @@ -409,6 +418,9 @@ static void smmu_tlb_inv_range(struct kvm_iommu_tlb_cookie *data, .tlbi.leaf = leaf, }; + if (smmu->iommu.power_is_off && smmu->caches_clean_on_power_on) + return; + /* * There are no mappings at high addresses since we don't use TTB1, so * no overflow possible. diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c index 0550e7bdf179..2fb5514ee0ef 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c @@ -327,10 +327,46 @@ phys_addr_t kvm_iommu_iova_to_phys(pkvm_handle_t iommu_id, return phys; } +static int iommu_power_on(struct kvm_power_domain *pd) +{ + struct kvm_hyp_iommu *iommu = container_of(pd, struct kvm_hyp_iommu, + power_domain); + + /* + * We currently assume that the device retains its architectural state + * across power off, hence no save/restore. + */ + hyp_spin_lock(&iommu_lock); + iommu->power_is_off = false; + hyp_spin_unlock(&iommu_lock); + return 0; +} + +static int iommu_power_off(struct kvm_power_domain *pd) +{ + struct kvm_hyp_iommu *iommu = container_of(pd, struct kvm_hyp_iommu, + power_domain); + + hyp_spin_lock(&iommu_lock); + iommu->power_is_off = true; + hyp_spin_unlock(&iommu_lock); + return 0; +} + +static const struct kvm_power_domain_ops iommu_power_ops = { + .power_on = iommu_power_on, + .power_off = iommu_power_off, +}; + int kvm_iommu_init_device(struct kvm_hyp_iommu *iommu) { + int ret; void *domains; + ret = pkvm_init_power_domain(&iommu->power_domain, &iommu_power_ops); + if (ret) + return ret; + domains = iommu->domains; iommu->domains = kern_hyp_va(domains); return pkvm_create_mappings(iommu->domains, iommu->domains +