From patchwork Thu Nov 26 14:49:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 11934197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-21.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4396C56202 for ; Thu, 26 Nov 2020 14:49:28 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4918520B80 for ; Thu, 26 Nov 2020 14:49:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="bUBbKRF2" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4918520B80 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe :List-Id:MIME-Version:Message-Id:Date:Subject:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Owner; bh=gBIYLVpsMhiod4P4Vg4GoHCj7LbquEaf3AdwqZGNHDg=; b=bUBbKRF28gfmtBX74bnKUsXi26 dsrtooQkWiQJen7W1gLvap7F0ufAVOLxbCZtt6fg/shUwAqK946DTzK88igS/MxC90QldmqO1D/YF zRFsX8irI3QRKmMsTQiRO8uGGgtHrqYb0y4VlgkT1d2YFw0Qu9ETVH/QF+zTftce14lA5E2eVlV02 bmovis2mwLzVCtJYANwfRNxyT7WaxZ9QamreKbAJY/LLk9zynBg5mc250ar0kLiHZPogxZaILBzW+ +JBKWicPySTZGAzueBf7wTdOUe5lcvVBNTFrRvrDEb7eMEVG1mZ/H/TqyPFkSvnEGdU+pxUl8/gL3 WQLP9PzQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kiIZH-0005im-Dw; Thu, 26 Nov 2020 14:48:19 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kiIZF-0005iL-3f for linux-arm-kernel@lists.infradead.org; Thu, 26 Nov 2020 14:48:18 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6E48731B; Thu, 26 Nov 2020 06:48:12 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7D6AC3F71F; Thu, 26 Nov 2020 06:48:11 -0800 (PST) From: Alexandru Elisei To: maz@kernel.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu Subject: [PATCH] KVM: arm64: Refuse to run VCPU if PMU is not initialized Date: Thu, 26 Nov 2020 14:49:16 +0000 Message-Id: <20201126144916.164075-1-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201126_094817_218454_A01CE19A X-CRM114-Status: GOOD ( 21.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 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 When enabling the PMU in kvm_arm_pmu_v3_enable(), KVM returns early if the PMU flag created is false and skips any other checks. Because PMU emulation is gated only on the VCPU feature being set, this makes it possible for userspace to get away with setting the VCPU feature but not doing any initialization for the PMU. Fix it by returning an error when trying to run the VCPU if the PMU hasn't been initialized correctly. The PMU is marked as created only if the interrupt ID has been set when using an in-kernel irqchip. This means the same check in kvm_arm_pmu_v3_enable() is redundant, remove it. Signed-off-by: Alexandru Elisei --- Patch is based on top of [1]. This has been reported at [2]. I tested the patch like in the report, with a modified version of kvmtool that sets the PMU feature, but doesn't do any initialization. Without this patch, when running the pmu kvm-unit-tests test, I get the warning described in the report. With this patch, KVM refuses to run the VCPU: $ ./lkvm-pmu run -c1 -m 64 -f /path/to/arm/pmu.flat --pmu -p cycle-counter # lkvm run --firmware /path/to/arm/pmu.flat -m 64 -c 1 --name guest-207 Info: Placing fdt at 0x80200000 - 0x80210000 KVM_RUN failed: Invalid argument I also tested what happens if I run a Linux guest without this patch with the modified version of kvmtool. The PMU is detected, but the guest doesn't receive any PMU interrupts. With this patch, KVM refuses to run the VCPU. I decided to return -EINVAL instead of -ENOEXEC because that is the error code that kvm_arm_pmu_v3_enable() was already returning if the interrupt ID was not initialized, which implies that the PMU hadn't been initialized. I also noticed that there are other places which return different error codes for KVM_RUN, and I'm in the process of untangling that to send a patch to document them. [1] https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git/log/?h=queue [2] https://www.spinics.net/lists/arm-kernel/msg857927.html arch/arm64/kvm/pmu-emul.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 643cf819f3c0..398f6df1bbe4 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -825,9 +825,12 @@ bool kvm_arm_support_pmu_v3(void) int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu) { - if (!vcpu->arch.pmu.created) + if (!kvm_vcpu_has_pmu(vcpu)) return 0; + if (!vcpu->arch.pmu.created) + return -EINVAL; + /* * A valid interrupt configuration for the PMU is either to have a * properly configured interrupt number and using an in-kernel @@ -835,9 +838,6 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu) */ if (irqchip_in_kernel(vcpu->kvm)) { int irq = vcpu->arch.pmu.irq_num; - if (!kvm_arm_pmu_irq_initialized(vcpu)) - return -EINVAL; - /* * If we are using an in-kernel vgic, at this point we know * the vgic will be initialized, so we can check the PMU irq