From patchwork Tue Oct 12 04:35:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551355 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41A38C433F5 for ; Tue, 12 Oct 2021 04:36:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2368A61040 for ; Tue, 12 Oct 2021 04:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232361AbhJLEiO (ORCPT ); Tue, 12 Oct 2021 00:38:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37092 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229593AbhJLEiN (ORCPT ); Tue, 12 Oct 2021 00:38:13 -0400 Received: from mail-qv1-xf49.google.com (mail-qv1-xf49.google.com [IPv6:2607:f8b0:4864:20::f49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 596FDC061570 for ; Mon, 11 Oct 2021 21:36:12 -0700 (PDT) Received: by mail-qv1-xf49.google.com with SMTP id t3-20020a056214154300b00383496932feso8878593qvw.6 for ; Mon, 11 Oct 2021 21:36:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=MgUI8dr71wiUF9Cg1eutjpaNE80Sfg4+1lD1k7gsd/M=; b=VuhEW5SxS1LqbD1y6W2u5fujsSWvlKITcaC+DfzF+nbgthQHFlCdofRA8Pi8vjahVC zj5zQtHgIuUulE5UV8fh2IwmG0qfPMjxzv4Je1fkjXzNToQ1TIi+isd08BO+cHpf5mov GmjnInH4aCSFrGLvvSDPH1qi1c0JUrr9tj+w/BIlW7hXWPzqtAYmhtej7Tn4nhbt1g2L /0kQzyKo+7Q8e5Igsao58iALORgjb0FH2nN+mof+i0fYRMQZ6jHwDhydsKPpT3TPWrqi beLVi1ReaNB51oUSUxAxWkT0IUBzCucR/GAogYdticZGdaMWLM519PKt+Oh3nLkuZcym 8cWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=MgUI8dr71wiUF9Cg1eutjpaNE80Sfg4+1lD1k7gsd/M=; b=lVE1++KYIdmRRsZZFHiKi0Xwp21Q+tMiSI7Itg8Wt4CXwUiT2YWZPUdGTsiuo9CllU gXdP7HqzvkQdyfwgcaLcNXq243C2hNFeltBskvFgJFT1D3dk0UZnvZk/Hs7yhk/fEfGW ZNMdWbZcmhGxoRFWHU5VN5JTUEn2FSV4iAObAq49K8Sg/wvPXQo0fkSMqSRcktM+Xp5e 1vdg3igMWOkPpByFEVW7BaJ3MlwfzePNUwlSFIcr7K5yP0JdYI3C8cSClrY2d6CqjPkg yvLmeIpmqUUw3eMJ4YCfDxlXLyZK8H++/kYTPQFJ2tYNKtczPPVPL4f2uOO1928ZqV10 fwBA== X-Gm-Message-State: AOAM531YE4JZw6M5fKqIN7d8eDNamdyv+g/KMtXrvselCAKQy2Tl5c1j oc28qDUhukVeY493DLpP0wKqxD1iLI0= X-Google-Smtp-Source: ABdhPJy2iKOySRcH3Ml4eFC4AOnvEXGxnJDRyYb6ehxJKmextSbm1vjwq+zjkblu6svI8PlWaI/8labARB4= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:ac8:202:: with SMTP id k2mr20117332qtg.398.1634013370868; Mon, 11 Oct 2021 21:36:10 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:11 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-2-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 01/25] KVM: arm64: Add has_reset_once flag for vcpu From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce 'has_reset_once' flag in kvm_vcpu_arch, which indicates if the vCPU reset has been done once, for later use. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/kvm/reset.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index f8be56d5342b..9b5e7a3b6011 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -384,6 +384,7 @@ struct kvm_vcpu_arch { u64 last_steal; gpa_t base; } steal; + bool has_reset_once; }; /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ @@ -449,6 +450,7 @@ struct kvm_vcpu_arch { #define vcpu_has_sve(vcpu) (system_supports_sve() && \ ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE)) +#define vcpu_has_reset_once(vcpu) ((vcpu)->arch.has_reset_once) #ifdef CONFIG_ARM64_PTR_AUTH #define vcpu_has_ptrauth(vcpu) \ diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 5ce36b0a3343..4d34e5c1586c 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -305,6 +305,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) if (loaded) kvm_arch_vcpu_load(vcpu, smp_processor_id()); preempt_enable(); + + if (!ret && !vcpu->arch.has_reset_once) + vcpu->arch.has_reset_once = true; + return ret; } From patchwork Tue Oct 12 04:35:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551357 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14998C433F5 for ; Tue, 12 Oct 2021 04:36:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ED6DD61039 for ; Tue, 12 Oct 2021 04:36:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232383AbhJLEiY (ORCPT ); Tue, 12 Oct 2021 00:38:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37136 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232374AbhJLEiX (ORCPT ); Tue, 12 Oct 2021 00:38:23 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 997DCC061570 for ; Mon, 11 Oct 2021 21:36:22 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id x16-20020a25b910000000b005b6b7f2f91cso26132800ybj.1 for ; Mon, 11 Oct 2021 21:36:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Z93DnbmChJRf3NM+LBnf4mN1DuMUD7rE5aIVZuW+HL0=; b=PtmrX72/0sGKpcnwJcLOf/UaKOFDQ+5S9S3IlXTMv7zJdIXpUksHL2ftiSNgSk+z4k QOVclAU5P4X9Hn/pdysFT9NVb9xUfiDDVUgHRpOzN5LQ0JSb/wOCRbJJLEiYyco6fVbu 0dct7uPkpb+K55Tzg9Gfo7gpLDvfMVS9w3HYEaFzgieo2h7wFwYVqKhDi16h4WNF0HM6 sw460YgYVjor3ULd0thxbX/NpQjjrrRfhAtzLlaJ779WGCI1aVuC8OWNxBREIKeEHjkR hXo2+jdZnTNhicSObQee3qNLC3uIHFMl5aYoQu/ZDSiFcrcch4+zkqs/q77gbV5eKKfe Lvew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Z93DnbmChJRf3NM+LBnf4mN1DuMUD7rE5aIVZuW+HL0=; b=JIAa7oqw5V+fLZLy/06ghPyMwl47lrjfScub+uaf6UQ6KOMeymjTQbNkIoSRC+KmIM dNFKi9KNgpNM6i3+WoU1U7K4D34ZyxLphFahhQru4tf2xPdIanp90/JeckD4OLHNpxf5 779ubLln8cw8i8UcHCmxiRhFJnAUOS319viBMAiupwLc4aXEbuvKZQR6YYEdlyzXkPQr 1KrU2SZuQdUbQ1+DI6guzSQ8uxKgFixd4ZOExS4oFX1TRHl0s6KuMfs/IOxTY3F+HvY1 NCUhJ9EP/2WEZqleZWd0sCkf1i2k48h88Nm9RpUheHHwA+WKQNvmHJXQJi7/cJ6x4qAS 2slw== X-Gm-Message-State: AOAM530LGKGuFToPLezljbl4asK4vQvkp4JX9whfIYEM679IQ+F7H85y YONg57xf7l5YDHZ59bYjnaQnnSV1svs= X-Google-Smtp-Source: ABdhPJyItztYg/nGIOk04Hx9xUnOSJKLgu2KzOyCL+f/o2RFo4gV8CWyqEUbibEQ2BnxvEaZPLTO7gz/xB8= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a25:2e01:: with SMTP id u1mr17924282ybu.363.1634013381864; Mon, 11 Oct 2021 21:36:21 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:12 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-3-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 02/25] KVM: arm64: Save ID registers' sanitized value per vCPU From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Extend sys_regs[] of kvm_cpu_context for ID registers and save ID registers' sanitized value in the array for the vCPU at the first vCPU reset. Use the saved ones when ID registers are read by userspace (via KVM_GET_ONE_REG) or the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 10 ++++++++++ arch/arm64/kvm/sys_regs.c | 26 ++++++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 9b5e7a3b6011..0cd351099adf 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -145,6 +145,14 @@ struct kvm_vcpu_fault_info { u64 disr_el1; /* Deferred [SError] Status Register */ }; +/* + * (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2), + * where 0<=crm<8, 0<=op2<8. + */ +#define KVM_ARM_ID_REG_MAX_NUM 64 +#define IDREG_IDX(id) ((sys_reg_CRm(id) << 3) | sys_reg_Op2(id)) +#define IDREG_SYS_IDX(id) (ID_REG_BASE + IDREG_IDX(id)) + enum vcpu_sysreg { __INVALID_SYSREG__, /* 0 is reserved as an invalid value */ MPIDR_EL1, /* MultiProcessor Affinity Register */ @@ -209,6 +217,8 @@ enum vcpu_sysreg { CNTP_CVAL_EL0, CNTP_CTL_EL0, + ID_REG_BASE, + ID_REG_END = ID_REG_BASE + KVM_ARM_ID_REG_MAX_NUM - 1, /* Memory Tagging Extension registers */ RGSR_EL1, /* Random Allocation Tag Seed Register */ GCR_EL1, /* Tag Control Register */ diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 1d46e185f31e..72ca518e7944 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -273,7 +273,7 @@ static bool trap_loregion(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1); + u64 val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(SYS_ID_AA64MMFR1_EL1)); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { @@ -1059,12 +1059,11 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, return true; } -/* Read a sanitised cpufeature ID register by sys_reg_desc */ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r, bool raz) { u32 id = reg_to_encoding(r); - u64 val = raz ? 0 : read_sanitised_ftr_reg(id); + u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { case SYS_ID_AA64PFR0_EL1: @@ -1174,6 +1173,16 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu, return REG_HIDDEN; } +static void reset_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) +{ + u32 id = reg_to_encoding(rd); + + if (vcpu_has_reset_once(vcpu)) + return; + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = read_sanitised_ftr_reg(id); +} + static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, const struct kvm_one_reg *reg, void __user *uaddr) @@ -1219,9 +1228,7 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, /* * cpufeature ID register user accessors * - * For now, these registers are immutable for userspace, so no values - * are stored, and for set_id_reg() we don't allow the effective value - * to be changed. + * We don't allow the effective value to be changed. */ static int __get_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, void __user *uaddr, @@ -1375,6 +1382,7 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu, #define ID_SANITISED(name) { \ SYS_DESC(SYS_##name), \ .access = access_id_reg, \ + .reset = reset_id_reg, \ .get_user = get_id_reg, \ .set_user = set_id_reg, \ .visibility = id_visibility, \ @@ -1830,8 +1838,10 @@ static bool trap_dbgdidr(struct kvm_vcpu *vcpu, if (p->is_write) { return ignore_write(vcpu, p); } else { - u64 dfr = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1); - u64 pfr = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); + u64 dfr = __vcpu_sys_reg(vcpu, + IDREG_SYS_IDX(SYS_ID_AA64DFR0_EL1)); + u64 pfr = __vcpu_sys_reg(vcpu, + IDREG_SYS_IDX(SYS_ID_AA64PFR0_EL1)); u32 el3 = !!cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR0_EL3_SHIFT); p->regval = ((((dfr >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) << 28) | From patchwork Tue Oct 12 04:35:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551359 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60DD7C433FE for ; Tue, 12 Oct 2021 04:36:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 49DA560EE5 for ; Tue, 12 Oct 2021 04:36:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232387AbhJLEiZ (ORCPT ); Tue, 12 Oct 2021 00:38:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232374AbhJLEiY (ORCPT ); Tue, 12 Oct 2021 00:38:24 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D472BC061570 for ; Mon, 11 Oct 2021 21:36:23 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id q3-20020aa79823000000b0044d24283b63so2378066pfl.5 for ; Mon, 11 Oct 2021 21:36:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ydcMqLw7I27y2BCq9xNW2IjPYrEmatmYQFDkuaqb6Ys=; b=fIhPep5xebOqDQxahAlQRhWaep55nEzLGFccYceuEdkPcptnR+qdgdjVxdKBQOKL7j /tnOstI0GSmvqfOb4XGBwZzcrcDFLol9FioWZfD7GNS2DPRDWI68dqEvItZb0sgHLuHa jV/G1BuwMRyZxX+4fA7gQ2YkeeOZr/dW/JbplrSneEEVF63KHueJ5KvilT1j3lzTVa8n lxSSq5tcFDBVmjBEyq8gwcDpMGWwIx5GMmTvxL7XQEwRyejlBwuingxhY6gK7+Gg9hcU aewGN/fbd3gWPBIyL5NAMYGuvQv+7XyE1JGWJ84mqCibVWmSZuzlIUE3lNn0ErvlDlTN qeKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ydcMqLw7I27y2BCq9xNW2IjPYrEmatmYQFDkuaqb6Ys=; b=im8y5uqCxvm/zxbBFIMsogamYYZStxLt4U9xlVI53pXPb2l8ckJCwXHfO89r84866Z n7zpFMlQodhPNKbf15MOI8ToUag8KzMi8cLCMbG3Cz3Jy+EDuS0KzAGdOfD1eC7R6nH2 o4nOtLdsI/cmJX5KnNK6Rb2eTASexUgYP9CAjoRQS+hqPaXrmCmwcyIz3B0QdMSIrXpE Ir1xZ6e9Rhp3JG3BuSFc46tVfstRCrCLRLYqdTpLzGSs5pQDUYFM3CttAkWSipZkWHkf +u8vWw9pybcmt2Tccwo7wrT1+ke4+Sta1QG86d/QHYEfec4/8huqrqL0t0R/HdsgD7Tt QcLQ== X-Gm-Message-State: AOAM531aaaCmv+JCPJS0knSscxloiINQGEJg0SfrabAzW+AqlcWtJHYe rAs80vxz8riapvLLNb411V7pycg9PAw= X-Google-Smtp-Source: ABdhPJxJkSl8XzKYhkBIAFMBll8PIXQOz4AtNn7iEoWt6JG9RA/u+2uTfezIu6/nxTTDqGUsD6OE9/ryTQ0= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a05:6a00:140e:b0:444:b077:51ef with SMTP id l14-20020a056a00140e00b00444b07751efmr25307458pfu.61.1634013383274; Mon, 11 Oct 2021 21:36:23 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:13 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-4-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 03/25] KVM: arm64: Introduce a validation function for an ID register From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce arm64_check_features(), which does a basic validity checking of an ID register value against the register's limit value that KVM can support. This function will be used by the following patches to check if an ID register value that userspace tries to set can be supported by KVM on the host. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/cpufeature.h | 1 + arch/arm64/kernel/cpufeature.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index ef6be92b1921..eda7ddbed8cf 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -631,6 +631,7 @@ void check_local_cpu_capabilities(void); u64 read_sanitised_ftr_reg(u32 id); u64 __read_sysreg_by_encoding(u32 sys_id); +int arm64_check_features(u32 sys_reg, u64 val, u64 limit); static inline bool cpu_supports_mixed_endian_el0(void) { diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 6ec7036ef7e1..d146ef759435 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -3114,3 +3114,29 @@ ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, return sprintf(buf, "Vulnerable\n"); } } + +/* + * Check if all features that are indicated in the given ID register value + * ('val') are also indicated in the 'limit'. + */ +int arm64_check_features(u32 sys_reg, u64 val, u64 limit) +{ + struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg); + const struct arm64_ftr_bits *ftrp; + u64 exposed_mask = 0; + + if (!reg) + return -ENOENT; + + for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) { + if (arm64_ftr_value(ftrp, val) > arm64_ftr_value(ftrp, limit)) + return -E2BIG; + + exposed_mask |= arm64_ftr_mask(ftrp); + } + + if (val & ~exposed_mask) + return -E2BIG; + + return 0; +} From patchwork Tue Oct 12 04:35:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551361 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7663C4332F for ; Tue, 12 Oct 2021 04:36:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB67661056 for ; Tue, 12 Oct 2021 04:36:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232404AbhJLEi1 (ORCPT ); Tue, 12 Oct 2021 00:38:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37154 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232401AbhJLEi0 (ORCPT ); Tue, 12 Oct 2021 00:38:26 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 893A8C06161C for ; Mon, 11 Oct 2021 21:36:25 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id s6-20020a254506000000b005b6b6434cd6so25796217yba.9 for ; Mon, 11 Oct 2021 21:36:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=yO1PAz+jT8UeVSC81HcgY5AK6Wp3sOfwLOCbdKGHTBw=; b=BNMh2xxk+NtYYpDrk/F6E2XihCZLns3ZajqJY9EWMKkEcI1BQYLEMvy1PTCRgIY3oK WGGj1bhWXocOkgj3HLp2GsnRL41t5Rb9bsolj9QGpfKQ27poteViLTX0mbXXaIH77PWQ WtsXuG/mciEBgqSyGF6MIR3h59oj02cOW2YYFL+LGTNxlOP47DdEpb1KWzMSO423eo5Q YTxBOw/oKjUS+lMstg8DVrUBxkmUHnmMSntWxhL07jYhaJwPn6OXc7G6KLJJphJub6Pr WAHY2oZdrrr27gEWVh3JWA9v3wJFm7ako3ckNcQP3XNa9Bh3rAv+JX+cgjPeBxQ9uM2s 0DyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=yO1PAz+jT8UeVSC81HcgY5AK6Wp3sOfwLOCbdKGHTBw=; b=hVdqX9bl/uBw8z8I9UaqGHZqPYlVj7I6t9VNXkR+wMAbpQced9zd5ONry1QBOg7kqv O/T1FaSCoDLD1rA7WTDFe+drHUvwcSE8sCDbQ17V9O2lTjTGoX8jGLLtz8H82M8bY9sf ZZFuj8ZROhYCHosVl5//3xwOgrO+98VV/funL8XgJ4fKAd02us3KcgOH2gxwQbZK5t1X eNkDGxmoljOswdvkYEI9Iyvcyq5Vxj1fzKoDqcnkg2AQVniy5RQSka4Aaz8H+JoNN1Q5 qrSNjb9sH8Yp3bQQsLGSnbfUs7ltazBMLlLh5x3fiZM5nqyn+ruJaFroogILkNDd6h+p Sw6w== X-Gm-Message-State: AOAM533jm2CSozMkoIQBqIUSmYwBwKJIF2P5u3EWAwxN35RZ1AfVLvCq oQD80qkZ+c9Kg3z6C/F5DStOSU8uQ0U= X-Google-Smtp-Source: ABdhPJxyJgraJ5AwHDPgzY9D+WbTlXuTeuy8jGj0LsPS3K2cu1koz8V6Ofx9NP2uOkX2rIeFqYI8ykM2HaI= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a25:517:: with SMTP id 23mr26194996ybf.496.1634013384822; Mon, 11 Oct 2021 21:36:24 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:14 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-5-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 04/25] KVM: arm64: Introduce struct id_reg_info From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch lays the groundwork to make ID registers writable. Introduce struct id_reg_info for an ID register to manage the register specific control of its value for the guest. It is used to do register specific initialization, validation of the ID register and etc. Not all ID registers must have the id_reg_info. ID registers that don't have the id_reg_info are handled in a common way that is applied to all other ID registers. At present, changing an ID register from userspace is allowed only if the ID register has the id_reg_info, but that will be changed by the following patches. No ID register has the structure yet and the following patches will add the id_reg_info for some ID registers. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 120 +++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 72ca518e7944..8a0b88f9a975 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -263,6 +263,76 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, return read_zero(vcpu, p); } +struct id_reg_info { + u32 sys_reg; /* Register ID */ + u64 sys_val; /* Sanitized system value */ + + /* + * Limit value of the register for a vcpu. The value is sys_val + * with bits cleared for unsupported features for the guest. + */ + u64 vcpu_limit_val; + + /* Bits that are not validated when userspace sets the register. */ + u64 ignore_mask; + + /* Initialization function of the id_reg_info */ + void (*init)(struct id_reg_info *id_reg); + + /* Register specific validation function */ + int (*validate)(struct kvm_vcpu *vcpu, u64 val); + + /* Return the reset value of the register for the vCPU */ + u64 (*get_reset_val)(struct kvm_vcpu *vcpu, struct id_reg_info *id_reg); +}; + +static void id_reg_info_init(struct id_reg_info *id_reg) +{ + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + id_reg->vcpu_limit_val = id_reg->sys_val; +} + +/* + * An ID register that needs special handling to control the value for the + * guest must have its own id_reg_info in id_reg_info_table. + * (i.e. the reset value is different from the host's sanitized value, + * the value is affected by opt-in features, some fields needs specific + * validation, etc.) + */ +#define GET_ID_REG_INFO(id) (id_reg_info_table[IDREG_IDX(id)]) +static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = {}; + +static int validate_id_reg(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd, u64 val) +{ + u32 id = reg_to_encoding(rd); + const struct id_reg_info *id_reg = GET_ID_REG_INFO(id); + u64 limit; + u64 check_val = val; + int err; + + if (id_reg) { + /* + * Clear bits with ignore_mask, which we don't want + * arm64_check_features to check. + */ + check_val &= ~id_reg->ignore_mask; + limit = id_reg->vcpu_limit_val; + } else + limit = read_sanitised_ftr_reg(id); + + /* Check if the value indicates any feature that is not in the limit. */ + err = arm64_check_features(id, check_val, limit); + if (err) + return err; + + if (id_reg && id_reg->validate) + /* Run the ID register specific validity check. */ + err = id_reg->validate(vcpu, val); + + return err; +} + /* * ARMv8.1 mandates at least a trivial LORegion implementation, where all the * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0 @@ -1176,11 +1246,19 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu, static void reset_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { u32 id = reg_to_encoding(rd); + struct id_reg_info *id_reg; + u64 val; if (vcpu_has_reset_once(vcpu)) return; - __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = read_sanitised_ftr_reg(id); + id_reg = GET_ID_REG_INFO(id); + if (id_reg && id_reg->get_reset_val) + val = id_reg->get_reset_val(vcpu, id_reg); + else + val = read_sanitised_ftr_reg(id); + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = val; } static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, @@ -1225,11 +1303,7 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, return 0; } -/* - * cpufeature ID register user accessors - * - * We don't allow the effective value to be changed. - */ +/* cpufeature ID register user accessors */ static int __get_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, void __user *uaddr, bool raz) @@ -1240,11 +1314,12 @@ static int __get_id_reg(const struct kvm_vcpu *vcpu, return reg_to_user(uaddr, &val, id); } -static int __set_id_reg(const struct kvm_vcpu *vcpu, +static int __set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, void __user *uaddr, bool raz) { const u64 id = sys_reg_to_index(rd); + u32 encoding = reg_to_encoding(rd); int err; u64 val; @@ -1252,10 +1327,18 @@ static int __set_id_reg(const struct kvm_vcpu *vcpu, if (err) return err; - /* This is what we mean by invariant: you can't change it. */ - if (val != read_id_reg(vcpu, rd, raz)) + /* Don't allow to change the reg unless the reg has id_reg_info */ + if (val != read_id_reg(vcpu, rd, raz) && !GET_ID_REG_INFO(encoding)) return -EINVAL; + if (raz) + return (val == 0) ? 0 : -EINVAL; + + err = validate_id_reg(vcpu, rd, val); + if (err) + return err; + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(encoding)) = val; return 0; } @@ -2818,6 +2901,23 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) return write_demux_regids(uindices); } +static void id_reg_info_init_all(void) +{ + int i; + struct id_reg_info *id_reg; + + for (i = 0; i < ARRAY_SIZE(id_reg_info_table); i++) { + id_reg = (struct id_reg_info *)id_reg_info_table[i]; + if (!id_reg) + continue; + + if (id_reg->init) + id_reg->init(id_reg); + else + id_reg_info_init(id_reg); + } +} + void kvm_sys_reg_table_init(void) { unsigned int i; @@ -2852,4 +2952,6 @@ void kvm_sys_reg_table_init(void) break; /* Clear all higher bits. */ cache_levels &= (1 << (i*3))-1; + + id_reg_info_init_all(); } From patchwork Tue Oct 12 04:35:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551363 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78A47C433F5 for ; Tue, 12 Oct 2021 04:36:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 585E861076 for ; Tue, 12 Oct 2021 04:36:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232401AbhJLEi2 (ORCPT ); Tue, 12 Oct 2021 00:38:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232419AbhJLEi1 (ORCPT ); Tue, 12 Oct 2021 00:38:27 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9BA1C06161C for ; Mon, 11 Oct 2021 21:36:26 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id my5-20020a17090b4c8500b001a0bf4025c1so88973pjb.8 for ; Mon, 11 Oct 2021 21:36:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=N5SZSA+fUqRTbjo35OUmhwDTNPioIOsC+zg6mLlAOeI=; b=Frtj842iBGMNrPh6OG3pi0Ms5HCdrLoaoymnVC+SUwO8+nKGBSOJVdpZwwm/QTQbF8 OTYgVScpMIOT0ud7g2c8hytKJ2CjSjDz8M4XdeW7TJqSm2DEPdgyODcnwhB2ODPv6mBy aCnGplUEJ7fzS1cDJvyDiowSxXzf1dgt50MFJ/Uk5H21JMyKTRiuLsErBtQwO2+JItNz iBxKlc8wMy4/NwvNuNqhflcxOhfd2YbyIgr5mN/ngArSdHJllHqhq/3p1yIaKfs1EZGh Cvc+6I1dKsoE3RBupUrn125tyGYruhnhJUP/+o/18uTjunuMSuy2ARiKdbaEzViiwxtU j8Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=N5SZSA+fUqRTbjo35OUmhwDTNPioIOsC+zg6mLlAOeI=; b=TBml0uj5if1QHJwO8nh+V56DyVwbV3uuIC20ODA4Rx7wHtsdvAbzUPozwhuXM72lJ2 vrfHYKZHz25yrtzycfKWZcx7Wr0qcXk0UrPXFEcRwcRMt/YSpi8XPfuV2Otwzhg8iLZV Vc5884c+R2q7tuMCaioGOEZCSBRqcUREyAHbrF0Z6l2dDiPdknhYlB4dtYK5vdmF81ic N7EyUFXNGDbVDQCgtLXCefKMK+7MAgcq9ZD2hwagEgaEZ51GRmStaZJLIEM2B0uMqRWn 9lAb/HMnZq/ir7IVN9/75P2eZqHLINY4gxifO95uuNHw9pL7dASfI+cnd8rr2eyM4qOs gNPQ== X-Gm-Message-State: AOAM530gWQwh2g7dfxHNL8qbuf0QVFa29wRz0imvdzV05+0lfMi4bpEs mbaRpF6I+zQifa88MR6HFO2QkgoDpI0= X-Google-Smtp-Source: ABdhPJxq/Mk4VVM9slvxTOJugnOnUA71qyKTuAL0h3f8/ueBhLbCcxivpgKtoQVfP4/2KUnvpPsw8Foxo9o= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a62:60c7:0:b0:40a:4bd7:752c with SMTP id u190-20020a6260c7000000b0040a4bd7752cmr29343562pfb.52.1634013386318; Mon, 11 Oct 2021 21:36:26 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:15 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-6-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 05/25] KVM: arm64: Keep consistency of ID registers between vCPUs From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org All vCPUs that are owned by a VM must have the same values of ID registers. Return an error at the very first KVM_RUN for a vCPU if the vCPU has different values in any ID registers from any other vCPUs that have already started KVM_RUN once. Also, return an error if userspace tries to change a value of ID register for a vCPU that already started KVM_RUN once. Changing ID register is still not allowed at present though. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/kvm/arm.c | 3 +++ arch/arm64/kvm/sys_regs.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 0cd351099adf..69af669308b0 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -745,6 +745,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, struct kvm_arm_copy_mte_tags *copy_tags); +int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu); + /* Guest/host FPSIMD coordination helpers */ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index fe102cd2e518..45ca72a37872 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -620,6 +620,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) ret = kvm_arm_pmu_v3_enable(vcpu); + if (kvm_id_regs_consistency_check(vcpu)) + return -EPERM; + return ret; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 8a0b88f9a975..2fe3121d50ca 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1331,6 +1331,10 @@ static int __set_id_reg(struct kvm_vcpu *vcpu, if (val != read_id_reg(vcpu, rd, raz) && !GET_ID_REG_INFO(encoding)) return -EINVAL; + /* Don't allow to change the reg after the first KVM_RUN. */ + if (vcpu->arch.has_run_once) + return -EINVAL; + if (raz) return (val == 0) ? 0 : -EINVAL; @@ -2901,6 +2905,33 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) return write_demux_regids(uindices); } +int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu) +{ + int i; + const struct kvm_vcpu *t_vcpu; + + /* + * Make sure vcpu->arch.has_run_once is visible for others so that + * ID regs' consistency between two vCPUs is checked by either one + * at least. + */ + smp_mb(); + WARN_ON(!vcpu->arch.has_run_once); + + kvm_for_each_vcpu(i, t_vcpu, vcpu->kvm) { + if (!t_vcpu->arch.has_run_once) + /* ID regs still could be updated. */ + continue; + + if (memcmp(&__vcpu_sys_reg(vcpu, ID_REG_BASE), + &__vcpu_sys_reg(t_vcpu, ID_REG_BASE), + sizeof(__vcpu_sys_reg(vcpu, ID_REG_BASE)) * + KVM_ARM_ID_REG_MAX_NUM)) + return -EINVAL; + } + return 0; +} + static void id_reg_info_init_all(void) { int i; From patchwork Tue Oct 12 04:35:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551365 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4033C4332F for ; Tue, 12 Oct 2021 04:36:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C9F8960EE2 for ; Tue, 12 Oct 2021 04:36:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232434AbhJLEia (ORCPT ); Tue, 12 Oct 2021 00:38:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232435AbhJLEi3 (ORCPT ); Tue, 12 Oct 2021 00:38:29 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 69D37C06161C for ; Mon, 11 Oct 2021 21:36:28 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id z23-20020a17090ab11700b001a070e36178so4795155pjq.3 for ; Mon, 11 Oct 2021 21:36:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=8dyVGfAnuSsD7UrU7Jpca57tmjUFZ9tgf846YFvtQus=; b=MU5wc9JaWIkqs29sBWrh9t/iwC/kaoJ0NbY49k7DmIsTXOhYUOst5jf47tHAdYplYv s2V/XLrwYcA4Mv5dh1FdsxjCEYnW40QVgHx4byeiyvEe9Va9sdxhyVFsNSfqqv+PAdlw XQrL9Ew8SGxpg/yAa+r13xCPIeizCn8QOrrxFJChjV7PZHwcNOfYUM6AiPmWqJpUDVCy zw/gQ9dsLwe/zZyWyXwGE+I5/9pmg61jrGOjK2YUg3jaOC2fueAUgeCLuh94hkD15QJC Rk1ataJtSA9zTN84rcsHGwiSQJs5q0AhdLfWIgzKlAsk9FfBiL3xyGJEhSONxSQunrRk w9nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=8dyVGfAnuSsD7UrU7Jpca57tmjUFZ9tgf846YFvtQus=; b=Lto3jYKSu2lyGQ+roRTGSA9AgPEfg3GB47GYYHdX6n1s7cksM1EOxZyLwYKkbtny2z 1dR93WBmsxwSDcCG4G36Vd7tyjXb3JkZT4O57YtG3Ao4IuIpw2pmI1oSecrmImEsX040 C4AG2CN/1GnwMVcvp+9CIFTussr2pJ8NxOptByLLhrxdKt6Q6+W7hDBw1Pu5qtnMCpEw xWaGo0iMECKlEocKr4vEGC2qlqjwB7JYsTy797l2BFcS8TbfFoIgyZJcmKmAqqxnOx9q H21D2OnMH673IVQCu/HV7jx1ItsQ52Dwd4QjRWlGlTmznGo3coWMdo35i4rQ1WWpmhgv AeBw== X-Gm-Message-State: AOAM5334pT01fX05B5j7zaNy8KVwAfqGxvYEgPudFCbQrq8vr1pSasLP T1qrwH1RZdfYjJKZP23kmq228XSMFV4= X-Google-Smtp-Source: ABdhPJytscYTGanXbYPD6/p7iTUsHexrmM0h47PIy7A3vZnUsTqBd51ijOyJtUhF1C1RuP4Fw6JbzZfhKzM= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:aa7:9047:0:b0:44b:e142:8b0d with SMTP id n7-20020aa79047000000b0044be1428b0dmr29594344pfo.45.1634013387945; Mon, 11 Oct 2021 21:36:27 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:16 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-7-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 06/25] KVM: arm64: Make ID_AA64PFR0_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_AA64PFR0_EL1 to make it writable by userspace. The CSV2/CSV3 fields of the register were already writable and values that were written for them affected all vCPUs before. Now they only affect the vCPU. Return an error if userspace tries to set SVE field of the register to a value that conflicts with SVE configuration for the guest (via KVM_ARM_VCPU_INIT). SIMD/FP/SVE fields of the requested value are validated according to Arm ARM. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 3 - arch/arm64/kvm/arm.c | 18 ----- arch/arm64/kvm/sys_regs.c | 122 +++++++++++++++++------------- 3 files changed, 68 insertions(+), 75 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 69af669308b0..691cb6ee0f5c 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -131,9 +131,6 @@ struct kvm_arch { unsigned long *pmu_filter; unsigned int pmuver; - u8 pfr0_csv2; - u8 pfr0_csv3; - /* Memory Tagging Extension enabled for the guest */ bool mte_enabled; }; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 45ca72a37872..820f35051d77 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -114,22 +114,6 @@ static int kvm_arm_default_max_vcpus(void) return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; } -static void set_default_spectre(struct kvm *kvm) -{ - /* - * The default is to expose CSV2 == 1 if the HW isn't affected. - * Although this is a per-CPU feature, we make it global because - * asymmetric systems are just a nuisance. - * - * Userspace can override this as long as it doesn't promise - * the impossible. - */ - if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED) - kvm->arch.pfr0_csv2 = 1; - if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED) - kvm->arch.pfr0_csv3 = 1; -} - /** * kvm_arch_init_vm - initializes a VM data structure * @kvm: pointer to the KVM struct @@ -155,8 +139,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) /* The maximum number of VCPUs is limited by the host's GIC model */ kvm->arch.max_vcpus = kvm_arm_default_max_vcpus(); - set_default_spectre(kvm); - return ret; out_free_stage2_pgd: kvm_free_stage2_pgd(&kvm->arch.mmu); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2fe3121d50ca..63eb207b387f 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -292,6 +292,70 @@ static void id_reg_info_init(struct id_reg_info *id_reg) id_reg->vcpu_limit_val = id_reg->sys_val; } +static int validate_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, u64 val) +{ + int fp, simd; + bool vcpu_has_sve = vcpu_has_sve(vcpu); + bool pfr0_has_sve = id_aa64pfr0_sve(val); + + simd = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_ASIMD_SHIFT); + fp = cpuid_feature_extract_signed_field(val, ID_AA64PFR0_FP_SHIFT); + if (simd != fp) + return -EINVAL; + + /* fp must be supported when sve is supported */ + if (pfr0_has_sve && (fp < 0)) + return -EINVAL; + + /* Check if there is a conflict with a request via KVM_ARM_VCPU_INIT */ + if (vcpu_has_sve ^ pfr0_has_sve) + return -EPERM; + + return 0; +} + +static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) +{ + u64 limit; + + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + limit = id_reg->sys_val; + + limit &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_AMU)); + if (!system_supports_sve()) + limit &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_SVE); + + /* + * The default is to expose CSV2 == 1 and CSV3 == 1 if the HW + * isn't affected. Userspace can override this as long as it + * doesn't promise the impossible. + */ + limit &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2) | + ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3)); + + if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED) + limit |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2), 1); + if (arm64_get_meltdown_state() == SPECTRE_UNAFFECTED) + limit |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3), 1); + + id_reg->vcpu_limit_val = limit; +} + +static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, + struct id_reg_info *idr) +{ + return vcpu_has_sve(vcpu) ? + idr->vcpu_limit_val : + (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64PFR0_SVE))); +} + +static struct id_reg_info id_aa64pfr0_el1_info = { + .sys_reg = SYS_ID_AA64PFR0_EL1, + .init = init_id_aa64pfr0_el1_info, + .validate = validate_id_aa64pfr0_el1, + .get_reset_val = get_reset_id_aa64pfr0_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -300,7 +364,9 @@ static void id_reg_info_init(struct id_reg_info *id_reg) * validation, etc.) */ #define GET_ID_REG_INFO(id) (id_reg_info_table[IDREG_IDX(id)]) -static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = {}; +static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { + [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, +}; static int validate_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, u64 val) @@ -1136,15 +1202,6 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { - case SYS_ID_AA64PFR0_EL1: - if (!vcpu_has_sve(vcpu)) - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_SVE); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_AMU); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2), (u64)vcpu->kvm->arch.pfr0_csv2); - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_CSV3), (u64)vcpu->kvm->arch.pfr0_csv3); - break; case SYS_ID_AA64PFR1_EL1: val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE); if (kvm_has_mte(vcpu->kvm)) { @@ -1261,48 +1318,6 @@ static void reset_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = val; } -static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, - const struct sys_reg_desc *rd, - const struct kvm_one_reg *reg, void __user *uaddr) -{ - const u64 id = sys_reg_to_index(rd); - u8 csv2, csv3; - int err; - u64 val; - - err = reg_from_user(&val, uaddr, id); - if (err) - return err; - - /* - * Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as - * it doesn't promise more than what is actually provided (the - * guest could otherwise be covered in ectoplasmic residue). - */ - csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV2_SHIFT); - if (csv2 > 1 || - (csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED)) - return -EINVAL; - - /* Same thing for CSV3 */ - csv3 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV3_SHIFT); - if (csv3 > 1 || - (csv3 && arm64_get_meltdown_state() != SPECTRE_UNAFFECTED)) - return -EINVAL; - - /* We can only differ with CSV[23], and anything else is an error */ - val ^= read_id_reg(vcpu, rd, false); - val &= ~((0xFUL << ID_AA64PFR0_CSV2_SHIFT) | - (0xFUL << ID_AA64PFR0_CSV3_SHIFT)); - if (val) - return -EINVAL; - - vcpu->kvm->arch.pfr0_csv2 = csv2; - vcpu->kvm->arch.pfr0_csv3 = csv3 ; - - return 0; -} - /* cpufeature ID register user accessors */ static int __get_id_reg(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, void __user *uaddr, @@ -1590,8 +1605,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { /* AArch64 ID registers */ /* CRm=4 */ - { SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg, - .get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, }, + ID_SANITISED(ID_AA64PFR0_EL1), ID_SANITISED(ID_AA64PFR1_EL1), ID_UNALLOCATED(4,2), ID_UNALLOCATED(4,3), From patchwork Tue Oct 12 04:35:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551367 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 828B0C433FE for ; Tue, 12 Oct 2021 04:36:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6CC0861040 for ; Tue, 12 Oct 2021 04:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232435AbhJLEib (ORCPT ); Tue, 12 Oct 2021 00:38:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37180 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232374AbhJLEia (ORCPT ); Tue, 12 Oct 2021 00:38:30 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 056BBC061570 for ; Mon, 11 Oct 2021 21:36:30 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id m9-20020a17090ade09b029017903cc8d6cso882899pjv.4 for ; Mon, 11 Oct 2021 21:36:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=nTXMtA3D4TOs62yx9xXmosWMy1vxPMYLyf89zj4P3sg=; b=DrM5WEJPxxLwrWWTHYAj8Qc4xV1msbr3ZUUIz+Vgg9CThMSACYyczJ1UDERNSK6Ggi oQ1MytUagNqi0alUFD2TBfQHxcb/biUjA9kU3iUrAkSkECbDozt/+ZHlOM2vIMgDe9DU xnCxdoFjVo+srhzN1SSDvIGsxKNr5p6kS/QEdy9M/mC+bcmA2HauNgHXrv7L/yShq/FW 9+CVeX4qwbX1/3Vpkveb9m3MH0vBJ1z79pzJh+E/UumcChjyMGgSgu86T5Y5nhHt0Gm/ YYSE3P8dAWvEZkJPNtplpVhxEpAPiOCT0+snPnaL7fQLiew9mZ19iajPqb9Fb8nQRLcu dJTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=nTXMtA3D4TOs62yx9xXmosWMy1vxPMYLyf89zj4P3sg=; b=GyrMf54MOaGugKKrxnorqOi5OC747IGYriQM5DY4NREzX1eate7KGhJLGEZdCcJ3Zr O3OLHjZZ3AiaUoQ47hcaCelXbINwuoxhhsdC2kEEhiDYlYbDemFEZ2P3tsB5eBzM4BrX EupYPaQEaj9NFENGA0g8x+jy0v81YW3p5/hGrB91gXPgZvtZUhbumFc/0kWAiFhfZAfb cfVipXhG7tIyEnSzYjAc9ArZwDNMx8SokyMmPXDMqFvhqnDiDfrjVSYjHZVOXtN0R+BM 5BtiTZn1Qmq3qhb7WseYoS900Y+V0U/JRx0j+DhiJTSItbK8CN5HHW20A7fKuN419hgU lTHw== X-Gm-Message-State: AOAM5322EkV63pRMvxhHxvnUw+YBfrcZSNSWa3ExJoNlY5vw4BJWHki8 CdcxSLsI1zymBKzCA+HvHB4FaENqwm0= X-Google-Smtp-Source: ABdhPJxUJvThrtjbXZAeg5X6W4utelZnX4+QN62pfB876yK1oZAkUxR/X7DkF7nkuOQxW5rPD2nt286kpBA= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90b:3b44:: with SMTP id ot4mr3486235pjb.145.1634013389503; Mon, 11 Oct 2021 21:36:29 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:17 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-8-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 07/25] KVM: arm64: Make ID_AA64PFR1_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_AA64PFR1_EL1 to make it writable by userspace. Return an error if userspace tries to set MTE field of the register to a value that conflicts with KVM_CAP_ARM_MTE configuration for the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/sys_regs.c | 51 ++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index b268082d67ed..aa0692595122 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -793,6 +793,7 @@ #define ID_AA64PFR0_ELx_32BIT_64BIT 0x2 /* id_aa64pfr1 */ +#define ID_AA64PFR1_CSV2FRAC_SHIFT 32 #define ID_AA64PFR1_MPAMFRAC_SHIFT 16 #define ID_AA64PFR1_RASFRAC_SHIFT 12 #define ID_AA64PFR1_MTE_SHIFT 8 diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 63eb207b387f..0e4423a81cb9 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -314,6 +314,20 @@ static int validate_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static int validate_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, u64 val) +{ + bool kvm_mte = kvm_has_mte(vcpu->kvm); + unsigned int mte; + + mte = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR1_MTE_SHIFT); + + /* Check if there is a conflict with a request via KVM_ARM_VCPU_INIT. */ + if (kvm_mte ^ (mte > 0)) + return -EPERM; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -341,6 +355,14 @@ static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) id_reg->vcpu_limit_val = limit; } +static void init_id_aa64pfr1_el1_info(struct id_reg_info *id_reg) +{ + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + id_reg->vcpu_limit_val = (system_supports_mte() ? + id_reg->sys_val : + (id_reg->sys_val & ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE))); +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, struct id_reg_info *idr) { @@ -349,6 +371,14 @@ static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64PFR0_SVE))); } +static u64 get_reset_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, + struct id_reg_info *idr) +{ + return kvm_has_mte(vcpu->kvm) ? + idr->vcpu_limit_val : + (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64PFR1_MTE))); +} + static struct id_reg_info id_aa64pfr0_el1_info = { .sys_reg = SYS_ID_AA64PFR0_EL1, .init = init_id_aa64pfr0_el1_info, @@ -356,6 +386,16 @@ static struct id_reg_info id_aa64pfr0_el1_info = { .get_reset_val = get_reset_id_aa64pfr0_el1, }; +static struct id_reg_info id_aa64pfr1_el1_info = { + .sys_reg = SYS_ID_AA64PFR1_EL1, + .ignore_mask = ARM64_FEATURE_MASK(ID_AA64PFR1_RASFRAC) | + ARM64_FEATURE_MASK(ID_AA64PFR1_MPAMFRAC) | + ARM64_FEATURE_MASK(ID_AA64PFR1_CSV2FRAC), + .init = init_id_aa64pfr1_el1_info, + .validate = validate_id_aa64pfr1_el1, + .get_reset_val = get_reset_id_aa64pfr1_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -366,6 +406,7 @@ static struct id_reg_info id_aa64pfr0_el1_info = { #define GET_ID_REG_INFO(id) (id_reg_info_table[IDREG_IDX(id)]) static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, + [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, @@ -1202,16 +1243,6 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { - case SYS_ID_AA64PFR1_EL1: - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE); - if (kvm_has_mte(vcpu->kvm)) { - u64 pfr, mte; - - pfr = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1); - mte = cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR1_MTE_SHIFT); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR1_MTE), mte); - } - break; case SYS_ID_AA64ISAR1_EL1: if (!vcpu_has_ptrauth(vcpu)) val &= ~(ARM64_FEATURE_MASK(ID_AA64ISAR1_APA) | From patchwork Tue Oct 12 04:35:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551369 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4AABFC433F5 for ; Tue, 12 Oct 2021 04:36:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 373C6610A4 for ; Tue, 12 Oct 2021 04:36:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232464AbhJLEid (ORCPT ); Tue, 12 Oct 2021 00:38:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232374AbhJLEic (ORCPT ); Tue, 12 Oct 2021 00:38:32 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE905C061570 for ; Mon, 11 Oct 2021 21:36:31 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id d5-20020a63ed05000000b002688d3aff8aso8040914pgi.2 for ; Mon, 11 Oct 2021 21:36:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=YN5X7g7A0IcM/p+7vsiMHZtNXVKHJ9chV2Lsbk7C1zQ=; b=D9t2oSmy3ndrP6bG2CsMouv9WCLzBGAUEH9kU9GDfWruie5xcB4VWV5N3fdKM04NQT y7exLiVXuZ5lFdKYyePdLkoPo8cn1KqjXXh2Bzo6fXPw7dt8Teh9e+XAsRniQxTFH2mj myl0tm3EG6VL6ui4G3GvrZAcc0a+CQ2Lu67tFDcHuFdPNLPfR4C+BiNq81g4Lrip9dW3 /BhRDqpetIQC6EqPlJuNc5GtsRceGBjoNScBNh8IPSRwQe1/D9hxC0nPlBkscc4lwz/O B48K0R37H4tPXUoiS6eIn0jXuDnOjMxP4kD4HyUDRMZT8H/DCqAyH7zyrmvQK/CheTFN IfnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=YN5X7g7A0IcM/p+7vsiMHZtNXVKHJ9chV2Lsbk7C1zQ=; b=TMPpsJ/WO6xvgIR5V90UfXhnz/uD2N/JVxKkMCqZlBlZDFTm8+Heu9psCCvjR+aYoU XzK3EDv9/fNfN4NDvTeCtm/tZYwmNYVUHvL+hldLkSeXfpyM/NPLuc2Uva9S5r+nmktS CCyLD0IQS+fch6KPIrnWbfJWmxDuJ+j3TwtPGjOQ9sOXiIjC6RA7vpNYHtf0dFzGVhy9 mnApQAEJoBmNibbBXGVb7x79V2Yz3fctMzcGeLskeHeNpNfl/4+tI8NG1SofstMKJBwk DajsMRc3yS4VA48uk9nDfwL2ZZ6xGihq3MRDEIvHgAQu0j+Ev/NBUYRQFTBr/pTxzcTe +LAQ== X-Gm-Message-State: AOAM5301fwsFlFmnaJp7ujASjddsLlz6GIZW5KvMT0QMz16XQQFtdzmI 085QaAXmWW45KBwheRZ/UdsSYOS8mBY= X-Google-Smtp-Source: ABdhPJx7SjSGAN6iiMVQeGbe49tKa2HXO9o45gNjMgaiwIrwZeu4H15V70apGcoFeW+OXBwcRgRJdrHYH/Q= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90a:3ee4:: with SMTP id k91mr295558pjc.1.1634013390825; Mon, 11 Oct 2021 21:36:30 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:18 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-9-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 08/25] KVM: arm64: Make ID_AA64ISAR0_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_AA64ISAR0_EL1 to make it writable by userspace. Updating sm3, sm4, sha1, sha2 and sha3 fields are allowed only if values of those fields follow Arm ARM. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 0e4423a81cb9..73b5dad0b2ee 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -328,6 +328,31 @@ static int validate_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static int validate_id_aa64isar0_el1(struct kvm_vcpu *vcpu, u64 val) +{ + unsigned int sm3, sm4, sha1, sha2, sha3; + + /* Run consistency checkings according to Arm ARM */ + sm3 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM3_SHIFT); + sm4 = cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR0_SM4_SHIFT); + if (sm3 != sm4) + return -EINVAL; + + sha1 = cpuid_feature_extract_unsigned_field(val, + ID_AA64ISAR0_SHA1_SHIFT); + sha2 = cpuid_feature_extract_unsigned_field(val, + ID_AA64ISAR0_SHA2_SHIFT); + if ((sha1 == 0) ^ (sha2 == 0)) + return -EINVAL; + + sha3 = cpuid_feature_extract_unsigned_field(val, + ID_AA64ISAR0_SHA3_SHIFT); + if (((sha2 == 2) ^ (sha3 == 1)) || (!sha1 && sha3)) + return -EINVAL; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -396,6 +421,11 @@ static struct id_reg_info id_aa64pfr1_el1_info = { .get_reset_val = get_reset_id_aa64pfr1_el1, }; +static struct id_reg_info id_aa64isar0_el1_info = { + .sys_reg = SYS_ID_AA64ISAR0_EL1, + .validate = validate_id_aa64isar0_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -407,6 +437,7 @@ static struct id_reg_info id_aa64pfr1_el1_info = { static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, + [IDREG_IDX(SYS_ID_AA64ISAR0_EL1)] = &id_aa64isar0_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, From patchwork Tue Oct 12 04:35:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551371 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14EC3C433EF for ; Tue, 12 Oct 2021 04:36:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F1E9A61056 for ; Tue, 12 Oct 2021 04:36:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232477AbhJLEif (ORCPT ); Tue, 12 Oct 2021 00:38:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37204 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232476AbhJLEie (ORCPT ); Tue, 12 Oct 2021 00:38:34 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D102C06161C for ; Mon, 11 Oct 2021 21:36:33 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id u84-20020a254757000000b005bbc2bc51fcso10805274yba.3 for ; Mon, 11 Oct 2021 21:36:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=pzYVrFzh/ZGEBEeS21xkrtQC5IckuFCKV+U32wAyb5M=; b=diOkSIXrqtH7r0bfBGZW7u/LYKDBg+4BjHQcGcA3rV2Gh/2LcXchanV1lcur9ie3oo LvDlKk075kJBdq5sh+OWM0i+svTEYp3NyZAMwwh1O44PAEnASPIQDvDfVnGoFBNLiJrt Wzv+yVIV/8aHiA4ug04hojX+Ahi7w4EPSilF4lcAFwEkVcAvyL07HFNTwRnPMLEp3tT0 i7jfjivHk5ylheFbUg2cWF8j3Iar696FO5q2CJpQxkTIMAKcjXh2EehSGcUALv0yFZho iYSGIeZNMz4/aynPURq/OqckkdQMi77Dpkq5kqkn1sxFl7Ly1MzWXg7YrmjamT1NXpRD ufew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=pzYVrFzh/ZGEBEeS21xkrtQC5IckuFCKV+U32wAyb5M=; b=1OySDl0Vbb/nF02D1MmMUqHCc0plMP00Rx8gWNH8FMqwoSYkBhLveyODzLzY6gECgn 2tXqgVk6/qNWDHEV0oJf/OPn592XKIn85SY2MffZZLi+yNYBqbFp2VKKcYjMw+fpS+Es ujNH/txuzOrkWrJk25hqInNnyQRu+ytid0H7IPC9WgyYiO1ozLTnnvnQDv+LGz9DLegA gWoAAcgBFXuj6cAgc0x7Y8vs+g7R3rQFKc0ZiKkftmmBRjFGA82ugMpS2Jriv1qOKuj3 TY8nY1DKi4DVLZr3p5Q8zgjflPtqJNWhqd39/sv6bwcoA7Vj0Yic0gCaoqNor4xyi2gN 76MQ== X-Gm-Message-State: AOAM533LdB9NozRMfB/jghkRpdSo2NGeCA0M8/5pdBWAQ/RrRz+ml2oj +vScH/muy6DgRwqcIihUjkdKu82pxfQ= X-Google-Smtp-Source: ABdhPJzVGAWlMaiSu1gHhA7Qs49UaGPQLo8/PBNvV9kyjNVw7VtUymOyejUZS98k6GvinFn8SKOa3ZtVE5U= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a25:3620:: with SMTP id d32mr25907878yba.46.1634013392668; Mon, 11 Oct 2021 21:36:32 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:19 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-10-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 09/25] KVM: arm64: Make ID_AA64ISAR1_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_AA64ISAR1_EL1 to make it writable by userspace. Return an error if userspace tries to set PTRAUTH related fields of the register to values that conflict with PTRAUTH configuration for the guest (via KVM_ARM_VCPU_INIT). Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 79 +++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 73b5dad0b2ee..7819a07ee248 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -263,6 +263,24 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, return read_zero(vcpu, p); } +#define PTRAUTH_MASK (ARM64_FEATURE_MASK(ID_AA64ISAR1_APA) | \ + ARM64_FEATURE_MASK(ID_AA64ISAR1_API) | \ + ARM64_FEATURE_MASK(ID_AA64ISAR1_GPA) | \ + ARM64_FEATURE_MASK(ID_AA64ISAR1_GPI)) + +#define aa64isar1_has_apa(val) \ + (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_APA_SHIFT) >= \ + ID_AA64ISAR1_APA_ARCHITECTED) +#define aa64isar1_has_api(val) \ + (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_API_SHIFT) >= \ + ID_AA64ISAR1_API_IMP_DEF) +#define aa64isar1_has_gpa(val) \ + (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPA_SHIFT) >= \ + ID_AA64ISAR1_GPA_ARCHITECTED) +#define aa64isar1_has_gpi(val) \ + (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT) >= \ + ID_AA64ISAR1_GPI_IMP_DEF) + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -353,6 +371,37 @@ static int validate_id_aa64isar0_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static int validate_id_aa64isar1_el1(struct kvm_vcpu *vcpu, u64 val) +{ + unsigned int gpi, gpa, api, apa; + bool generic, address; + bool vcpu_ptrauth = vcpu_has_ptrauth(vcpu); + + gpi = aa64isar1_has_gpi(val); + gpa = aa64isar1_has_gpa(val); + api = aa64isar1_has_api(val); + apa = aa64isar1_has_apa(val); + if ((gpi && gpa) || (api && apa)) + return -EINVAL; + + generic = gpi || gpa; + address = api || apa; + + /* + * Since the current KVM guest implementation works by enabling + * both address/generic pointer authentication features, + * return an error if they conflict. + */ + if (generic ^ address) + return -EPERM; + + /* Check if there is a conflict with a request via KVM_ARM_VCPU_INIT */ + if (vcpu_ptrauth ^ (generic && address)) + return -EPERM; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -388,6 +437,14 @@ static void init_id_aa64pfr1_el1_info(struct id_reg_info *id_reg) (id_reg->sys_val & ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE))); } +static void init_id_aa64isar1_el1_info(struct id_reg_info *id_reg) +{ + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + id_reg->vcpu_limit_val = system_has_full_ptr_auth() ? + id_reg->sys_val : + (id_reg->sys_val & ~PTRAUTH_MASK); +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, struct id_reg_info *idr) { @@ -404,6 +461,13 @@ static u64 get_reset_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64PFR1_MTE))); } +static u64 get_reset_id_aa64isar1_el1(struct kvm_vcpu *vcpu, + struct id_reg_info *idr) +{ + return vcpu_has_ptrauth(vcpu) ? + idr->vcpu_limit_val : (idr->vcpu_limit_val & ~PTRAUTH_MASK); +} + static struct id_reg_info id_aa64pfr0_el1_info = { .sys_reg = SYS_ID_AA64PFR0_EL1, .init = init_id_aa64pfr0_el1_info, @@ -426,6 +490,13 @@ static struct id_reg_info id_aa64isar0_el1_info = { .validate = validate_id_aa64isar0_el1, }; +static struct id_reg_info id_aa64isar1_el1_info = { + .sys_reg = SYS_ID_AA64ISAR1_EL1, + .init = init_id_aa64isar1_el1_info, + .validate = validate_id_aa64isar1_el1, + .get_reset_val = get_reset_id_aa64isar1_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -438,6 +509,7 @@ static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR0_EL1)] = &id_aa64isar0_el1_info, + [IDREG_IDX(SYS_ID_AA64ISAR1_EL1)] = &id_aa64isar1_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, @@ -1274,13 +1346,6 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { - case SYS_ID_AA64ISAR1_EL1: - if (!vcpu_has_ptrauth(vcpu)) - val &= ~(ARM64_FEATURE_MASK(ID_AA64ISAR1_APA) | - ARM64_FEATURE_MASK(ID_AA64ISAR1_API) | - ARM64_FEATURE_MASK(ID_AA64ISAR1_GPA) | - ARM64_FEATURE_MASK(ID_AA64ISAR1_GPI)); - break; case SYS_ID_AA64DFR0_EL1: /* Limit debug to ARMv8.0 */ val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER); From patchwork Tue Oct 12 04:35:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551373 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C577C433FE for ; Tue, 12 Oct 2021 04:36:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5890861056 for ; Tue, 12 Oct 2021 04:36:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232468AbhJLEig (ORCPT ); Tue, 12 Oct 2021 00:38:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232374AbhJLEif (ORCPT ); Tue, 12 Oct 2021 00:38:35 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE545C061570 for ; Mon, 11 Oct 2021 21:36:34 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id v22-20020a170902e8d600b0013eed5613f1so8393981plg.10 for ; Mon, 11 Oct 2021 21:36:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=KkXFZ5Fme7Kzy6UMAllI6J6cKTiNLiuGaTgPl7tFhoc=; b=gNWTCyHt0F+Tgvg9IjH1MQsh4TR7Z/ZVpwe1d0n6s1PxESO4F3WckfgA0IFJR+4tn1 BrtW2efC0MMgaI4/C1g8YwITxHGdB4kUZ8wLio9087ilyqc9MkdkTM5VcR8GGZVdnnTi C4dix4cTMWXtL1S55G+HZOYWpktnCDcr0foHyFoJu3MczBgMQQVGsAhhUogHjuB6MlUM 1GuIC4m5jLesSIHV4l7obvirl8Dh/035/DnD5RnDlOgtzH4urkuhgGTc1/+if+XBxq4g KjJDD0rV93rZv/LytfXCBIvF3/Ei+xCOLf7Mii0kfNbDKXYS8fASBPTK9gv1TluP05hb 0nmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=KkXFZ5Fme7Kzy6UMAllI6J6cKTiNLiuGaTgPl7tFhoc=; b=izyUSFxOsu8hHCJ2kEQ0DUP/p/AnrP3xZOHxblx7XY05n+cmPaubKsqZft5fXBHtL0 jr/I1rDGoKHGKct4zQd47M639KaeNItbp1/EV7pfpTyIc9Qzt5FjYVRZLunwFNXJT8e9 Uh6Eq5i1VY6dZ97x2L0bbhdeqEW8Xqlhw4hBvb08uclSCW0h+IXKQVyDxb8d3+PQKrvB HR+LG/ancCi0LgkDr1y1u2JYunm8hwVXYk7uwqlLtMA6Jy+JzdG2QJoFjlnk6uzxjf/x nD45iKgiWozqXxNRqLNqYm7xLU8m3+ox3hT+Yvi35S/412+tmoa54qtjvf1rUAAWqY1T 1I/w== X-Gm-Message-State: AOAM533n17D30pBDhYQgTsi7K01jboXE+2pFxwVOZq4HUecA/oEU+mOy OTzLuqOruMQ3Fi5ssHpq2iXUn13llVs= X-Google-Smtp-Source: ABdhPJyzBf51TEcN/HoLmrN431l4sJxIHytNAgq2tIPPD+LnRTXbAwEq84O2Hau4z9V+wwNwWLecscNAgN0= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90a:8b8d:: with SMTP id z13mr296118pjn.0.1634013393949; Mon, 11 Oct 2021 21:36:33 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:20 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-11-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 10/25] KVM: arm64: Make ID_AA64DFR0_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_AA64DFR0_EL1 to make it writable by userspace. Return an error if userspace tries to set PMUVER field of the register to a value that conflicts with the PMU configuration. Since number of context-aware breakpoints must be no more than number of supported breakpoints according to Arm ARM, return an error if userspace tries to set CTX_CMPS field to such value. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 108 ++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 7819a07ee248..61e61f4bb81c 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -402,6 +402,46 @@ static int validate_id_aa64isar1_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static bool id_reg_has_pmu(u64 val, u64 shift, u64 min) +{ + u64 pmu = ((val >> shift) & 0xf); + + /* + * Treat IMPLEMENTATION DEFINED functionality as unimplemented for + * ID_AA64DFR0_EL1.PMUVer/ID_DFR0_EL1.PerfMon. + */ + if (pmu == 0xf) + pmu = 0; + + return (pmu >= min); +} + +static int validate_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, u64 val) +{ + unsigned int brps, ctx_cmps; + bool vcpu_pmu = kvm_vcpu_has_pmu(vcpu); + bool dfr0_pmu = id_reg_has_pmu(val, ID_AA64DFR0_PMUVER_SHIFT, + ID_AA64DFR0_PMUVER_8_0); + + brps = cpuid_feature_extract_unsigned_field(val, + ID_AA64DFR0_BRPS_SHIFT); + ctx_cmps = cpuid_feature_extract_unsigned_field(val, + ID_AA64DFR0_CTX_CMPS_SHIFT); + + /* + * Number of context-aware breakpoints can be no more than number of + * supported breakpoints. + */ + if (ctx_cmps > brps) + return -EINVAL; + + /* Check if there is a conflict with a request via KVM_ARM_VCPU_INIT */ + if (vcpu_pmu ^ dfr0_pmu) + return -EPERM; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -445,6 +485,47 @@ static void init_id_aa64isar1_el1_info(struct id_reg_info *id_reg) (id_reg->sys_val & ~PTRAUTH_MASK); } +/* + * ID_AA64DFR0_EL1.PMUVer/ID_DFR0_EL1.PerfMon == 0xf indicates + * IMPLEMENTATION DEFINED form of performance monitors supported, + * PMUv3 not supported (NOTE: 0x0 indicates PMU is not supported). + * This function is to cap a value of those two fields with the + * given 'cap_val' treating 0xf in the fields as 0. + */ +static u64 id_reg_cap_pmu(u64 val, u64 shift, u64 cap_val) +{ + u64 mask = 0xf; + u64 pmu; + + pmu = (val >> shift) & mask; + pmu = (pmu == 0xf) ? 0 : pmu; + pmu = min(pmu, cap_val); + + val &= ~(0xfULL << shift); + val |= (pmu & 0xf) << shift; + return val; +} + +static void init_id_aa64dfr0_el1_info(struct id_reg_info *id_reg) +{ + u64 limit; + + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + limit = id_reg->sys_val; + + /* Limit guests to PMUv3 for ARMv8.4 */ + limit = id_reg_cap_pmu(limit, ID_AA64DFR0_PMUVER_SHIFT, + ID_AA64DFR0_PMUVER_8_4); + /* Limit debug to ARMv8.0 */ + limit &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER); + limit |= (FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER), 6)); + + /* Hide SPE from guests */ + limit &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_PMSVER); + + id_reg->vcpu_limit_val = limit; +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, struct id_reg_info *idr) { @@ -468,6 +549,14 @@ static u64 get_reset_id_aa64isar1_el1(struct kvm_vcpu *vcpu, idr->vcpu_limit_val : (idr->vcpu_limit_val & ~PTRAUTH_MASK); } +static u64 get_reset_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, + struct id_reg_info *idr) +{ + return kvm_vcpu_has_pmu(vcpu) ? + idr->vcpu_limit_val : + (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64DFR0_PMUVER))); +} + static struct id_reg_info id_aa64pfr0_el1_info = { .sys_reg = SYS_ID_AA64PFR0_EL1, .init = init_id_aa64pfr0_el1_info, @@ -497,6 +586,13 @@ static struct id_reg_info id_aa64isar1_el1_info = { .get_reset_val = get_reset_id_aa64isar1_el1, }; +static struct id_reg_info id_aa64dfr0_el1_info = { + .sys_reg = SYS_ID_AA64DFR0_EL1, + .init = init_id_aa64dfr0_el1_info, + .validate = validate_id_aa64dfr0_el1, + .get_reset_val = get_reset_id_aa64dfr0_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -508,6 +604,7 @@ static struct id_reg_info id_aa64isar1_el1_info = { static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, + [IDREG_IDX(SYS_ID_AA64DFR0_EL1)] = &id_aa64dfr0_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR0_EL1)] = &id_aa64isar0_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR1_EL1)] = &id_aa64isar1_el1_info, }; @@ -1346,17 +1443,6 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { - case SYS_ID_AA64DFR0_EL1: - /* Limit debug to ARMv8.0 */ - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64DFR0_DEBUGVER), 6); - /* Limit guests to PMUv3 for ARMv8.4 */ - val = cpuid_feature_cap_perfmon_field(val, - ID_AA64DFR0_PMUVER_SHIFT, - kvm_vcpu_has_pmu(vcpu) ? ID_AA64DFR0_PMUVER_8_4 : 0); - /* Hide SPE from guests */ - val &= ~ARM64_FEATURE_MASK(ID_AA64DFR0_PMSVER); - break; case SYS_ID_DFR0_EL1: /* Limit guests to PMUv3 for ARMv8.4 */ val = cpuid_feature_cap_perfmon_field(val, From patchwork Tue Oct 12 04:35:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551375 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D463C433EF for ; Tue, 12 Oct 2021 04:36:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 63A8161078 for ; Tue, 12 Oct 2021 04:36:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232675AbhJLEii (ORCPT ); Tue, 12 Oct 2021 00:38:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232591AbhJLEih (ORCPT ); Tue, 12 Oct 2021 00:38:37 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D088C06161C for ; Mon, 11 Oct 2021 21:36:36 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id m26-20020a62a21a000000b0041361973ba7so8587932pff.15 for ; Mon, 11 Oct 2021 21:36:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=cwGN9Xe3XWxW643nb96+bXhhQ/Ir7xJT1HwtMeHM7cQ=; b=DBUBOXq/KtFBlinyQ1LBw4GMEMeHuJzh2MUTnjINtr2KUrltQAUA/+vj8wI0Fk5ST3 XiWsa2domVcF8x4i7LPxC0hj8GAwn/DPal9Zqj1qoljPzYPMatgwIia0NMQQqWKOxdYE LeLft6vpRTZbBcHr0bemhAlKRQCe5qJgGwKhn2+w35t4snNcehqQb2g0rsw1RIOdYFU9 bAiPujoV+AaVBXHt8l6+A821yQN76n/5eHRiIh9+1xoDs8dHcReaRoDiKfQOBKkSwGZP HVYmsNdv0YnE0MVnp1hIZAk+puV5zvweS0KhO09Xkis/O6oEEaP7NKkHSlBTNJZEgphI qdnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=cwGN9Xe3XWxW643nb96+bXhhQ/Ir7xJT1HwtMeHM7cQ=; b=4SRq5QmYTQaCGn3w45jcVV9GtnT9tyDtvo0aSCp3vH/SF3R7qNWWyZr3BRIPSwgF1t CTQBvpqFxXqwB0nqxZ0li2xLD8hMqza5/lSVwGnJguqVLg/rAYa6bhI0X/PkIiHO1D4k ziqANgp+pe4CAxh3KSRrcrYjAG1jxtdXG3trZgEErg9fF+1htQ8aZhQOMSIEjQTlcIrN 0CJF1yFxz+mHOrp9njyfqty6Ak/w9mU94oVDCRmcYFrd2HxddDs0ktaGRSL5saig9MQ9 CjKONs0kYQkr8NFR4EWXw+0L8RXtFbKz9v29+8bd2DwemRzL+EpKCyUkaHf5M6I5TlIU 9vgg== X-Gm-Message-State: AOAM530loQMB3xmo6IGAAnTr/PTAM/jFKdNxjWtt+mO0m6oyGhHvG9U2 Iz9BELofGlMPjaqNScMiDj4j8+JvvQg= X-Google-Smtp-Source: ABdhPJy8CGkD4X+vedywWNr5lgYqfM+G5c5VEXo+GN+CPYbQ23SjsxTScLeFIEMAadLh5UzZSK8h53NYvAg= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90a:8b8d:: with SMTP id z13mr296126pjn.0.1634013395790; Mon, 11 Oct 2021 21:36:35 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:21 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-12-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 11/25] KVM: arm64: Make ID_DFR0_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for ID_DFR0_EL1 to make it writable by userspace. Return an error if userspace tries to set PerfMon field of the register to a value that conflicts with the PMU configuration. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 57 +++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 61e61f4bb81c..84c064dfc63a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -442,6 +442,25 @@ static int validate_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static int validate_id_dfr0_el1(struct kvm_vcpu *vcpu, u64 val) +{ + bool vcpu_pmu = kvm_vcpu_has_pmu(vcpu); + unsigned int perfmon = cpuid_feature_extract_unsigned_field(val, + ID_DFR0_PERFMON_SHIFT); + bool dfr0_pmu = id_reg_has_pmu(val, ID_DFR0_PERFMON_SHIFT, + ID_DFR0_PERFMON_8_0); + + if (perfmon == 1 || perfmon == 2) + /* PMUv1 or PMUv2 is not allowed on ARMv8. */ + return -EINVAL; + + /* Check if there is a conflict with a request via KVM_ARM_VCPU_INIT */ + if (vcpu_pmu ^ dfr0_pmu) + return -EPERM; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -526,6 +545,16 @@ static void init_id_aa64dfr0_el1_info(struct id_reg_info *id_reg) id_reg->vcpu_limit_val = limit; } +static void init_id_dfr0_el1_info(struct id_reg_info *id_reg) +{ + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + + /* Limit guests to PMUv3 for ARMv8.4 */ + id_reg->vcpu_limit_val = id_reg_cap_pmu(id_reg->sys_val, + ID_DFR0_PERFMON_SHIFT, + ID_DFR0_PERFMON_8_4); +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, struct id_reg_info *idr) { @@ -557,6 +586,14 @@ static u64 get_reset_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_AA64DFR0_PMUVER))); } +static u64 get_reset_id_dfr0_el1(struct kvm_vcpu *vcpu, + struct id_reg_info *idr) +{ + return kvm_vcpu_has_pmu(vcpu) ? + idr->vcpu_limit_val : + (idr->vcpu_limit_val & ~(ARM64_FEATURE_MASK(ID_DFR0_PERFMON))); +} + static struct id_reg_info id_aa64pfr0_el1_info = { .sys_reg = SYS_ID_AA64PFR0_EL1, .init = init_id_aa64pfr0_el1_info, @@ -593,6 +630,13 @@ static struct id_reg_info id_aa64dfr0_el1_info = { .get_reset_val = get_reset_id_aa64dfr0_el1, }; +static struct id_reg_info id_dfr0_el1_info = { + .sys_reg = SYS_ID_DFR0_EL1, + .init = init_id_dfr0_el1_info, + .validate = validate_id_dfr0_el1, + .get_reset_val = get_reset_id_dfr0_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -602,6 +646,7 @@ static struct id_reg_info id_aa64dfr0_el1_info = { */ #define GET_ID_REG_INFO(id) (id_reg_info_table[IDREG_IDX(id)]) static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { + [IDREG_IDX(SYS_ID_DFR0_EL1)] = &id_dfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, [IDREG_IDX(SYS_ID_AA64DFR0_EL1)] = &id_aa64dfr0_el1_info, @@ -1440,18 +1485,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r, bool raz) { u32 id = reg_to_encoding(r); - u64 val = raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); - switch (id) { - case SYS_ID_DFR0_EL1: - /* Limit guests to PMUv3 for ARMv8.4 */ - val = cpuid_feature_cap_perfmon_field(val, - ID_DFR0_PERFMON_SHIFT, - kvm_vcpu_has_pmu(vcpu) ? ID_DFR0_PERFMON_8_4 : 0); - break; - } - - return val; + return raz ? 0 : __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); } static unsigned int id_visibility(const struct kvm_vcpu *vcpu, From patchwork Tue Oct 12 04:35:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551377 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C6C4C4332F for ; Tue, 12 Oct 2021 04:36:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 569FF61074 for ; Tue, 12 Oct 2021 04:36:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232901AbhJLEio (ORCPT ); Tue, 12 Oct 2021 00:38:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232684AbhJLEij (ORCPT ); Tue, 12 Oct 2021 00:38:39 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F10BC06174E for ; Mon, 11 Oct 2021 21:36:38 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id j193-20020a2523ca000000b005b789d71d9aso25783060ybj.21 for ; Mon, 11 Oct 2021 21:36:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=FDFGhMdlG5o/vMsnwPNFr7Rd2snS1UKSEvF8GgeeBk0=; b=bFgp4asOyTe5ohqjZrdTrsCRaXrQKZImQiXs0iv6ieHHCXWjcZ4+e/dCT7hgcdYpAY mJE0cltfIC6m0zQpTRr07A4H7BDFqur03nuvRSNTON1uQT+SwxsBf5+AbbbCmULIZWQZ KyifZ2mptugqxzta6k+xpDUxVoiM8/hCsH6nGtttUNM+3YUcCxIcTbmhKdG4/2uGy9lE TzJy4XfdtsrFDat2QKaUjSnomRyAfmnfZLG0nh/PY5Bco9jYqR1fjRE9lvNIKHzqsHpi ezKsGvVQK+Ae7dyB0wtV4rmnXsUYPFiGpFEZpDkaNlgen+ezu2eUbx86PQ4frv7cUAFx AZMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=FDFGhMdlG5o/vMsnwPNFr7Rd2snS1UKSEvF8GgeeBk0=; b=AFkOVFoOM/BYOzz/pOy4zrhBSw6TlpY++MA+/akjfEmpI1GMh9yvstFwNeAk042TjD 6PI0Cvh4xmaeqZuWV2uLjQCOzmEw5gNp+gFhtfbhWDu7F+XgpbmXaFYv2x12Jn0pwl0/ 7pIv2+qs1bu/2iz9i05SWj4sQvIRMxHt7DMwOMsxuxo0acq7KcDbWy89iPyZzRibPD34 As4CCwi7FAozGKJJQlU7afaNDWnu4fZSyflNh1oZiWieIEM/88TreljeDKkmCr4BL/f+ pfhZsvfDRzR2oa/bbMqiM35W8on3Do+VhQTzm31uIOqDslATKBomjOfHyrhDvxH+ch9i RKwA== X-Gm-Message-State: AOAM532q7SeTly2g4J+9AN0WODu6qfuXPSZP2b0ByiRffiw1QxCrtf0d XAoxV7s1hilP4y8Ld/yPOMUYbLIKEQc= X-Google-Smtp-Source: ABdhPJy/Am31eNzPPFxM2MuSeuH8s6JV4pcMog7TA73zjPoDJL1Y4brQNrPfvNSY+xWqEWvRHGSmE/XmAVI= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a25:54c5:: with SMTP id i188mr26034197ybb.43.1634013397423; Mon, 11 Oct 2021 21:36:37 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:22 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-13-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 12/25] KVM: arm64: Make MVFR1_EL1 writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch adds id_reg_info for MVFR1_EL1 to make it writable by userspace. There are only a few valid combinations of values that can be set for FPHP and SIMDHP fields according to Arm ARM. Return an error when userspace tries to set those fields to values that don't match any of the valid combinations. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 84c064dfc63a..71cfd62f9c85 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -461,6 +461,35 @@ static int validate_id_dfr0_el1(struct kvm_vcpu *vcpu, u64 val) return 0; } +static int validate_mvfr1_el1(struct kvm_vcpu *vcpu, u64 val) +{ + unsigned int fphp, simdhp; + struct fphp_simdhp { + unsigned int fphp; + unsigned int simdhp; + }; + /* Permitted fphp/simdhp value combinations according to Arm ARM */ + struct fphp_simdhp valid_fphp_simdhp[3] = {{0, 0}, {2, 1}, {3, 2}}; + int i; + bool is_valid_fphp_simdhp = false; + + fphp = cpuid_feature_extract_unsigned_field(val, MVFR1_FPHP_SHIFT); + simdhp = cpuid_feature_extract_unsigned_field(val, MVFR1_SIMDHP_SHIFT); + + for (i = 0; i < ARRAY_SIZE(valid_fphp_simdhp); i++) { + if (valid_fphp_simdhp[i].fphp == fphp && + valid_fphp_simdhp[i].simdhp == simdhp) { + is_valid_fphp_simdhp = true; + break; + } + } + + if (!is_valid_fphp_simdhp) + return -EINVAL; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit; @@ -637,6 +666,11 @@ static struct id_reg_info id_dfr0_el1_info = { .get_reset_val = get_reset_id_dfr0_el1, }; +static struct id_reg_info mvfr1_el1_info = { + .sys_reg = SYS_MVFR1_EL1, + .validate = validate_mvfr1_el1, +}; + /* * An ID register that needs special handling to control the value for the * guest must have its own id_reg_info in id_reg_info_table. @@ -647,6 +681,7 @@ static struct id_reg_info id_dfr0_el1_info = { #define GET_ID_REG_INFO(id) (id_reg_info_table[IDREG_IDX(id)]) static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_DFR0_EL1)] = &id_dfr0_el1_info, + [IDREG_IDX(SYS_MVFR1_EL1)] = &mvfr1_el1_info, [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, [IDREG_IDX(SYS_ID_AA64DFR0_EL1)] = &id_aa64dfr0_el1_info, From patchwork Tue Oct 12 04:35:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551379 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32B1AC433FE for ; Tue, 12 Oct 2021 04:36:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 18A776108F for ; Tue, 12 Oct 2021 04:36:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232374AbhJLEix (ORCPT ); Tue, 12 Oct 2021 00:38:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37262 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232752AbhJLEil (ORCPT ); Tue, 12 Oct 2021 00:38:41 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68E09C061767 for ; Mon, 11 Oct 2021 21:36:39 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id a16-20020a63d410000000b00268ebc7f4faso8029955pgh.17 for ; Mon, 11 Oct 2021 21:36:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=1CPPpn8KI1TMZ7GOgYY97mtQvxGoDF5nzyvksmCa+Fo=; b=Aa/p3+3YZnA0JDS8zWOXEXRZ2ZxkPrOLUOlaX3VyAf7LudzDEdPB3CLJ1YVKMe7L9G Wb8CyupAqRRvvfXLbGdNalJb9N1cIo9LYCHTskPgOkE6h6lfDwn+y9/uxIl8ygZCkOUD CNPuFzpb9ztvN1IozmoW1sGZpIedv4EjEUpJDMCY/hS2AgqJE8x+CTgsRrNjDDZqbME8 l90jqzqQhgg5JVyOWjLQ+mT6BS5zOh9zM/vLwhRCm0ZtrfpE4PF9CW58QdPjF02Dt0jz 6HZjuCYbrZSCLV4LiEZqfciTJsA8zVhac0Rle06fMkXQhjS2DhUlWMc4fK9x5TOiAgvs bU+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=1CPPpn8KI1TMZ7GOgYY97mtQvxGoDF5nzyvksmCa+Fo=; b=sAgNDM1IiYdcF8kbJpMaMYDA+gmK1KiVgL6PDA7+tDtQlxq3o9O2dMpIxyRlSW3NB+ Oo/45MuPXsrg5J2G33iecnrav495q7gQ159OiiWKr1H35iobNVs0JzKowZrymcDUnIWE FXxg06tS/i+kSCd/n79jJGrcoatzB2qZ2cnTinc5Hu2f9AvOusJA7urQAI/iC9Zpr3HQ AYrZ0P7AMwUlAnchC6ygK8N5PRdLyVzt9ys+EOsw7IyEv65Edpa13RFvCJwAreGNe/pS 7f2SIPcxOstC4eaNGCKPOFZle2iQI71lEDwelJmfWNqNbYo2vUbmxVFQlhG3WgojkWns IZEg== X-Gm-Message-State: AOAM530Gr8+06xaZGzOXaQtExLU91PIDue+LlfHwuhkZx3wVrV4um0Ze u9wFw6IlgPgyhj81WOe5Ow4ywo5xkhs= X-Google-Smtp-Source: ABdhPJw94QBclZTr8KRoQua2KsoSUSz/7GaRlZ1blagFA4MtNarr7PzT8SqQ7pJ7+LRN050secmOa62Uv/c= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a05:6a00:984:b0:44c:e996:fc2d with SMTP id u4-20020a056a00098400b0044ce996fc2dmr20321105pfg.31.1634013398952; Mon, 11 Oct 2021 21:36:38 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:23 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-14-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 13/25] KVM: arm64: Make ID registers without id_reg_info writable From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Make ID registers that don't have id_reg_info writable. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 71cfd62f9c85..2c092136cdff 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1625,12 +1625,8 @@ static int __set_id_reg(struct kvm_vcpu *vcpu, if (err) return err; - /* Don't allow to change the reg unless the reg has id_reg_info */ - if (val != read_id_reg(vcpu, rd, raz) && !GET_ID_REG_INFO(encoding)) - return -EINVAL; - /* Don't allow to change the reg after the first KVM_RUN. */ - if (vcpu->arch.has_run_once) + if ((val != read_id_reg(vcpu, rd, raz)) && vcpu->arch.has_run_once) return -EINVAL; if (raz) From patchwork Tue Oct 12 04:35:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551381 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB68DC433F5 for ; Tue, 12 Oct 2021 04:36:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B5FBD61078 for ; Tue, 12 Oct 2021 04:36:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232783AbhJLEiz (ORCPT ); Tue, 12 Oct 2021 00:38:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37272 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232830AbhJLEim (ORCPT ); Tue, 12 Oct 2021 00:38:42 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DEB8C061570 for ; Mon, 11 Oct 2021 21:36:41 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id k18-20020a170902c41200b0013f24806d35so2668752plk.1 for ; Mon, 11 Oct 2021 21:36:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=NdSMRo52Kt8R49ASB3iWmgOfNvqbp057LlUUAD7mUQ8=; b=UJMj1LQnQg8ni482AfX60HHwpm8Qdom8NNgfPE0bTl86X4YpvAIA/blDO5OHvVVxpt OMG9HXknPMZA4yh62hHr1vUuixaM5NtleBEvLLzCSflMqnJR94YrBRunIlqd27uYLYzo Hke6AO32AiOv7drD5U03XDkZJ4BJwD9kLzPeXwwzxkOwEOfZFdxzlj2p0ncOC1z7EL0H YJiP8uqQz3Ozfmb3zGYTDjQtsnZkCpE26TLAb3d7ro6dcu8FBo2zNWngLlRQQtPh9mHA py5TkWMBMMoPGNxlnZAu46Jzbv+EzyRZ2ULtjhNyIDXMgvJme8F7lkvqQUrLXOfbNQ3n uPUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=NdSMRo52Kt8R49ASB3iWmgOfNvqbp057LlUUAD7mUQ8=; b=EOsBW/Q0oNmUYTAph1APEwzp84WPW5DfQC16RxI4UsMSrYY2AuC9oFh+73eDMfaoUZ k9Ui+/lxMvcBosebHibP/XlQVWQmKA+EagXYaT241p3ugiIawQ+zstroE5GCRsUsHSVP Nl8DHBHvaoI6NE2ROMCAG4QoFkZoBHGlQ2xxJnfqVekB/IocT6mQbcGaun1VPTwNJSIC +B8PU+3nJZRgg54rxOizi7jusYtDxrGuAV+w3USCL5byxDW7byyv6o0+u3bcuiATY31P UwcB8g+4cjvJ8ty9tiMRVZrMP72I+k03wigRn8FOwaAFhS34pp6oQHnhX9wHeejehaUZ Xtyw== X-Gm-Message-State: AOAM531KvWK7jDe3lhDsumxYCarO+KZmvMkD2hSM+dCZlckfnNCWwr5u Iza9pFGfwaM6CiRe/HvA+x2n9VOOICk= X-Google-Smtp-Source: ABdhPJwFu+FIz+R1kOBR7i1iuVZKIe5AIiaGB4ZNE8m5SuwM1w6CfzaHd9uansbux6G4jPV1AJeCKsHeMB0= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90a:8b8d:: with SMTP id z13mr296149pjn.0.1634013400403; Mon, 11 Oct 2021 21:36:40 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:24 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-15-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 14/25] KVM: arm64: Add consistency checking for frac fields of ID registers From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Feature fractional field of an ID register cannot be simply validated at KVM_SET_ONE_REG because its validity depends on its (main) feature field value, which could be in a different ID register (and might be set later). Validate fractional fields at the first KVM_RUN instead. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 98 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2c092136cdff..536e313992d4 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -632,9 +632,6 @@ static struct id_reg_info id_aa64pfr0_el1_info = { static struct id_reg_info id_aa64pfr1_el1_info = { .sys_reg = SYS_ID_AA64PFR1_EL1, - .ignore_mask = ARM64_FEATURE_MASK(ID_AA64PFR1_RASFRAC) | - ARM64_FEATURE_MASK(ID_AA64PFR1_MPAMFRAC) | - ARM64_FEATURE_MASK(ID_AA64PFR1_CSV2FRAC), .init = init_id_aa64pfr1_el1_info, .validate = validate_id_aa64pfr1_el1, .get_reset_val = get_reset_id_aa64pfr1_el1, @@ -3198,10 +3195,79 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) return write_demux_regids(uindices); } +/* ID register's fractional field information with its feature field. */ +struct feature_frac { + u32 frac_id; + u32 id; + u64 frac_mask; + u64 mask; +}; + +static const struct feature_frac feature_frac_table[] = { + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_mask = ARM64_FEATURE_MASK(ID_AA64PFR1_RASFRAC), + .id = SYS_ID_AA64PFR0_EL1, + .mask = ARM64_FEATURE_MASK(ID_AA64PFR0_RAS), + }, + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_mask = ARM64_FEATURE_MASK(ID_AA64PFR1_MPAMFRAC), + .id = SYS_ID_AA64PFR0_EL1, + .mask = ARM64_FEATURE_MASK(ID_AA64PFR0_MPAM), + }, + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_mask = ARM64_FEATURE_MASK(ID_AA64PFR1_CSV2FRAC), + .id = SYS_ID_AA64PFR0_EL1, + .mask = ARM64_FEATURE_MASK(ID_AA64PFR0_CSV2), + }, +}; + +/* + * Return non-zero if the feature/fractional fields pair are not + * supported. Return zero otherwise. + */ +static int vcpu_id_reg_feature_frac_check(const struct kvm_vcpu *vcpu, + const struct feature_frac *ftr_frac) +{ + const struct id_reg_info *id_reg; + u32 id; + u64 val, lim; + int err; + + /* Check the feature field */ + id = ftr_frac->id; + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) & ftr_frac->mask; + id_reg = GET_ID_REG_INFO(id); + lim = id_reg ? id_reg->vcpu_limit_val : read_sanitised_ftr_reg(id); + lim &= ftr_frac->mask; + err = arm64_check_features(id, val, lim); + if (err) + /* The feature version is larger than the limit. */ + return err; + + if (val != lim) + /* + * The feature version is smaller than the limit. + * Any fractional version should be fine. + */ + return 0; + + /* Check the fractional field */ + id = ftr_frac->frac_id; + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) & ftr_frac->frac_mask; + id_reg = GET_ID_REG_INFO(id); + lim = id_reg ? id_reg->vcpu_limit_val : read_sanitised_ftr_reg(id); + lim &= ftr_frac->frac_mask; + return arm64_check_features(id, val, lim); +} + int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu) { - int i; + int i, err; const struct kvm_vcpu *t_vcpu; + const struct feature_frac *frac; /* * Make sure vcpu->arch.has_run_once is visible for others so that @@ -3222,6 +3288,17 @@ int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu) KVM_ARM_ID_REG_MAX_NUM)) return -EINVAL; } + + /* + * Check ID registers' fractional fields, which aren't checked + * when userspace sets. + */ + for (i = 0; i < ARRAY_SIZE(feature_frac_table); i++) { + frac = &feature_frac_table[i]; + err = vcpu_id_reg_feature_frac_check(vcpu, frac); + if (err) + return err; + } return 0; } @@ -3240,6 +3317,19 @@ static void id_reg_info_init_all(void) else id_reg_info_init(id_reg); } + + /* + * Update ignore_mask of ID registers based on fractional fields + * information. Any ID register that have fractional fields + * is expected to have its own id_reg_info. + */ + for (i = 0; i < ARRAY_SIZE(feature_frac_table); i++) { + id_reg = GET_ID_REG_INFO(feature_frac_table[i].frac_id); + if (WARN_ON_ONCE(!id_reg)) + continue; + + id_reg->ignore_mask |= feature_frac_table[i].frac_mask; + } } void kvm_sys_reg_table_init(void) From patchwork Tue Oct 12 04:35:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551383 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0643CC433FE for ; Tue, 12 Oct 2021 04:36:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E367461074 for ; Tue, 12 Oct 2021 04:36:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232867AbhJLEi5 (ORCPT ); Tue, 12 Oct 2021 00:38:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37282 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232915AbhJLEio (ORCPT ); Tue, 12 Oct 2021 00:38:44 -0400 Received: from mail-qt1-x849.google.com (mail-qt1-x849.google.com [IPv6:2607:f8b0:4864:20::849]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D715C061749 for ; Mon, 11 Oct 2021 21:36:43 -0700 (PDT) Received: by mail-qt1-x849.google.com with SMTP id 12-20020aed208c000000b002a78b33ad97so2242034qtb.23 for ; Mon, 11 Oct 2021 21:36:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=W3IwbsI0k+1QwX+TAHKvccKyulobDPeUG2CVSppLk2E=; b=TfiizDughOv6XpmrE/B/ta2oJtWh1KOl7oRghEckpq0jtU04giMWrFXne9m7+dzkv6 +vDn6LO6SZHnG6Q2pROAG2PQBSDXREyd22lMQG+lxRGsSADq1E+VnO1Z7WqkDHfrJlNO EVH0Yg/uVDi2saPJf04+wIlOaX6lLvVlRsChENQhZNP7PXPXCNlE+6otUV3bnagcPn4z Yx6SBV7yyfslru2sqW6hIZHTINV96lf4W7ad0FwkZXwvoj8/k7dfbQXIV11HMFzC35M9 3BWa+zuJL4S/hTBSHGuyaF8QFy7mPEwc4ITx69ZWKUdntSI1EIJBbI4KYAjAoqtTxm/c HEOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=W3IwbsI0k+1QwX+TAHKvccKyulobDPeUG2CVSppLk2E=; b=vFyeo0m3R92qDJvhrLfGQ09XeUJKyS5LcuJukPl/c6AZ36LlvqmC6/J3SFG7ycsZB0 Te9fQhyCNRWN2oqEt8stjdJtxrdYyeEdi42K5yEN4pMEKVZcl6VbsVfutBcCDLI+dl0U /BLRwtqsSm4ako5wGtUsW4pMcWeMedVqbIoBAUgtHuo9BrUK5lUS7fRY5Y/lUUImJ1F2 EMARQyH+NYFcdjvRelyKJvLnhgOimnLB30Yv+58Edl2YjQFSCL/k4Glx8rv65i2GjvGG fnVof5v+McGS6xT17nsp0dbQ+bkdX8KuqPW+v94E0UCNdfKLl6B8GMZ6runwZSqwunm5 fMtw== X-Gm-Message-State: AOAM532vxszvQKz3W2bl2R05WtFzsXfCZdSV/VXAfD5mToIU1tAnuW4B gn3hTKy2N+Ls0q86M1uw92Npw+2A4co= X-Google-Smtp-Source: ABdhPJzqRlxJ4C5xz9JQufFpuXIYDJjLzFExk6TNCvlIXorPpPAh6QasGboxtVmBj45EPB8PnMerC+dbHno= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a05:622a:1a0b:: with SMTP id f11mr12653018qtb.133.1634013402619; Mon, 11 Oct 2021 21:36:42 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:25 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-16-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 15/25] KVM: arm64: Introduce KVM_CAP_ARM_ID_REG_WRITABLE capability From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce a new capability KVM_CAP_ARM_ID_REG_WRITABLE to indicate that ID registers are writable by userspace. Signed-off-by: Reiji Watanabe --- Documentation/virt/kvm/api.rst | 8 ++++++++ arch/arm64/kvm/arm.c | 1 + include/uapi/linux/kvm.h | 1 + 3 files changed, 10 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index a6729c8cf063..f7dfb5127310 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7265,3 +7265,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset of the result of KVM_CHECK_EXTENSION. KVM will forward to userspace the hypercalls whose corresponding bit is in the argument, and return ENOSYS for the others. + +8.35 KVM_CAP_ARM_ID_REG_WRITABLE +-------------------------------- + +:Architectures: arm64 + +This capability indicates that userspace can modify the ID registers +via KVM_SET_ONE_REG ioctl. diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 820f35051d77..29c13a32dd21 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -197,6 +197,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: case KVM_CAP_PTP_KVM: + case KVM_CAP_ARM_ID_REG_WRITABLE: r = 1; break; case KVM_CAP_SET_GUEST_DEBUG2: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a067410ebea5..3345a57f05a6 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1112,6 +1112,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_BINARY_STATS_FD 203 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_ARM_MTE 205 +#define KVM_CAP_ARM_ID_REG_WRITABLE 206 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Tue Oct 12 04:35:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551385 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7112EC4332F for ; Tue, 12 Oct 2021 04:37:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5E6A660EE5 for ; Tue, 12 Oct 2021 04:37:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233262AbhJLEjC (ORCPT ); Tue, 12 Oct 2021 00:39:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233106AbhJLEiv (ORCPT ); Tue, 12 Oct 2021 00:38:51 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D542C06176A for ; Mon, 11 Oct 2021 21:36:44 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id nv1-20020a17090b1b4100b001a04861d474so1224000pjb.5 for ; Mon, 11 Oct 2021 21:36:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=O80RXxKd8P9hs8Tp3F97VMD6XsGe17hQTC/zrEZsizQ=; b=SvA0l3zedVEdqzURZ8w9+HdGYvSxtHH6R+4rarSwRZVDbUeoUP7+itvF+pPbZmYxgp tqNXFiiEQ5XcrfsIcKB6HF+9e09nLcJgmuiDt3NTbbJlZjUESi9d7BU974p5vaR+BlDA D9zX1ejs2fPDzhQ1c07zTov6Ee4fQgeyY1eS/hXiVWLnMGH1n0LDkoxFk1+GQ17XweAr 8n3dBIyuW+4zyleYH6+CkBWwJgTBP5/rZxU9XOGR6SyX1JAZY1ZTXePq7LM46/q8wX15 OUtenXDhvJfEUo+DWJ32JbW7Z8W1KVGCaY5QiXWiKuiqIaPPh6l3IQQrwUEzR9jW1X/c rbKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=O80RXxKd8P9hs8Tp3F97VMD6XsGe17hQTC/zrEZsizQ=; b=ZLimbo3acR4MS0WMhhdQm7LUR7NrWBF3DNJLcSUgAW7goSbWN5aVKGH7Jte3UbVk57 MoxFr9oDlZRpqrtb4bJv0DOuxfdcSvVcv6GfA/S5B3fx0jMAMdDxIyme3Ru1E3G8kEcz kZRw7sYDolZ+rmZ0eXBopzJIKkmm/FSLv8zrhIdEE95eHd00YltghxECnSL+CHLMfneX o3VnG2C56fvlUf/CRTGPQETCjuXDsGpn9heWD5555slkUSHMmomHnToQhKlsP/I/PDw3 5jFkqIrxwT3nxTAcc72XN1NexF4h26TEybn88pv4cE2JP6c+KSh7st90l3vTxeMbvvsP tHMg== X-Gm-Message-State: AOAM532US4WrcZQi6IscbdeTDlxDEWaA4QajiPDRDJ9C1rKmGo/q/9zF cxPrxwa5tWVnf7PkuT4EAbDqaYpPAM4= X-Google-Smtp-Source: ABdhPJyCqIvdNbnd9WwEvKh4oT9+MR9jl6x5aWloqmAyIa7gGMLPXWot1OgqE3Gfyb3ZJKtfcyeA94G0bQQ= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:902:b111:b0:13f:48e1:9bc4 with SMTP id q17-20020a170902b11100b0013f48e19bc4mr5211016plr.53.1634013403885; Mon, 11 Oct 2021 21:36:43 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:26 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-17-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 16/25] KVM: arm64: Use vcpu->arch cptr_el2 to track value of cptr_el2 for VHE From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Track the baseline guest value for cptr_el2 in struct kvm_vcpu_arch for VHE. Use this value when setting cptr_el2 for the guest. Currently this value is unchanged, but the following patches will set trapping bits based on features supported for the guest. No functional change intended. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_arm.h | 16 ++++++++++++++++ arch/arm64/kvm/arm.c | 5 ++++- arch/arm64/kvm/hyp/vhe/switch.c | 14 ++------------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 327120c0089f..f11ba1b6699d 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -288,6 +288,22 @@ GENMASK(19, 14) | \ BIT(11)) +/* + * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to + * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, + * except for some missing controls, such as TAM. + * In this case, CPTR_EL2.TAM has the same position with or without + * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM + * shift value for trapping the AMU accesses. + */ +#define CPTR_EL2_VHE_GUEST_DEFAULT (CPACR_EL1_TTA | CPTR_EL2_TAM) + +/* + * Bits that are copied from vcpu->arch.cptr_el2 to set cptr_el2 for + * guest with VHE. + */ +#define CPTR_EL2_VHE_GUEST_TRACKED_MASK (CPACR_EL1_TTA | CPTR_EL2_TAM) + /* Hyp Debug Configuration Register bits */ #define MDCR_EL2_E2TB_MASK (UL(0x3)) #define MDCR_EL2_E2TB_SHIFT (UL(24)) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 29c13a32dd21..32fd6edbd9e1 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1108,7 +1108,10 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, } vcpu_reset_hcr(vcpu); - vcpu->arch.cptr_el2 = CPTR_EL2_DEFAULT; + if (has_vhe()) + vcpu->arch.cptr_el2 = CPTR_EL2_VHE_GUEST_DEFAULT; + else + vcpu->arch.cptr_el2 = CPTR_EL2_DEFAULT; /* * Handle the "start in power-off" case. diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index ded2c66675f0..b924e9d5e6fa 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -38,20 +38,10 @@ static void __activate_traps(struct kvm_vcpu *vcpu) ___activate_traps(vcpu); val = read_sysreg(cpacr_el1); - val |= CPACR_EL1_TTA; + val &= ~CPTR_EL2_VHE_GUEST_TRACKED_MASK; + val |= (vcpu->arch.cptr_el2 & CPTR_EL2_VHE_GUEST_TRACKED_MASK); val &= ~CPACR_EL1_ZEN; - /* - * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to - * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, - * except for some missing controls, such as TAM. - * In this case, CPTR_EL2.TAM has the same position with or without - * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM - * shift value for trapping the AMU accesses. - */ - - val |= CPTR_EL2_TAM; - if (update_fp_enabled(vcpu)) { if (vcpu_has_sve(vcpu)) val |= CPACR_EL1_ZEN; From patchwork Tue Oct 12 04:35:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551387 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 619A2C433EF for ; Tue, 12 Oct 2021 04:37:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4E46B60EE2 for ; Tue, 12 Oct 2021 04:37:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233310AbhJLEjD (ORCPT ); Tue, 12 Oct 2021 00:39:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37314 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232602AbhJLEiv (ORCPT ); Tue, 12 Oct 2021 00:38:51 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 032D9C06176E for ; Mon, 11 Oct 2021 21:36:46 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id t4-20020a62ea04000000b0044b333f5d1bso8590471pfh.20 for ; Mon, 11 Oct 2021 21:36:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=0ZHKUOwuChcfcYJa8iP/PsFVSj3BwFFjpYVXfGnVVxU=; b=mjDXddS6mtqkEh62Do5NxpNb41/LwWTC2n3D/+Ug1Lcuv37dFkYweiWPN8B2WJkYmW mKzZdfIRWGthEyo4paKm+wXpRD2HY+B4w03MH8YsO/8fSiLbYK9t7a8i2cl3Plz9WiaC XXTcsTP9VQNfk8U99KOkX47Sid6a/cpShR5kKUIvVj5ar6NWFZ6ZM6tzjRFg9noqCeIu uPeuk/T3jbx+usHKSylBvdCnC+BZ0rYmp79KWyRLa9DYQkjr1PID0fZWf8og9KjiK7iQ /FCF5a+cl1wmRp7tld6cptvvssMjVhPNPZRPj9yfV78Hyzea1ESojs5S9TEw3WBAIbl8 Jwsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=0ZHKUOwuChcfcYJa8iP/PsFVSj3BwFFjpYVXfGnVVxU=; b=RR2PyQAEE5nYme8IIW81vzfiOE+YXdNn7GFW966xsrio9D5OpT8oZNDNyJUjHfrmOm BPOptm1nJ+GDn+8zlEOwXxUZmADj/edeTtQTrIVcUhyOBD2YuSZ8ihv3A1DoE/gyiyQ4 3pPv1CQZCX9DEShCC3uf+JySq0oNbrUKtrdxfc3inxHIselu3d4dsDGCsbP1wM0O4elO bwhm0xMwt0zgBnMnu6GeKMjIZL+pKPIooYvFqDn99H/DK68urgS+1QDvtteT6cKHixwE AwRwrmgOY5LA686VP4wRsT/sZwEvGZ20QSNgsav3t9GNh6oi3rji7VQghdEj+DaN6Fnz 8kfQ== X-Gm-Message-State: AOAM531BS83/MmZdZC8yXrDEu9gPuyo+OPXVPej6lAJXOrpCWrfSrRpW KEPJjDJCRKsg9vR7R34RVFpFLLfCa0E= X-Google-Smtp-Source: ABdhPJwE5QRMas4+J8u2/xwhktuRlyVOoA2E9U8HDw32BeONkGZwJFeKAJm/CO2sKvDWWiTH1lMKO062rcw= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:aa7:9d91:0:b0:44d:2778:561f with SMTP id f17-20020aa79d91000000b0044d2778561fmr6369522pfq.15.1634013405458; Mon, 11 Oct 2021 21:36:45 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:27 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-18-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 17/25] KVM: arm64: Use vcpu->arch.mdcr_el2 to track value of mdcr_el2 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Track the baseline guest value for mdcr_el2 in struct kvm_vcpu_arch. Use this value when setting mdcr_el2 for the guest. Currently this value is unchanged, but the following patches will set trapping bits based on features supported for the guest. No functional change intended. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_arm.h | 16 ++++++++++++++++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/debug.c | 13 ++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index f11ba1b6699d..e560e5549472 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -332,6 +332,22 @@ BIT(18) | \ GENMASK(16, 15)) +/* + * The default value for the guest below also clears MDCR_EL2_E2PB_MASK + * and MDCR_EL2_E2TB_MASK to disable guest access to the profiling and + * trace buffers. + */ +#define MDCR_GUEST_FLAGS_DEFAULT \ + (MDCR_EL2_TPM | MDCR_EL2_TPMS | MDCR_EL2_TTRF | \ + MDCR_EL2_TPMCR | MDCR_EL2_TDRA | MDCR_EL2_TDOSA) + +/* Bits that are copied from vcpu->arch.mdcr_el2 to set mdcr_el2 for guest. */ +#define MDCR_GUEST_FLAGS_TRACKED_MASK \ + (MDCR_EL2_TPM | MDCR_EL2_TPMS | MDCR_EL2_TTRF | \ + MDCR_EL2_TPMCR | MDCR_EL2_TDRA | MDCR_EL2_TDOSA | \ + (MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)) + + /* For compatibility with fault code shared with 32-bit */ #define FSC_FAULT ESR_ELx_FSC_FAULT #define FSC_ACCESS ESR_ELx_FSC_ACCESS diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 32fd6edbd9e1..38301ddf8372 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1108,6 +1108,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, } vcpu_reset_hcr(vcpu); + vcpu->arch.mdcr_el2 = MDCR_GUEST_FLAGS_DEFAULT; if (has_vhe()) vcpu->arch.cptr_el2 = CPTR_EL2_VHE_GUEST_DEFAULT; else diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index db9361338b2a..83330968a411 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -84,16 +84,11 @@ void kvm_arm_init_debug(void) static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu) { /* - * This also clears MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK - * to disable guest access to the profiling and trace buffers + * Keep the vcpu->arch.mdcr_el2 bits that are specified by + * MDCR_GUEST_FLAGS_TRACKED_MASK. */ - vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; - vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | - MDCR_EL2_TPMS | - MDCR_EL2_TTRF | - MDCR_EL2_TPMCR | - MDCR_EL2_TDRA | - MDCR_EL2_TDOSA); + vcpu->arch.mdcr_el2 &= MDCR_GUEST_FLAGS_TRACKED_MASK; + vcpu->arch.mdcr_el2 |= __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; /* Is the VM being debugged by userspace? */ if (vcpu->guest_debug) From patchwork Tue Oct 12 04:35:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551389 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C148FC433EF for ; Tue, 12 Oct 2021 04:37:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ADEC960E52 for ; Tue, 12 Oct 2021 04:37:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233325AbhJLEjF (ORCPT ); Tue, 12 Oct 2021 00:39:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37272 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232598AbhJLEiy (ORCPT ); Tue, 12 Oct 2021 00:38:54 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11281C061776 for ; Mon, 11 Oct 2021 21:36:48 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id w4-20020a1709029a8400b00138e222b06aso8402010plp.12 for ; Mon, 11 Oct 2021 21:36:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=OQYgwRpV/afvA18lL6MxXV8IUfnKjIjbj1gRfgEyVlM=; b=IXmq+jTnwzeMBZKuKOipuIYaqVqyDgFMjOwwqaAgqb69yrm6IYJI+VT/YZ5EeAWbSq gCLxYJ+uTN3DFS1my5x2/PLGxbN9dRP5QOnJ/ssIh7ETvLkRsUOqZlVwI/ahI8wMgahd bCXEbEQzWffBR905nT9Ci/R/YNi+a+J9L6RmWiRtI0WBgUIUd4hCS+EgjruLZtHR40WH hkCCqtj9wBP07X1FJFqKlmx39A4gvLr+AXiIvUp94hY3RkNS7y3kZCECK51vw7qF/gcq lQUcFrWMU2XfVxGskB5pP/mWuzWV4MnjVj+dLW5eyUPPGDPUj5CUUy2HBW7TvX6rhT2n Adjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=OQYgwRpV/afvA18lL6MxXV8IUfnKjIjbj1gRfgEyVlM=; b=IBdJIvMVq+2zgxeW7OrU2YBShHHsQ1dFs4FzzhBtLG5Osigaei6V/JhqerqMk5vewt pPjGF87kVzoojMV/vbD7+/YohbVK66GPpDcIBeBaPy2KCfbNwaFLm/hiMch46gd8FDyF 1Ous396pZz100ybvtlUvY9e5IdgHJRQO3JY+DK31ovVyd6s9twiRxZCddX0bsIDVp0pT dqZ8EVqzdkNjlk8GNl2ogdx9J1puJqNRwN0RzWp2fBXgextDkKNYrM6lWnDYzpnu1F9L +0L2C/D8v9I/6adto4+kNnZ0yYjtRfkiPoPSOjM6FSL7x1RiNAjfeqYW+COo5yau6LqY 657A== X-Gm-Message-State: AOAM531EH+0LnVPmZ/giGO4uz6ejvWrf5IsBTGtr6JL4xN2/febfSFK6 PbSyg6yVEq/wPgPrukweaoDKWc6h3pY= X-Google-Smtp-Source: ABdhPJxBaQNXtyGD8dhFMG0rTvuje7KSg1St0xidYAdYw8pJDEOzrI/xNhyhGBTWV3iL65bgyq5YRTWE8mM= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90a:3ee4:: with SMTP id k91mr295603pjc.1.1634013407117; Mon, 11 Oct 2021 21:36:47 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:28 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-19-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 18/25] KVM: arm64: Introduce framework to trap disabled features From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When a CPU feature that is supported on the host is not exposed to its guest, emulating a real CPU's behavior (by trapping or disabling guest's using the feature) is generally a desirable behavior (when it's possible without any or little side effect). Introduce feature_config_ctrl structure, which manages feature information to program configuration register to trap or disable the feature when the feature is not exposed to the guest, and functions that uses the structure to activate trapping the feature. At present, no feature has feature_config_ctrl yet and the following patches will add the feature_config_ctrl for several features. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 117 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 536e313992d4..55c514e21214 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -281,6 +281,35 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT) >= \ ID_AA64ISAR1_GPI_IMP_DEF) +enum vcpu_config_reg { + VCPU_HCR_EL2 = 1, + VCPU_MDCR_EL2, + VCPU_CPTR_EL2, +}; + +/* + * Feature information to program configuration register to trap or disable + * guest's using a feature when the feature is not exposed to the guest. + */ +struct feature_config_ctrl { + /* ID register/field for the feature */ + u32 ftr_reg; /* ID register */ + bool ftr_signed; /* Is the feature field signed ? */ + u8 ftr_shift; /* Field of ID register for the feature */ + s8 ftr_min; /* Min value that indicate the feature */ + + /* + * Function to check trapping is needed. This is used when the above + * fields are not enough to determine if trapping is needed. + */ + bool (*ftr_need_trap)(struct kvm_vcpu *vcpu); + + /* Configuration register information to trap the feature. */ + enum vcpu_config_reg cfg_reg; /* Configuration register */ + u64 cfg_mask; /* Field of the configuration register */ + u64 cfg_val; /* Value that are set for the field */ +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -302,6 +331,9 @@ struct id_reg_info { /* Return the reset value of the register for the vCPU */ u64 (*get_reset_val)(struct kvm_vcpu *vcpu, struct id_reg_info *id_reg); + + /* Information to trap features that are disabled for the guest */ + const struct feature_config_ctrl *(*trap_features)[]; }; static void id_reg_info_init(struct id_reg_info *id_reg) @@ -717,6 +749,47 @@ static int validate_id_reg(struct kvm_vcpu *vcpu, return err; } +static void feature_trap_activate(struct kvm_vcpu *vcpu, + const struct feature_config_ctrl *config) +{ + u64 *reg_ptr, reg_val; + + switch (config->cfg_reg) { + case VCPU_HCR_EL2: + reg_ptr = &vcpu->arch.hcr_el2; + break; + case VCPU_MDCR_EL2: + reg_ptr = &vcpu->arch.mdcr_el2; + break; + case VCPU_CPTR_EL2: + reg_ptr = &vcpu->arch.cptr_el2; + break; + } + + /* Update cfg_mask fields with cfg_val */ + reg_val = (*reg_ptr & ~config->cfg_mask); + reg_val |= config->cfg_val; + *reg_ptr = reg_val; +} + +static inline bool feature_avail(const struct feature_config_ctrl *ctrl, + u64 id_val) +{ + int field_val = cpuid_feature_extract_field(id_val, + ctrl->ftr_shift, ctrl->ftr_signed); + + return (field_val >= ctrl->ftr_min); +} + +static inline bool vcpu_feature_is_available(struct kvm_vcpu *vcpu, + const struct feature_config_ctrl *ctrl) +{ + u64 val; + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(ctrl->ftr_reg)); + return feature_avail(ctrl, val); +} + /* * ARMv8.1 mandates at least a trivial LORegion implementation, where all the * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0 @@ -1570,6 +1643,42 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id); static int reg_to_user(void __user *uaddr, const u64 *val, u64 id); static u64 sys_reg_to_index(const struct sys_reg_desc *reg); +static void id_reg_features_trap_activate(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg) +{ + u64 val; + int i = 0; + const struct feature_config_ctrl **ctrlp_array, *ctrl; + + if (!id_reg || !id_reg->trap_features) + /* No information to trap a feature */ + return; + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id_reg->sys_reg)); + if (val == id_reg->sys_val) + /* No feature needs to be trapped (no feature is disabled). */ + return; + + ctrlp_array = *id_reg->trap_features; + while ((ctrl = ctrlp_array[i++]) != NULL) { + if (ctrl->ftr_need_trap && ctrl->ftr_need_trap(vcpu)) { + feature_trap_activate(vcpu, ctrl); + continue; + } + + if (!feature_avail(ctrl, id_reg->sys_val)) + /* The feature is not supported on the host. */ + continue; + + if (feature_avail(ctrl, val)) + /* The feature is enabled for the guest. */ + continue; + + /* The feature is supported but disabled. */ + feature_trap_activate(vcpu, ctrl); + } +} + /* Visibility overrides for SVE-specific control registers */ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) @@ -3195,6 +3304,14 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) return write_demux_regids(uindices); } +void kvm_vcpu_id_regs_trap_activate(struct kvm_vcpu *vcpu) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(id_reg_info_table); i++) + id_reg_features_trap_activate(vcpu, id_reg_info_table[i]); +} + /* ID register's fractional field information with its feature field. */ struct feature_frac { u32 frac_id; From patchwork Tue Oct 12 04:35:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551391 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BD04C433F5 for ; Tue, 12 Oct 2021 04:37:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 04E6560238 for ; Tue, 12 Oct 2021 04:37:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232802AbhJLEjG (ORCPT ); Tue, 12 Oct 2021 00:39:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37332 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232674AbhJLEiy (ORCPT ); Tue, 12 Oct 2021 00:38:54 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1526EC061777 for ; Mon, 11 Oct 2021 21:36:49 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id g10-20020a17090a578a00b0019f1277a815so893403pji.1 for ; Mon, 11 Oct 2021 21:36:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=aRSx5zsU8oar0tb24ztRfo+cPgh7JwnM1ai34rY7D1c=; b=cYhiDj33nfyC1+mBMm3OX/sk39KmpppUj6JtIztRs3tz0amKzYK5kcV4cxVpWZXfg4 bTWk0/6bU4Zvq2uI+1uL/yMfWefIo4MQdEckJ44mowOvJtPPi0vus7k/2XEqB2ypPjY9 fJX+tPmHrUgbq1fgzi8vtt8vcgO7dp1y5ioqBi0XzM89yZPoQd7PvWicCEHqmA23SP9q lH7fwIHrQjJtLM3nTriL0j9gmXlmqAPikl59xzwEsrjG139moFR1UUaBdUzjfgt+89UO WMoGcLgXEcRUFn2J9P77SlB4HqSPpjpY9XeBggk036qs3o/688SPHWQpfyAVju5CnKgT oIxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=aRSx5zsU8oar0tb24ztRfo+cPgh7JwnM1ai34rY7D1c=; b=dvFAcuh5ISON0hF7MTLMME3mlODUGKy4LsTIbE53KqyQGosv4XwUY3kCOa6NaRD0Pf 33v/5Pwl0Q6rwRqDNL4hkGKSJZQeuRBp/YmnGtQM3U8R3PBxNx3hR1LYVq9NnTTjG1ye 9l30spIWQzZ2LYVs7m5LsBIIg4T+X0z4H40WCeuy25ECGj0qvxoV5CiPb+aOBcfEPMwJ BW1OemJ/TuVj8mqNFKkiozHcJMZ8GLtEJkMJwcEF7yxTGLrnmp7UK5FBaMlYdpLvVJHW RazdGP35xhzja2wiyrkYyMGW8+9oi+svBgYWQHVdE29T3hHJO4Prf0ToirUKm5424qGx 31/g== X-Gm-Message-State: AOAM531HMkU1KnJ1NyZfJHFyPN9N6DdaNtPlg4eAx9VWiOIvg5u2bbpF Egway3pZM49Ur9a+A4NbRee4caMHB1Y= X-Google-Smtp-Source: ABdhPJwMjijcnPLmRF0gVFsrWCvfaeII36N+1PxEShOqBpmnd6e5wcu2sZR24dDiEMFwJYbs4Q5g7aB3YhQ= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a05:6a00:181c:b0:44c:bf17:e8ad with SMTP id y28-20020a056a00181c00b0044cbf17e8admr28869751pfa.67.1634013408614; Mon, 11 Oct 2021 21:36:48 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:29 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-20-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 19/25] KVM: arm64: Trap disabled features of ID_AA64PFR0_EL1 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add feature_config_ctrl for RAS and AMU, which are indicated in ID_AA64PFR0_EL1, to program configuration registers to trap guest's using those features when they are not exposed to the guest. Introduce trap_ras_regs() to change a behavior of guest's access to the registers, which is currently raz/wi, depending on the feature's availability for the guest (and inject undefined instruction exception when guest's RAS register access are trapped and RAS is not exposed to the guest). In order to keep the current visibility of the RAS registers from userspace (always visible), a visibility function for RAS registers is not added. No code is added for AMU's access/visibility handler because the current code already injects the exception for Guest's AMU register access unconditionally because AMU is never exposed to the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 54 +++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 55c514e21214..2b45db310151 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -310,6 +310,27 @@ struct feature_config_ctrl { u64 cfg_val; /* Value that are set for the field */ }; +/* For ID_AA64PFR0_EL1 */ +static struct feature_config_ctrl ftr_ctrl_ras = { + .ftr_reg = SYS_ID_AA64PFR0_EL1, + .ftr_shift = ID_AA64PFR0_RAS_SHIFT, + .ftr_min = ID_AA64PFR0_RAS_V1, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_HCR_EL2, + .cfg_mask = (HCR_TERR | HCR_TEA | HCR_FIEN), + .cfg_val = (HCR_TERR | HCR_TEA), +}; + +static struct feature_config_ctrl ftr_ctrl_amu = { + .ftr_reg = SYS_ID_AA64PFR0_EL1, + .ftr_shift = ID_AA64PFR0_AMU_SHIFT, + .ftr_min = ID_AA64PFR0_AMU, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_CPTR_EL2, + .cfg_mask = CPTR_EL2_TAM, + .cfg_val = CPTR_EL2_TAM, +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -660,6 +681,11 @@ static struct id_reg_info id_aa64pfr0_el1_info = { .init = init_id_aa64pfr0_el1_info, .validate = validate_id_aa64pfr0_el1, .get_reset_val = get_reset_id_aa64pfr0_el1, + .trap_features = &(const struct feature_config_ctrl *[]) { + &ftr_ctrl_ras, + &ftr_ctrl_amu, + NULL, + }, }; static struct id_reg_info id_aa64pfr1_el1_info = { @@ -790,6 +816,18 @@ static inline bool vcpu_feature_is_available(struct kvm_vcpu *vcpu, return feature_avail(ctrl, val); } +static bool trap_ras_regs(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + if (!vcpu_feature_is_available(vcpu, &ftr_ctrl_ras)) { + kvm_inject_undefined(vcpu); + return false; + } + + return trap_raz_wi(vcpu, p, r); +} + /* * ARMv8.1 mandates at least a trivial LORegion implementation, where all the * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0 @@ -2052,14 +2090,14 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 }, { SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 }, - { SYS_DESC(SYS_ERRIDR_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERRSELR_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXFR_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXCTLR_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXSTATUS_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXADDR_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi }, - { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERRIDR_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERRSELR_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXFR_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXCTLR_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXSTATUS_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXADDR_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXMISC0_EL1), trap_ras_regs }, + { SYS_DESC(SYS_ERXMISC1_EL1), trap_ras_regs }, MTE_REG(TFSR_EL1), MTE_REG(TFSRE0_EL1), From patchwork Tue Oct 12 04:35:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551393 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8838AC4332F for ; Tue, 12 Oct 2021 04:37:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 726846044F for ; Tue, 12 Oct 2021 04:37:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233372AbhJLEjH (ORCPT ); Tue, 12 Oct 2021 00:39:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37282 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232830AbhJLEi4 (ORCPT ); Tue, 12 Oct 2021 00:38:56 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ACA3C061778 for ; Mon, 11 Oct 2021 21:36:51 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id i83-20020a256d56000000b005b706d1417bso25890512ybc.6 for ; Mon, 11 Oct 2021 21:36:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=coUrbvM5Lflty8spiztbsAsv+oJSc+F2TzdUPHTvF9k=; b=Ej/iKb8rhpuAFcFhtUeJxd6vSSdkQ2BxL4TjlXKczR/6dr5X6ci0KopMAWsHDKOqjv okJL8Sppbfs3inGm9cGEmEYOuaQpNVgtJFpM7j8m66AwkUwYxOU1sjQ443h6XFSBJmMK v5b7RbvmeJRv4kOx4BcVMQ3hiBWnsJ7CuryfbV04C0oCi80aONDVPBeImSrVKgXQCb0d FB9No1u+1RpUHV6C7uwVmJPr1oYspLsYn6DzWVKGUDNNQ2badK3vWNggpGelXEpMFnF+ IH06c42XNyHc9Mbeg+uit5VZ7HA0CiQyecbm7ta0nasgP0t0rBUVAX5EePI+t7TMCE+t QqnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=coUrbvM5Lflty8spiztbsAsv+oJSc+F2TzdUPHTvF9k=; b=3TaWWOQAHf63NybKiJsPBLFp68uFTW6RTWd/YbUboTNWcB9ZisBrgfJp6C0/kqy55m OwmY7tdZInN6KHcUNPqhpg2+bEV5iy4jihW4dHPdsJeYaCBijDXgu4eWn2gwCq9Or1Nh oP1EY5x5MvOzeU74buvqE4RPb2bSNEoOa8hXV3FbQk7zzvF/UNZeDQISXo19zaLW4IZL yTUJSRwmYa+4MZgtX+zKP1TSe2fBSgX/19NfTz6VtlqMbTqRQ4Qp29qJOFpeyuLVlacl EJWHpUUp8ShRb2w6NS1tLQq+LsEnNcVuR+1HL5kv2GXWaKme29cgOo/fKo8Ieb4M2Yh1 rsDA== X-Gm-Message-State: AOAM533VO81JM9TykP0HFjfvEvXXMu+22W1qiwLlvvrgiNQ6QebfQ/bX fPoW6JiW7Xjc7fQDqGutG87r4NoX3zY= X-Google-Smtp-Source: ABdhPJwPvi/lmgC+gTZ21/Wz66CiGZojJBK5kwnJiiX4LQSzHxbRpLQV3my0CP726mGMYzFbz6D93vOC+Rk= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a25:1c45:: with SMTP id c66mr27703481ybc.133.1634013410276; Mon, 11 Oct 2021 21:36:50 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:30 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-21-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 20/25] KVM: arm64: Trap disabled features of ID_AA64PFR1_EL1 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add feature_config_ctrl for MTE, which is indicated in ID_AA64PFR1_EL1, to program configuration register to trap the guest's using the feature when it is not exposed to the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2b45db310151..595ab1c79bae 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -331,6 +331,17 @@ static struct feature_config_ctrl ftr_ctrl_amu = { .cfg_val = CPTR_EL2_TAM, }; +/* For ID_AA64PFR1_EL1 */ +static struct feature_config_ctrl ftr_ctrl_mte = { + .ftr_reg = SYS_ID_AA64PFR1_EL1, + .ftr_shift = ID_AA64PFR1_MTE_SHIFT, + .ftr_min = ID_AA64PFR1_MTE_EL0, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_HCR_EL2, + .cfg_mask = (HCR_TID5 | HCR_DCT | HCR_ATA), + .cfg_val = HCR_TID5, +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -693,6 +704,10 @@ static struct id_reg_info id_aa64pfr1_el1_info = { .init = init_id_aa64pfr1_el1_info, .validate = validate_id_aa64pfr1_el1, .get_reset_val = get_reset_id_aa64pfr1_el1, + .trap_features = &(const struct feature_config_ctrl *[]) { + &ftr_ctrl_mte, + NULL, + }, }; static struct id_reg_info id_aa64isar0_el1_info = { From patchwork Tue Oct 12 04:35:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551395 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B06FC433F5 for ; Tue, 12 Oct 2021 04:37:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5597160EE2 for ; Tue, 12 Oct 2021 04:37:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233409AbhJLEjL (ORCPT ); Tue, 12 Oct 2021 00:39:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232716AbhJLEjA (ORCPT ); Tue, 12 Oct 2021 00:39:00 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 283BBC06177B for ; Mon, 11 Oct 2021 21:36:52 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id oo5-20020a17090b1c8500b0019e585e8f6fso876167pjb.9 for ; Mon, 11 Oct 2021 21:36:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=X2MC5tS4urnyh50skPCY/9xIv7Rg4adWM6caa08DYXc=; b=inNCt9FpIq76B+VhKdpWkwhHuSBX1gL+4xixhQW+svRbgV2n+ibgsdFUCNmdtoMru2 /it/NY6mdNUiEezsHyd52DTIcssGR44sV17vmvs3biSKEQaMcDmePmVdCsE7EOOmmICQ g3K5iFvnZOU1DXcSFi3420WslBqkRO1yBTilD2CQLSFmjVj/FnILkKaZBBVq8qOJOqwI w07qZGVrqOdO8jQH5FI+AHLzxUDDqdXxSOg6Ln7nkNxoSl1AUhvikgKBoaHiZKe2hZ0S cVlQJHpaMstreT9JmVbLDZ2PiW3p0ajTViN3Kr0rA8/MLsVEqSUGf+/i2fAnNshMHjyF hXmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=X2MC5tS4urnyh50skPCY/9xIv7Rg4adWM6caa08DYXc=; b=K0dGXOAJLCbHMUu5vFnGPPKzxg9fBLpN4hMpClkthfNjFWJSjU/SrfgPGwIkSKYTyD Jap1iUyEpDGbcztm9IFEp63Q3hzaKb4GmGBSgr3T5n7LFd6xI4Tzswx/9rLQerKXOaIa IOosF7hPymQ/RhMhG6MBiMx96/+49q5x3yhbJFkb/KA9WYtc0CDzJnHOaWBmlV2g9FP/ fURmmkmAnVfGIZjGaL06hC0ZMTNMibZi0qGOu4b3mdb/h1gWOrcQAHMzqS7p1dvQ/cV4 RGyaIlKr6pevoWs3pRnniEFpnlINmOxdBLhOkWgqk3ETPeZ6tCYQA1LzUf2I07S7HRAj PkVw== X-Gm-Message-State: AOAM533OpKhQWOm8TUEnS/WFdWzv4GRXvgKSfC9BhOoDOMt/7m3ya2aT qq96B0nHXq0keOvCbSN37ibXH/7hcyw= X-Google-Smtp-Source: ABdhPJyXRkRDYHX+V64uORGsvksZYYcAzeDYpRvgXni5jgbKqEJlLN+vJO2JfCbxPWmEGCNi7HHH8xh+o+g= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:aa7:81c7:0:b0:44c:517f:a759 with SMTP id c7-20020aa781c7000000b0044c517fa759mr29319641pfn.3.1634013411673; Mon, 11 Oct 2021 21:36:51 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:31 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-22-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 21/25] KVM: arm64: Trap disabled features of ID_AA64DFR0_EL1 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add feature_config_ctrl for PMUv3, PMS and TraceFilt, which are indicated in ID_AA64DFR0_EL1, to program configuration registers to trap guest's using those features when they are not exposed to the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 595ab1c79bae..23a3bcac4986 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -342,6 +342,38 @@ static struct feature_config_ctrl ftr_ctrl_mte = { .cfg_val = HCR_TID5, }; +/* For ID_AA64DFR0_EL1 */ +static struct feature_config_ctrl ftr_ctrl_pmuv3 = { + .ftr_reg = SYS_ID_AA64DFR0_EL1, + .ftr_shift = ID_AA64DFR0_PMUVER_SHIFT, + .ftr_min = ID_AA64DFR0_PMUVER_8_0, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_MDCR_EL2, + .cfg_mask = MDCR_EL2_TPM, + .cfg_val = MDCR_EL2_TPM, +}; + +static struct feature_config_ctrl ftr_ctrl_pms = { + .ftr_reg = SYS_ID_AA64DFR0_EL1, + .ftr_shift = ID_AA64DFR0_PMSVER_SHIFT, + .ftr_min = ID_AA64DFR0_PMSVER_8_2, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_MDCR_EL2, + .cfg_mask = (MDCR_EL2_TPMS | + (MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)), + .cfg_val = MDCR_EL2_TPMS, +}; + +static struct feature_config_ctrl ftr_ctrl_tracefilt = { + .ftr_reg = SYS_ID_AA64DFR0_EL1, + .ftr_shift = ID_AA64DFR0_TRACE_FILT_SHIFT, + .ftr_min = 1, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_MDCR_EL2, + .cfg_mask = MDCR_EL2_TTRF, + .cfg_val = MDCR_EL2_TTRF, +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -727,6 +759,12 @@ static struct id_reg_info id_aa64dfr0_el1_info = { .init = init_id_aa64dfr0_el1_info, .validate = validate_id_aa64dfr0_el1, .get_reset_val = get_reset_id_aa64dfr0_el1, + .trap_features = &(const struct feature_config_ctrl *[]) { + &ftr_ctrl_pmuv3, + &ftr_ctrl_pms, + &ftr_ctrl_tracefilt, + NULL, + }, }; static struct id_reg_info id_dfr0_el1_info = { From patchwork Tue Oct 12 04:35:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551397 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FA0CC433F5 for ; Tue, 12 Oct 2021 04:37:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5DA2560E52 for ; Tue, 12 Oct 2021 04:37:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233433AbhJLEjM (ORCPT ); Tue, 12 Oct 2021 00:39:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37314 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232963AbhJLEjA (ORCPT ); Tue, 12 Oct 2021 00:39:00 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1DCAC061766 for ; Mon, 11 Oct 2021 21:36:53 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id m14-20020a63fd4e000000b00287791fb324so8049827pgj.7 for ; Mon, 11 Oct 2021 21:36:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Q7BixuP9It6rmSZII5to1B682tn/DwfVjd2jGHGuE3Y=; b=VGyjwy0JLnxlj+5/nSK7fzF48FMF95j1whwYEMpop9FWTB0rqlyROF9oshJ3QC19Ah /nWVAeJYXtbJeeOlLH1Hc9uwEfAtyGk8MUxmFTq19H8/qadkNx6jrZEnOkwURLzC2fUl igxGrUonWVrPb8y1F0DrvziuACcatliv7ZDhATMzOtkVF4HHKQv1Hjb7OBYAni2IPR+/ tShJ+JcFQPQigr0Xzq/uFDjxCZfpv+E8aCD0o5d5RL9BKthxy7V7aHUj533ZCFAyxkRO ZIRjwMvfOuP1CUsBO4HcQZ6sG+oThFCDbNRhtPeEP8AfPXKh5RA4n8TfknOirMYZ7Oqh e7Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Q7BixuP9It6rmSZII5to1B682tn/DwfVjd2jGHGuE3Y=; b=1+XWr3mY1XAxlEHbT2V5Q9jU/QszhlfsAEKOEha7koVxAyj4wf0+n4szDS06tgJ1q1 o7j+rMlQVwK0f1TPQpN5u6wI2Rvde4oINkT01YLW/QTcp4UpGSnw3yRYD3r3jqmud9Ce A60oxXAXEL49Zx17xzEqa1+pl5g1sbVDnzHEY3+MJIlR4FxLcXFTKJPDmAlwQ6TzVYL9 4iZClxblwOQ0QFRd3UjaOtnbRTVsYn61k0RfIOI6MwLnXDNoWyALTXe0Cjf/sOSd2qOq S+r3MEr8utJPxx5Yk/17mieity7blMPxRKQNw9NSWOAb5EoeINCrAw30UT4Lp4w2+PP7 fDRw== X-Gm-Message-State: AOAM531H91jeD4aYmbFwG48KyDv5CYDhVLGe0hVxUGE1I9YNJRgcluzm hroKw3KSCu09q0XTyNViRwn3exdpDfk= X-Google-Smtp-Source: ABdhPJw5rppfGPZ6lLyq9dLDd23bK7T/kn8o9AZfVh2XW/iGmZLrNXsPL87P/02l4KUEPKW2WmekxAQ68aU= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a05:6a00:2284:b0:43d:fc72:e565 with SMTP id f4-20020a056a00228400b0043dfc72e565mr29890632pfe.84.1634013413069; Mon, 11 Oct 2021 21:36:53 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:32 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-23-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 22/25] KVM: arm64: Trap disabled features of ID_AA64MMFR1_EL1 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add feature_config_ctrl for LORegions, which is indicated in ID_AA64MMFR1_EL1, to program configuration register to trap guest's using the feature when it is not exposed to the guest. Change trap_loregion() to use vcpu_feature_is_available() to simplify checking of the feature's availability. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 23a3bcac4986..68df4e4eba05 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -374,6 +374,17 @@ static struct feature_config_ctrl ftr_ctrl_tracefilt = { .cfg_val = MDCR_EL2_TTRF, }; +/* For ID_AA64MMFR1_EL1 */ +static struct feature_config_ctrl ftr_ctrl_lor = { + .ftr_reg = SYS_ID_AA64MMFR1_EL1, + .ftr_shift = ID_AA64MMFR1_LOR_SHIFT, + .ftr_min = 1, + .ftr_signed = FTR_UNSIGNED, + .cfg_reg = VCPU_HCR_EL2, + .cfg_mask = HCR_TLOR, + .cfg_val = HCR_TLOR, +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -767,6 +778,14 @@ static struct id_reg_info id_aa64dfr0_el1_info = { }, }; +static struct id_reg_info id_aa64mmfr1_el1_info = { + .sys_reg = SYS_ID_AA64MMFR1_EL1, + .trap_features = &(const struct feature_config_ctrl *[]) { + &ftr_ctrl_lor, + NULL, + }, +}; + static struct id_reg_info id_dfr0_el1_info = { .sys_reg = SYS_ID_DFR0_EL1, .init = init_id_dfr0_el1_info, @@ -795,6 +814,7 @@ static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64DFR0_EL1)] = &id_aa64dfr0_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR0_EL1)] = &id_aa64isar0_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR1_EL1)] = &id_aa64isar1_el1_info, + [IDREG_IDX(SYS_ID_AA64MMFR1_EL1)] = &id_aa64mmfr1_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, @@ -891,10 +911,9 @@ static bool trap_loregion(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - u64 val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(SYS_ID_AA64MMFR1_EL1)); u32 sr = reg_to_encoding(r); - if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { + if (!vcpu_feature_is_available(vcpu, &ftr_ctrl_lor)) { kvm_inject_undefined(vcpu); return false; } From patchwork Tue Oct 12 04:35:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551399 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DCD7C433F5 for ; Tue, 12 Oct 2021 04:37:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7142560EE5 for ; Tue, 12 Oct 2021 04:37:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233463AbhJLEjR (ORCPT ); Tue, 12 Oct 2021 00:39:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37268 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233174AbhJLEjE (ORCPT ); Tue, 12 Oct 2021 00:39:04 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 466CFC0613E3 for ; Mon, 11 Oct 2021 21:36:55 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id d5-20020a63ed05000000b002688d3aff8aso8041376pgi.2 for ; Mon, 11 Oct 2021 21:36:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=7vo9Jye3iy34d7wxk7g8XLP+SJucgQI7Y2FBb4PVMnw=; b=XCT8s0xZr8hIUrdDmvqfnOnxYqMGJEiaoh+nFQ5WhVn0ZRTLWHNTAn+HFJmbjCOnY6 x5CrPKVbLKHn40TQUW6a7Q7MVzdtVa4bBdMtIBG8yxn4VHVcVH8spAAakxPJeKOiObxk 7xAxslDtmuqWhePLlKBtuFovwM6E11QC69B+fMBVFwNCeVZTacs5Lyd0WdW3GE3W7S2I Xk+6327uHlA8k24iPB2Rs4HTIpXl7swnhKavBqrVmt7TV46GZ+okhJnmWDSjvxezpDyE StUmedw/6Ehw533z4QaBgSx9/KKX3YCeVLKGVZzAXzgfoBIc9HpvhWvm8/2pXkJttqTB giJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=7vo9Jye3iy34d7wxk7g8XLP+SJucgQI7Y2FBb4PVMnw=; b=VD5aC6VIol02z924Ilsw1jsnEydJ42+CmyH+BXBYgLxx6cRMldxFew+377cW5IjRaT w30P/BoWx95T7ep0dg7ylpW0dqGmmL9oojvJ6aeSeQowAFSLxuvvPhWFxqITPQDHPPuJ mWzFkjtiiDpQyGqzlvAX98dEcaBTj3f35BwL/UgxKeTjbUqw4Cb7WwkmOotBFqKufan4 4L/3csakPbkq6tAZsUP+mhlGk0J8ee3rztTpHSOJygGVls3U00XUkLAQxDlLPhTTfxfo S/0xK9495xLO7xM2Q4/ced1BjTVw30ezsnJ62Ua+3hzZm9DWFvcjErN5DKJwmw3Wq31U XdFw== X-Gm-Message-State: AOAM532R+5zgsy4UBl3G8IHpPQ2k0h1v2muJ8T3EeH21oroVaAm+/XJH TO6keGTwFt7XZ7JyJP0fX9fbSz/gJeE= X-Google-Smtp-Source: ABdhPJx0SaVYdmsGOHnnA4GhbM5OqxPa33tsX7LZFC6lKXCPshs+pcbFLj6wvFn9yiyMZ22Y3bGPzseV7Jk= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:902:8b8b:b0:13d:e91c:a1b9 with SMTP id ay11-20020a1709028b8b00b0013de91ca1b9mr28229688plb.60.1634013414788; Mon, 11 Oct 2021 21:36:54 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:33 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-24-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 23/25] KVM: arm64: Trap disabled features of ID_AA64ISAR1_EL1 From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add feature_config_ctrl for PTRAUTH, which is indicated in ID_AA64ISAR1_EL1, to program configuration register to trap guest's using the feature when it is not exposed to the guest. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 68df4e4eba05..e74b33741dc4 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -281,6 +281,35 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, (cpuid_feature_extract_unsigned_field(val, ID_AA64ISAR1_GPI_SHIFT) >= \ ID_AA64ISAR1_GPI_IMP_DEF) +/* + * Return true if ptrauth needs to be trapped. + * (i.e. if ptrauth is supported on the host but not exposed to the guest) + */ +static bool vcpu_need_trap_ptrauth(struct kvm_vcpu *vcpu) +{ + u64 val; + unsigned int gpi, gpa, api, apa; + unsigned int generic, address; + + if (!system_has_full_ptr_auth()) + /* The feature is not supported. */ + return false; + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(SYS_ID_AA64ISAR1_EL1)); + gpi = aa64isar1_has_gpi(val); + gpa = aa64isar1_has_gpa(val); + api = aa64isar1_has_api(val); + apa = aa64isar1_has_apa(val); + generic = gpi || gpa; + address = api || apa; + if (generic && address) + /* The feature is available. */ + return false; + + /* The feature is supported but hidden. */ + return true; +} + enum vcpu_config_reg { VCPU_HCR_EL2 = 1, VCPU_MDCR_EL2, @@ -385,6 +414,14 @@ static struct feature_config_ctrl ftr_ctrl_lor = { .cfg_val = HCR_TLOR, }; +/* For SYS_ID_AA64ISAR1_EL1 */ +static struct feature_config_ctrl ftr_ctrl_ptrauth = { + .ftr_need_trap = vcpu_need_trap_ptrauth, + .cfg_reg = VCPU_HCR_EL2, + .cfg_mask = (HCR_API | HCR_APK), + .cfg_val = 0, +}; + struct id_reg_info { u32 sys_reg; /* Register ID */ u64 sys_val; /* Sanitized system value */ @@ -763,6 +800,10 @@ static struct id_reg_info id_aa64isar1_el1_info = { .init = init_id_aa64isar1_el1_info, .validate = validate_id_aa64isar1_el1, .get_reset_val = get_reset_id_aa64isar1_el1, + .trap_features = &(const struct feature_config_ctrl *[]) { + &ftr_ctrl_ptrauth, + NULL, + }, }; static struct id_reg_info id_aa64dfr0_el1_info = { From patchwork Tue Oct 12 04:35:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551401 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07B4AC433FE for ; Tue, 12 Oct 2021 04:37:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E4FAE60E52 for ; Tue, 12 Oct 2021 04:37:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232598AbhJLEjS (ORCPT ); Tue, 12 Oct 2021 00:39:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233210AbhJLEjF (ORCPT ); Tue, 12 Oct 2021 00:39:05 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F3AAC061749 for ; Mon, 11 Oct 2021 21:36:56 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id o6-20020a170902bcc600b00138a9a5bc42so8385150pls.17 for ; Mon, 11 Oct 2021 21:36:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=eIUhuChkelcONVLGBJ0a2MPEEEhxwwehMuijtFOAuDI=; b=RuE+yIAI83dgKgc0EI81lpKKKdaCzCn8+SfDwPeU8Fln6xA4/deZlxo2DwtD71VRgy cw6TSj8JyRvn5oKLcvmqRuGF7hVSbUVdrEMEKUojpjZyBBQ+tJ1vSUHBrWlg1IuSMZPv R+rpCZeNhqGRUmc+stVB+dTUWZ147p6Jjc9tP2WejjahKq68g464d/gR3s99oJIo6lWp A/jaKj7gVcm9U7Tzh6Orb4tNznNnOji9vtaNMWche+5EZdUD4rHwml9Y4DQ6LY92/e/n yuPPhMOR//Z2EmHt3/Rk9H1biH/MgK7UmW3yEvDk4dlwnyojLI/KFQPcSc40TnGmCYIW ZXcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=eIUhuChkelcONVLGBJ0a2MPEEEhxwwehMuijtFOAuDI=; b=m1o8hmftfTdssyPEnaZaqCp7Xe/CWgBExXaORqH+b+fYBKi0E10Pj2okZHCnH87xKH 34EvJqfTn1RsPX7vEI6Rmy4qA2tP8R3UzX4Y0d6UR93dpD8sPBUu6inm5YsyF3IX26zD bYBh2iJMtUVE9cgecp9LyDd+MYXtWcuZF8YwWd3Sh87pYj7o7IxXFrNoM8IIVCqVbjU2 tFF30MBs/+z+OylwJdoYAlN6A2QHRFV+KiaD3vgmnV4hXfeGHeOPXIMJIMoPYgcYy7lc AhTzmSeNrkS+5wcpd7KbzdjGwW2JyK8EsskM23cijp6EDVtmaU+MP2bv7BSsH9s5TOCX 4vWQ== X-Gm-Message-State: AOAM530C160ISYsxccXAYbkfcvYZbdEMePYhMRY4xO5rTDm7SnG8jx/7 9DTmSgs+BwjyLH3rNh5sl7a/txV5BOE= X-Google-Smtp-Source: ABdhPJyTEEEJJ8ULSCGnE5RUuiEtmSCACpElVLQCVz7cpGVyLWG6TLcY5A92rMWKWU0CqVfHfvo0h0Ok6PA= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:902:6ac4:b0:13f:52e1:8840 with SMTP id i4-20020a1709026ac400b0013f52e18840mr1435432plt.15.1634013416153; Mon, 11 Oct 2021 21:36:56 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:34 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-25-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 24/25] KVM: arm64: Activate trapping of disabled CPU features for the guest From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Call kvm_vcpu_id_regs_trap_activate() at the first KVM_RUN to activate trapping of disabled CPU features. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/arm.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 691cb6ee0f5c..41f785fdc2e6 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -743,6 +743,7 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, struct kvm_arm_copy_mte_tags *copy_tags); int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu); +void kvm_vcpu_id_regs_trap_activate(struct kvm_vcpu *vcpu); /* Guest/host FPSIMD coordination helpers */ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 38301ddf8372..6b392d7feab7 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -606,6 +606,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) if (kvm_id_regs_consistency_check(vcpu)) return -EPERM; + kvm_vcpu_id_regs_trap_activate(vcpu); + return ret; } From patchwork Tue Oct 12 04:35:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12551403 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A9CC1C433F5 for ; Tue, 12 Oct 2021 04:37:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8BE9560E52 for ; Tue, 12 Oct 2021 04:37:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232880AbhJLEjT (ORCPT ); Tue, 12 Oct 2021 00:39:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232792AbhJLEjF (ORCPT ); Tue, 12 Oct 2021 00:39:05 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26F4AC0613E6 for ; Mon, 11 Oct 2021 21:36:58 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id d5-20020a63ed05000000b002688d3aff8aso8041426pgi.2 for ; Mon, 11 Oct 2021 21:36:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=F4iS/JS5o366hKiMrkuWZ9m27Iy2Dx1PXZ2dYLdTzsw=; b=Z4DOHzlv3tDZnYeYvu36Uh28AvRZsjq87djOQFxTy0xXLdMlCQ8Q80Xuu8J97J1XIs P6f266jDcLR3Ql4nFzGzv8mcuwt9b3hJ6YmU2SZgKRhspV0Ad3QhyrYQAmMS9psKGnCu q4bhGDa8BixzYSMcynwhcPL9adtMzR6MakRKWMyBwZ2ChCRA2OLR7+VjyiXZifng9HrI Dx/vYD69rbLEAGhR+p2BbO5tDIfLHwUIuFtdFPWWI3e/KS9/FTl8OVFG2WmJ2zNO3Ygr /cZdol0rxa8u4EZp43JLZjgewoWssfK38QhJFiy6GYAIQWC02aa2xKo9DTOrrmZ4fQYx Rk5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=F4iS/JS5o366hKiMrkuWZ9m27Iy2Dx1PXZ2dYLdTzsw=; b=I8NMeFos+c7kYuHFdCWO59kvBcKoJ1c/iadvNJxWoEWfYyDzty02EzsuJMipwN44xP z/jw7dv6PAZkK183dsCOa+/MkXin6Ub+sNL2Y8Q0pRvVTpdTCacFUpSxqaajOuDBXk7v rSFrkKggDriF8L56yTh66Vetdv+PVqoXFp0qpD9NZ6PXYMP+EZsY3dH5RA4DP2y0hDwN R+t1Ef8UL6EbedfYRn3KlLGWJmF8MSd09jdTPXvZuIV/OuRyxEUZi5M1dPc5N9wZ7PRK s0aBvNzWaaSNj1Apba6HixY8tDaTHFo8MgPSQgBsu7VqzMGS0zOWRmBxzaXPOfrq0+YK LUKQ== X-Gm-Message-State: AOAM532rZFbH+kKnaISB0hf7Kn9UYB9+Sd3op3FZi59NzVaG/tfAQ3u2 lFPDw2HSsuRG9FMlsQm/zcjy8oFSzKU= X-Google-Smtp-Source: ABdhPJzCS/0Tl2lU28MAYcr0P0HLgAbzU7JMD1Kf0OX1f2fMyWnGT06D5oJk7H+5kedIqmlF7J+VtCj64lo= X-Received: from reiji-vws.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:15a3]) (user=reijiw job=sendgmr) by 2002:a17:90b:1649:: with SMTP id il9mr3464381pjb.167.1634013417679; Mon, 11 Oct 2021 21:36:57 -0700 (PDT) Date: Mon, 11 Oct 2021 21:35:35 -0700 In-Reply-To: <20211012043535.500493-1-reijiw@google.com> Message-Id: <20211012043535.500493-26-reijiw@google.com> Mime-Version: 1.0 References: <20211012043535.500493-1-reijiw@google.com> X-Mailer: git-send-email 2.33.0.882.g93a45727a2-goog Subject: [RFC PATCH 25/25] KVM: arm64: selftests: Introduce id_reg_test From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, James Morse , Alexandru Elisei , Suzuki K Poulose , Paolo Bonzini , Will Deacon , Andrew Jones , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce a test for aarch64 to validate basic behavior of KVM_GET_ONE_REG and KVM_SET_ONE_REG for ID registers. This test runs only when KVM_CAP_ARM_ID_REG_WRITABLE is supported. Signed-off-by: Reiji Watanabe --- tools/arch/arm64/include/asm/sysreg.h | 1 + tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/aarch64/id_reg_test.c | 1296 +++++++++++++++++ 4 files changed, 1299 insertions(+) create mode 100644 tools/testing/selftests/kvm/aarch64/id_reg_test.c diff --git a/tools/arch/arm64/include/asm/sysreg.h b/tools/arch/arm64/include/asm/sysreg.h index 7640fa27be94..be3947c125f1 100644 --- a/tools/arch/arm64/include/asm/sysreg.h +++ b/tools/arch/arm64/include/asm/sysreg.h @@ -793,6 +793,7 @@ #define ID_AA64PFR0_ELx_32BIT_64BIT 0x2 /* id_aa64pfr1 */ +#define ID_AA64PFR1_CSV2FRAC_SHIFT 32 #define ID_AA64PFR1_MPAMFRAC_SHIFT 16 #define ID_AA64PFR1_RASFRAC_SHIFT 12 #define ID_AA64PFR1_MTE_SHIFT 8 diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 02444fc69bae..82f37dd7faa2 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -2,6 +2,7 @@ /aarch64/arch_timer /aarch64/debug-exceptions /aarch64/get-reg-list +/aarch64/id_reg_test /aarch64/psci_cpu_on_test /aarch64/vgic_init /s390x/memop diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 79947dde0b66..65e4bb1ebfcb 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -89,6 +89,7 @@ TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test TEST_GEN_PROGS_aarch64 += aarch64/arch_timer TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list +TEST_GEN_PROGS_aarch64 += aarch64/id_reg_test TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test TEST_GEN_PROGS_aarch64 += aarch64/vgic_init TEST_GEN_PROGS_aarch64 += demand_paging_test diff --git a/tools/testing/selftests/kvm/aarch64/id_reg_test.c b/tools/testing/selftests/kvm/aarch64/id_reg_test.c new file mode 100644 index 000000000000..c3ac955e6b2d --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/id_reg_test.c @@ -0,0 +1,1296 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" + +/* + * id_reg_test.c - Tests reading/writing the aarch64's ID registers + * + * The test validates KVM_SET_ONE_REG/KVM_GET_ONE_REG ioctl for ID + * registers as well as reading ID register from the guest works fine. + */ + +/* Reserved ID registers */ +#define SYS_ID_REG_3_3_EL1 sys_reg(3, 0, 0, 3, 3) +#define SYS_ID_REG_3_7_EL1 sys_reg(3, 0, 0, 3, 7) + +#define SYS_ID_REG_4_2_EL1 sys_reg(3, 0, 0, 4, 2) +#define SYS_ID_REG_4_3_EL1 sys_reg(3, 0, 0, 4, 3) +#define SYS_ID_REG_4_5_EL1 sys_reg(3, 0, 0, 4, 5) +#define SYS_ID_REG_4_6_EL1 sys_reg(3, 0, 0, 4, 6) +#define SYS_ID_REG_4_7_EL1 sys_reg(3, 0, 0, 4, 7) + +#define SYS_ID_REG_5_2_EL1 sys_reg(3, 0, 0, 5, 2) +#define SYS_ID_REG_5_3_EL1 sys_reg(3, 0, 0, 5, 3) +#define SYS_ID_REG_5_6_EL1 sys_reg(3, 0, 0, 5, 6) +#define SYS_ID_REG_5_7_EL1 sys_reg(3, 0, 0, 5, 7) + +#define SYS_ID_REG_6_2_EL1 sys_reg(3, 0, 0, 6, 2) +#define SYS_ID_REG_6_3_EL1 sys_reg(3, 0, 0, 6, 3) +#define SYS_ID_REG_6_4_EL1 sys_reg(3, 0, 0, 6, 4) +#define SYS_ID_REG_6_5_EL1 sys_reg(3, 0, 0, 6, 5) +#define SYS_ID_REG_6_6_EL1 sys_reg(3, 0, 0, 6, 6) +#define SYS_ID_REG_6_7_EL1 sys_reg(3, 0, 0, 6, 7) + +#define SYS_ID_REG_7_3_EL1 sys_reg(3, 0, 0, 7, 3) +#define SYS_ID_REG_7_4_EL1 sys_reg(3, 0, 0, 7, 4) +#define SYS_ID_REG_7_5_EL1 sys_reg(3, 0, 0, 7, 5) +#define SYS_ID_REG_7_6_EL1 sys_reg(3, 0, 0, 7, 6) +#define SYS_ID_REG_7_7_EL1 sys_reg(3, 0, 0, 7, 7) + +#define READ_ID_REG_FN(name) read_## name ## _EL1 + +#define DEFINE_READ_SYS_REG(reg_name) \ +uint64_t read_##reg_name(void) \ +{ \ + return read_sysreg_s(SYS_##reg_name); \ +} + +#define DEFINE_READ_ID_REG(name) \ + DEFINE_READ_SYS_REG(name ## _EL1) + +#define __ID_REG(reg_name) \ + .name = #reg_name, \ + .id = SYS_## reg_name ##_EL1, \ + .read_reg = READ_ID_REG_FN(reg_name), + +#define ID_REG_ENT(reg_name) \ + [ID_IDX(reg_name)] = { __ID_REG(reg_name) } + +/* Functions to read each ID register */ +/* CRm=1 */ +DEFINE_READ_ID_REG(ID_PFR0) +DEFINE_READ_ID_REG(ID_PFR1) +DEFINE_READ_ID_REG(ID_DFR0) +DEFINE_READ_ID_REG(ID_AFR0) +DEFINE_READ_ID_REG(ID_MMFR0) +DEFINE_READ_ID_REG(ID_MMFR1) +DEFINE_READ_ID_REG(ID_MMFR2) +DEFINE_READ_ID_REG(ID_MMFR3) + +/* CRm=2 */ +DEFINE_READ_ID_REG(ID_ISAR0) +DEFINE_READ_ID_REG(ID_ISAR1) +DEFINE_READ_ID_REG(ID_ISAR2) +DEFINE_READ_ID_REG(ID_ISAR3) +DEFINE_READ_ID_REG(ID_ISAR4) +DEFINE_READ_ID_REG(ID_ISAR5) +DEFINE_READ_ID_REG(ID_MMFR4) +DEFINE_READ_ID_REG(ID_ISAR6) + +/* CRm=3 */ +DEFINE_READ_ID_REG(MVFR0) +DEFINE_READ_ID_REG(MVFR1) +DEFINE_READ_ID_REG(MVFR2) +DEFINE_READ_ID_REG(ID_REG_3_3) +DEFINE_READ_ID_REG(ID_PFR2) +DEFINE_READ_ID_REG(ID_DFR1) +DEFINE_READ_ID_REG(ID_MMFR5) +DEFINE_READ_ID_REG(ID_REG_3_7) + +/* CRm=4 */ +DEFINE_READ_ID_REG(ID_AA64PFR0) +DEFINE_READ_ID_REG(ID_AA64PFR1) +DEFINE_READ_ID_REG(ID_REG_4_2) +DEFINE_READ_ID_REG(ID_REG_4_3) +DEFINE_READ_ID_REG(ID_AA64ZFR0) +DEFINE_READ_ID_REG(ID_REG_4_5) +DEFINE_READ_ID_REG(ID_REG_4_6) +DEFINE_READ_ID_REG(ID_REG_4_7) + +/* CRm=5 */ +DEFINE_READ_ID_REG(ID_AA64DFR0) +DEFINE_READ_ID_REG(ID_AA64DFR1) +DEFINE_READ_ID_REG(ID_REG_5_2) +DEFINE_READ_ID_REG(ID_REG_5_3) +DEFINE_READ_ID_REG(ID_AA64AFR0) +DEFINE_READ_ID_REG(ID_AA64AFR1) +DEFINE_READ_ID_REG(ID_REG_5_6) +DEFINE_READ_ID_REG(ID_REG_5_7) + +/* CRm=6 */ +DEFINE_READ_ID_REG(ID_AA64ISAR0) +DEFINE_READ_ID_REG(ID_AA64ISAR1) +DEFINE_READ_ID_REG(ID_REG_6_2) +DEFINE_READ_ID_REG(ID_REG_6_3) +DEFINE_READ_ID_REG(ID_REG_6_4) +DEFINE_READ_ID_REG(ID_REG_6_5) +DEFINE_READ_ID_REG(ID_REG_6_6) +DEFINE_READ_ID_REG(ID_REG_6_7) + +/* CRm=7 */ +DEFINE_READ_ID_REG(ID_AA64MMFR0) +DEFINE_READ_ID_REG(ID_AA64MMFR1) +DEFINE_READ_ID_REG(ID_AA64MMFR2) +DEFINE_READ_ID_REG(ID_REG_7_3) +DEFINE_READ_ID_REG(ID_REG_7_4) +DEFINE_READ_ID_REG(ID_REG_7_5) +DEFINE_READ_ID_REG(ID_REG_7_6) +DEFINE_READ_ID_REG(ID_REG_7_7) + +#define ID_IDX(name) REG_IDX_## name + +enum id_reg_idx { + /* CRm=1 */ + ID_IDX(ID_PFR0) = 0, + ID_IDX(ID_PFR1), + ID_IDX(ID_DFR0), + ID_IDX(ID_AFR0), + ID_IDX(ID_MMFR0), + ID_IDX(ID_MMFR1), + ID_IDX(ID_MMFR2), + ID_IDX(ID_MMFR3), + + /* CRm=2 */ + ID_IDX(ID_ISAR0), + ID_IDX(ID_ISAR1), + ID_IDX(ID_ISAR2), + ID_IDX(ID_ISAR3), + ID_IDX(ID_ISAR4), + ID_IDX(ID_ISAR5), + ID_IDX(ID_MMFR4), + ID_IDX(ID_ISAR6), + + /* CRm=3 */ + ID_IDX(MVFR0), + ID_IDX(MVFR1), + ID_IDX(MVFR2), + ID_IDX(ID_REG_3_3), + ID_IDX(ID_PFR2), + ID_IDX(ID_DFR1), + ID_IDX(ID_MMFR5), + ID_IDX(ID_REG_3_7), + + /* CRm=4 */ + ID_IDX(ID_AA64PFR0), + ID_IDX(ID_AA64PFR1), + ID_IDX(ID_REG_4_2), + ID_IDX(ID_REG_4_3), + ID_IDX(ID_AA64ZFR0), + ID_IDX(ID_REG_4_5), + ID_IDX(ID_REG_4_6), + ID_IDX(ID_REG_4_7), + + /* CRm=5 */ + ID_IDX(ID_AA64DFR0), + ID_IDX(ID_AA64DFR1), + ID_IDX(ID_REG_5_2), + ID_IDX(ID_REG_5_3), + ID_IDX(ID_AA64AFR0), + ID_IDX(ID_AA64AFR1), + ID_IDX(ID_REG_5_6), + ID_IDX(ID_REG_5_7), + + /* CRm=6 */ + ID_IDX(ID_AA64ISAR0), + ID_IDX(ID_AA64ISAR1), + ID_IDX(ID_REG_6_2), + ID_IDX(ID_REG_6_3), + ID_IDX(ID_REG_6_4), + ID_IDX(ID_REG_6_5), + ID_IDX(ID_REG_6_6), + ID_IDX(ID_REG_6_7), + + /* CRm=7 */ + ID_IDX(ID_AA64MMFR0), + ID_IDX(ID_AA64MMFR1), + ID_IDX(ID_AA64MMFR2), + ID_IDX(ID_REG_7_3), + ID_IDX(ID_REG_7_4), + ID_IDX(ID_REG_7_5), + ID_IDX(ID_REG_7_6), + ID_IDX(ID_REG_7_7), +}; + +struct id_reg_test_info { + char *name; + uint32_t id; + bool can_clear; + uint64_t fixed_mask; + uint64_t org_val; + uint64_t user_val; + uint64_t (*read_reg)(void); +}; + +#define ID_REG_INFO(name) (&id_reg_list[ID_IDX(name)]) +static struct id_reg_test_info id_reg_list[] = { + /* CRm=1 */ + ID_REG_ENT(ID_PFR0), + ID_REG_ENT(ID_PFR1), + ID_REG_ENT(ID_DFR0), + ID_REG_ENT(ID_AFR0), + ID_REG_ENT(ID_MMFR0), + ID_REG_ENT(ID_MMFR1), + ID_REG_ENT(ID_MMFR2), + ID_REG_ENT(ID_MMFR3), + + /* CRm=2 */ + ID_REG_ENT(ID_ISAR0), + ID_REG_ENT(ID_ISAR1), + ID_REG_ENT(ID_ISAR2), + ID_REG_ENT(ID_ISAR3), + ID_REG_ENT(ID_ISAR4), + ID_REG_ENT(ID_ISAR5), + ID_REG_ENT(ID_MMFR4), + ID_REG_ENT(ID_ISAR6), + + /* CRm=3 */ + ID_REG_ENT(MVFR0), + ID_REG_ENT(MVFR1), + ID_REG_ENT(MVFR2), + ID_REG_ENT(ID_REG_3_3), + ID_REG_ENT(ID_PFR2), + ID_REG_ENT(ID_DFR1), + ID_REG_ENT(ID_MMFR5), + ID_REG_ENT(ID_REG_3_7), + + /* CRm=4 */ + ID_REG_ENT(ID_AA64PFR0), + ID_REG_ENT(ID_AA64PFR1), + ID_REG_ENT(ID_REG_4_2), + ID_REG_ENT(ID_REG_4_3), + ID_REG_ENT(ID_AA64ZFR0), + ID_REG_ENT(ID_REG_4_5), + ID_REG_ENT(ID_REG_4_6), + ID_REG_ENT(ID_REG_4_7), + + /* CRm=5 */ + ID_REG_ENT(ID_AA64DFR0), + ID_REG_ENT(ID_AA64DFR1), + ID_REG_ENT(ID_REG_5_2), + ID_REG_ENT(ID_REG_5_3), + ID_REG_ENT(ID_AA64AFR0), + ID_REG_ENT(ID_AA64AFR1), + ID_REG_ENT(ID_REG_5_6), + ID_REG_ENT(ID_REG_5_7), + + /* CRm=6 */ + ID_REG_ENT(ID_AA64ISAR0), + ID_REG_ENT(ID_AA64ISAR1), + ID_REG_ENT(ID_REG_6_2), + ID_REG_ENT(ID_REG_6_3), + ID_REG_ENT(ID_REG_6_4), + ID_REG_ENT(ID_REG_6_5), + ID_REG_ENT(ID_REG_6_6), + ID_REG_ENT(ID_REG_6_7), + + /* CRm=7 */ + ID_REG_ENT(ID_AA64MMFR0), + ID_REG_ENT(ID_AA64MMFR1), + ID_REG_ENT(ID_AA64MMFR2), + ID_REG_ENT(ID_REG_7_3), + ID_REG_ENT(ID_REG_7_4), + ID_REG_ENT(ID_REG_7_5), + ID_REG_ENT(ID_REG_7_6), + ID_REG_ENT(ID_REG_7_7), +}; + +/* Utilities to get a feature field from ID register value */ +static inline int +cpuid_signed_field_width(uint64_t id_val, int field, int width) +{ + return (s64)(id_val << (64 - width - field)) >> (64 - width); +} + +static unsigned int +cpuid_unsigned_field_width(uint64_t id_val, int field, int width) +{ + return (uint64_t)(id_val << (64 - width - field)) >> (64 - width); +} + +static inline int __attribute_const__ +cpuid_extract_field_width(uint64_t id_val, int field, int width, bool sign) +{ + return (sign) ? cpuid_signed_field_width(id_val, field, width) : + cpuid_unsigned_field_width(id_val, field, width); +} + +#define GET_ID_FIELD(regval, shift, is_signed) \ + cpuid_extract_field_width(regval, shift, 4, is_signed) + +#define GET_ID_UFIELD(regval, shift) \ + cpuid_unsigned_field_width(regval, shift, 4) + +#define UPDATE_ID_UFIELD(regval, shift, fval) \ + (((regval) & ~(0xfULL << (shift))) | \ + (((uint64_t)((fval) & 0xf)) << (shift))) + +void test_pmu_init(struct kvm_vm *vm, uint32_t vcpu) +{ + struct kvm_device_attr attr = { + .group = KVM_ARM_VCPU_PMU_V3_CTRL, + .attr = KVM_ARM_VCPU_PMU_V3_INIT, + }; + vcpu_ioctl(vm, vcpu, KVM_SET_DEVICE_ATTR, &attr); +} + +void test_sve_init(struct kvm_vm *vm, uint32_t vcpu) +{ + int feature = KVM_ARM_VCPU_SVE; + + vcpu_ioctl(vm, vcpu, KVM_ARM_VCPU_FINALIZE, &feature); +} + +#define MAX_CAPS 2 +struct feature_test_info { + char *name; /* Feature Name (Debug information) */ + struct id_reg_test_info *sreg; /* ID register for the feature */ + int shift; /* Field of the ID register for the feature */ + int min; /* Min value to indicate the feature */ + bool is_sign; /* Is the field signed or unsigned ? */ + int ncaps; /* Number of valid Capabilities in caps[] */ + long caps[MAX_CAPS]; /* Capabilities to indicate this feature */ + /* struct kvm_enable_cap to use the capability if needed */ + struct kvm_enable_cap *opt_in_cap; + bool run_test; /* Does guest run test for this feature ? */ + /* Initialization function for the feature as needed */ + void (*init_feature)(struct kvm_vm *vm, uint32_t vcpuid); + /* struct kvm_vcpu_init to opt-in the feature if needed */ + struct kvm_vcpu_init *vcpu_init; +}; + +/* Test for optin CPU features */ +static struct feature_test_info feature_test_info_table[] = { + { + .name = "SVE", + .sreg = ID_REG_INFO(ID_AA64PFR0), + .shift = ID_AA64PFR0_SVE_SHIFT, + .min = 1, + .caps = {KVM_CAP_ARM_SVE}, + .ncaps = 1, + .init_feature = test_sve_init, + .vcpu_init = &(struct kvm_vcpu_init) { + .features = {1ULL << KVM_ARM_VCPU_SVE}, + }, + }, + { + .name = "MTE", + .sreg = ID_REG_INFO(ID_AA64PFR1), + .shift = ID_AA64PFR1_MTE_SHIFT, + .min = 2, + .caps = {KVM_CAP_ARM_MTE}, + .ncaps = 1, + .opt_in_cap = &(struct kvm_enable_cap) { + .cap = KVM_CAP_ARM_MTE, + }, + }, + { + .name = "PMUV3", + .sreg = ID_REG_INFO(ID_AA64DFR0), + .shift = ID_AA64DFR0_PMUVER_SHIFT, + .min = 1, + .init_feature = test_pmu_init, + .caps = {KVM_CAP_ARM_PMU_V3}, + .ncaps = 1, + .vcpu_init = &(struct kvm_vcpu_init) { + .features = {1ULL << KVM_ARM_VCPU_PMU_V3}, + }, + }, + { + .name = "PERFMON", + .sreg = ID_REG_INFO(ID_DFR0), + .shift = ID_DFR0_PERFMON_SHIFT, + .min = 3, + .init_feature = test_pmu_init, + .caps = {KVM_CAP_ARM_PMU_V3}, + .ncaps = 1, + .vcpu_init = &(struct kvm_vcpu_init) { + .features = {1ULL << KVM_ARM_VCPU_PMU_V3}, + }, + }, +}; + +static int walk_id_reg_list(int (*fn)(struct id_reg_test_info *sreg, void *arg), + void *arg) +{ + int ret = 0, i; + + for (i = 0; i < ARRAY_SIZE(id_reg_list); i++) { + ret = fn(&id_reg_list[i], arg); + if (ret) + break; + } + return ret; +} + +static int guest_code_id_reg_check_one(struct id_reg_test_info *sreg, void *arg) +{ + uint64_t val = sreg->read_reg(); + + GUEST_ASSERT_2(val == sreg->user_val, sreg->name, sreg->user_val); + return 0; +} + +static void guest_code_id_reg_check_all(uint32_t cpu) +{ + walk_id_reg_list(guest_code_id_reg_check_one, NULL); + GUEST_DONE(); +} + +static void guest_code_do_nothing(uint32_t cpu) +{ + GUEST_DONE(); +} + +static void guest_code_feature_check(uint32_t cpu) +{ + int i; + struct feature_test_info *finfo; + + for (i = 0; i < ARRAY_SIZE(feature_test_info_table); i++) { + finfo = &feature_test_info_table[i]; + if (finfo->run_test) + guest_code_id_reg_check_one(finfo->sreg, NULL); + } + + GUEST_DONE(); +} + +static void guest_code_ptrauth_check(uint32_t cpuid) +{ + struct id_reg_test_info *sreg = ID_REG_INFO(ID_AA64ISAR1); + uint64_t val = sreg->read_reg(); + + GUEST_ASSERT_2(val == sreg->user_val, "PTRAUTH", val); + GUEST_DONE(); +} + +static int reset_id_reg_info_one(struct id_reg_test_info *sreg, void *arg) +{ + sreg->user_val = sreg->org_val; + return 0; +} + +static void reset_id_reg_info(void) +{ + walk_id_reg_list(reset_id_reg_info_one, NULL); +} + +static struct kvm_vm *test_vm_create_cap(uint32_t nvcpus, + void (*guest_code)(uint32_t), struct kvm_vcpu_init *init, + struct kvm_enable_cap *cap) +{ + struct kvm_vm *vm; + uint32_t cpuid; + uint64_t mem_pages; + + mem_pages = DEFAULT_GUEST_PHY_PAGES + DEFAULT_STACK_PGS * nvcpus; + mem_pages += mem_pages / (PTES_PER_MIN_PAGE * 2); + mem_pages = vm_adjust_num_guest_pages(VM_MODE_DEFAULT, mem_pages); + + vm = vm_create(VM_MODE_DEFAULT, + DEFAULT_GUEST_PHY_PAGES + (DEFAULT_STACK_PGS * nvcpus), + O_RDWR); + if (cap) + vm_enable_cap(vm, cap); + + kvm_vm_elf_load(vm, program_invocation_name); + + if (init && init->target == -1) { + struct kvm_vcpu_init preferred; + + vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred); + init->target = preferred.target; + } + + vm_init_descriptor_tables(vm); + for (cpuid = 0; cpuid < nvcpus; cpuid++) { + if (init) + aarch64_vcpu_add_default(vm, cpuid, init, guest_code); + else + vm_vcpu_add_default(vm, cpuid, guest_code); + + vcpu_init_descriptor_tables(vm, cpuid); + } + + ucall_init(vm, NULL); + return vm; +} + +static struct kvm_vm *test_vm_create(uint32_t nvcpus, + void (*guest_code)(uint32_t), + struct kvm_vcpu_init *init) +{ + return test_vm_create_cap(nvcpus, guest_code, init, NULL); +} + +static void test_vm_free(struct kvm_vm *vm) +{ + ucall_uninit(vm); + kvm_vm_free(vm); +} + +#define TEST_RUN(vm, cpu) \ + (test_vcpu_run(__func__, __LINE__, vm, cpu, true)) + +#define TEST_RUN_NO_SYNC_DATA(vm, cpu) \ + (test_vcpu_run(__func__, __LINE__, vm, cpu, false)) + +static int test_vcpu_run(const char *test_name, int line, + struct kvm_vm *vm, uint32_t vcpuid, bool sync_data) +{ + struct ucall uc; + int ret; + + if (sync_data) { + sync_global_to_guest(vm, id_reg_list); + sync_global_to_guest(vm, feature_test_info_table); + } + + vcpu_args_set(vm, vcpuid, 1, vcpuid); + + ret = _vcpu_run(vm, vcpuid); + if (ret) { + ret = errno; + goto sync_exit; + } + + switch (get_ucall(vm, vcpuid, &uc)) { + case UCALL_SYNC: + case UCALL_DONE: + ret = 0; + break; + case UCALL_ABORT: + TEST_FAIL( + "%s (%s) at line %d (user %s at line %d), args[3]=0x%lx", + (char *)uc.args[0], (char *)uc.args[2], (int)uc.args[1], + test_name, line, uc.args[3]); + break; + default: + TEST_FAIL("Unexpected guest exit\n"); + } + +sync_exit: + if (sync_data) { + sync_global_from_guest(vm, id_reg_list); + sync_global_from_guest(vm, feature_test_info_table); + } + return ret; +} + +static int set_id_regs_after_run_test_one(struct id_reg_test_info *sreg, + void *arg) +{ + struct kvm_vm *vm = arg; + struct kvm_one_reg one_reg; + uint32_t vcpuid = 0; + uint64_t reg_val; + int ret; + + one_reg.addr = (uint64_t)®_val; + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + + vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &one_reg); + if ((reg_val != 0) && (sreg->can_clear)) { + reg_val = 0; + ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &one_reg); + TEST_ASSERT(ret && errno == EINVAL, + "Changing ID reg value should fail\n"); + } + + vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &one_reg); + ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &one_reg); + TEST_ASSERT(ret == 0, "Setting the same ID reg value should work\n"); + + return 0; +} + +static int set_id_regs_test_one(struct id_reg_test_info *sreg, void *arg) +{ + struct kvm_vm *vm = arg; + struct kvm_one_reg one_reg; + uint32_t vcpuid = 0; + uint64_t reg_val; + + one_reg.addr = (uint64_t)®_val; + reset_id_reg_info(); + + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + if (sreg->can_clear) { + /* Change the register to 0 when possible */ + reg_val = 0; + vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &one_reg); + vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &one_reg); + TEST_ASSERT(reg_val == 0, + "GET(%s) didn't return 0 but 0x%lx", sreg->name, reg_val); + } + + /* Check if we can restore the initial value */ + reg_val = sreg->org_val; + vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &one_reg); + vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &one_reg); + TEST_ASSERT(reg_val == sreg->org_val, + "GET(%s) didn't return 0x%lx but 0x%lx", + sreg->name, sreg->org_val, reg_val); + sreg->user_val = sreg->org_val; + return 0; +} + +static void set_id_regs_test(void) +{ + struct kvm_vm *vm; + int ret; + + reset_id_reg_info(); + vm = test_vm_create(1, guest_code_id_reg_check_all, NULL); + + ret = walk_id_reg_list(set_id_regs_test_one, vm); + assert(!ret); + + ret = TEST_RUN(vm, 0); + TEST_ASSERT(!ret, "%s TEST_RUN failed, ret=0x%x", __func__, ret); + + ret = walk_id_reg_list(set_id_regs_after_run_test_one, vm); + assert(!ret); +} + +static int clear_id_reg_when_possible(struct id_reg_test_info *sreg, void *arg) +{ + uint64_t reg_val = 0; + struct kvm_one_reg one_reg; + struct kvm_vm *vm = (struct kvm_vm *)((uint64_t *)arg)[0]; + uint32_t vcpu = ((uint64_t *)arg)[1]; + + if (sreg->can_clear) { + assert(sreg->org_val); + one_reg.addr = (uint64_t)®_val; + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + vcpu_ioctl(vm, vcpu, KVM_SET_ONE_REG, &one_reg); + sreg->user_val = 0; + } + return sreg->can_clear; +} + +static void clear_any_id_reg(struct kvm_vm *vm, uint32_t vcpuid) +{ + int ret; + uint64_t args[2] = {(uint64_t)vm, vcpuid}; + + ret = walk_id_reg_list(clear_id_reg_when_possible, args); + + /* Return non-zero means one of non-zero registers was cleared */ + assert(ret); + sync_global_to_guest(vm, id_reg_list); +} + +static bool caps_are_supported(long *caps, int ncaps) +{ + int i; + + for (i = 0; i < ncaps; i++) { + if (kvm_check_cap(caps[i]) <= 0) + return false; + } + return true; +} + +static void test_feature_ptrauth(void) +{ + struct kvm_one_reg one_reg; + struct kvm_vcpu_init init; + struct kvm_vm *vm = NULL; + struct id_reg_test_info *sreg = ID_REG_INFO(ID_AA64ISAR1); + uint32_t vcpu = 0; + int64_t rval; + int ret; + int apa, api, gpa, gpi; + char *name = "PTRAUTH"; + long caps[2] = {KVM_CAP_ARM_PTRAUTH_ADDRESS, + KVM_CAP_ARM_PTRAUTH_GENERIC}; + + reset_id_reg_info(); + one_reg.addr = (uint64_t)&rval; + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + + if (caps_are_supported(caps, 2)) { + + /* Test with feature enabled */ + memset(&init, 0, sizeof(init)); + init.target = -1; + init.features[0] = (1ULL << KVM_ARM_VCPU_PTRAUTH_ADDRESS | + 1ULL << KVM_ARM_VCPU_PTRAUTH_GENERIC); + vm = test_vm_create_cap(1, guest_code_ptrauth_check, &init, + NULL); + vcpu_ioctl(vm, vcpu, KVM_GET_ONE_REG, &one_reg); + apa = GET_ID_UFIELD(rval, ID_AA64ISAR1_APA_SHIFT); + api = GET_ID_UFIELD(rval, ID_AA64ISAR1_API_SHIFT); + gpa = GET_ID_UFIELD(rval, ID_AA64ISAR1_GPA_SHIFT); + gpi = GET_ID_UFIELD(rval, ID_AA64ISAR1_GPI_SHIFT); + + TEST_ASSERT((apa > 0) || (api > 0), + "Either apa(0x%x) or api(0x%x) must be available", + apa, gpa); + TEST_ASSERT((gpa > 0) || (gpi > 0), + "Either gpa(0x%x) or gpi(0x%x) must be available", + gpa, gpi); + + TEST_ASSERT((apa > 0) ^ (api > 0), + "Both apa(0x%x) and api(0x%x) must not be available", + apa, api); + TEST_ASSERT((gpa > 0) ^ (gpi > 0), + "Both gpa(0x%x) and gpi(0x%x) must not be available", + gpa, gpi); + + sreg->user_val = rval; + + pr_debug("%s: Test with %s enabled (%s: 0x%lx)\n", + __func__, name, sreg->name, sreg->user_val); + ret = TEST_RUN(vm, vcpu); + TEST_ASSERT(!ret, "%s:KVM_RUN failed with %s enabled", + __func__, name); + test_vm_free(vm); + } + + /* Test with feature disabled */ + reset_id_reg_info(); + + vm = test_vm_create(1, guest_code_feature_check, NULL); + vcpu_ioctl(vm, vcpu, KVM_GET_ONE_REG, &one_reg); + + apa = GET_ID_UFIELD(rval, ID_AA64ISAR1_APA_SHIFT); + api = GET_ID_UFIELD(rval, ID_AA64ISAR1_API_SHIFT); + gpa = GET_ID_UFIELD(rval, ID_AA64ISAR1_GPA_SHIFT); + gpi = GET_ID_UFIELD(rval, ID_AA64ISAR1_GPI_SHIFT); + TEST_ASSERT(!apa && !api && !gpa && !gpi, + "apa(0x%x), api(0x%x), gpa(0x%x), gpi(0x%x) must be zero", + apa, api, gpa, gpi); + + pr_debug("%s: Test with %s disabled (%s: 0x%lx)\n", + __func__, name, sreg->name, sreg->user_val); + + ret = TEST_RUN(vm, vcpu); + TEST_ASSERT(!ret, "%s TEST_RUN failed with %s enabled, ret=0x%x", + __func__, name, ret); + + test_vm_free(vm); +} + +static void test_feature(struct feature_test_info *finfo) +{ + struct id_reg_test_info *sreg = finfo->sreg; + struct kvm_one_reg one_reg; + struct kvm_vcpu_init init, *initp = NULL; + struct kvm_vm *vm = NULL; + int64_t fval, reg_val; + uint32_t vcpu = 0; + bool is_sign = finfo->is_sign; + int min = finfo->min; + int shift = finfo->shift; + int ret; + + pr_debug("%s: %s (reg %s)\n", __func__, finfo->name, sreg->name); + + reset_id_reg_info(); + finfo->run_test = 1; /* Indicate that guest runs the test on it */ + one_reg.addr = (uint64_t)®_val; + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + + /* Test with feature enabled */ + + /* Need KVM_ARM_VCPU_INIT or opt-in capability ? */ + if (finfo->vcpu_init || finfo->opt_in_cap) { + if ((finfo->ncaps == 0) || + (caps_are_supported(finfo->caps, finfo->ncaps))) { + if (finfo->vcpu_init) { + /* + * Need to enable the feature via + * KVM_ARM_VCPU_INIT. + */ + memset(&init, 0, sizeof(init)); + init = *finfo->vcpu_init; + init.target = -1; + initp = &init; + } + + vm = test_vm_create_cap(1, guest_code_feature_check, + initp, finfo->opt_in_cap); + vcpu_ioctl(vm, vcpu, KVM_GET_ONE_REG, &one_reg); + fval = GET_ID_FIELD(reg_val, shift, is_sign); + TEST_ASSERT(fval >= min, + "%s field of %s is too small (%ld)", + finfo->name, sreg->name, fval); + sreg->user_val = reg_val; + } + } else { + /* Check if the feature is available */ + if (GET_ID_FIELD(sreg->org_val, shift, is_sign) >= min) + vm = test_vm_create(1, guest_code_feature_check, NULL); + } + + if (vm) { + if (finfo->init_feature) + /* Run any required extra process to use the feature */ + finfo->init_feature(vm, vcpu); + + pr_debug("%s: Test with %s enabled (%s: 0x%lx)\n", + __func__, finfo->name, sreg->name, sreg->user_val); + + ret = TEST_RUN(vm, vcpu); + TEST_ASSERT(!ret, "%s:TEST_RUN failed with %s enabled", + __func__, finfo->name); + test_vm_free(vm); + } + + /* Test with feature disabled */ + reset_id_reg_info(); + + vm = test_vm_create(1, guest_code_feature_check, NULL); + vcpu_ioctl(vm, vcpu, KVM_GET_ONE_REG, &one_reg); + fval = GET_ID_FIELD(reg_val, shift, is_sign); + if (finfo->vcpu_init || finfo->opt_in_cap) { + /* + * If the feature needs to be enabled with KVM_ARM_VCPU_INIT + * or opt-in capabilities, the default value of the ID register + * shouldn't indicate the feature. + */ + TEST_ASSERT(fval < min, "%s field of %s is too big (%ld)", + finfo->name, sreg->name, fval); + } else { + /* Update the relevant field to hide the feature. */ + fval = is_sign ? 0xf : 0x0; + reg_val = UPDATE_ID_UFIELD(reg_val, shift, fval); + ret = _vcpu_ioctl(vm, vcpu, KVM_SET_ONE_REG, &one_reg); + TEST_ASSERT(ret == 0, "Disabling %s failed %d\n", + finfo->name, ret); + sreg->user_val = reg_val; + } + + pr_debug("%s: Test with %s disabled (%s: 0x%lx)\n", + __func__, finfo->name, sreg->name, sreg->user_val); + + ret = TEST_RUN(vm, vcpu); + finfo->run_test = 0; + test_vm_free(vm); +} + +static void test_feature_all(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(feature_test_info_table); i++) + test_feature(&feature_test_info_table[i]); +} + +int test_set_reg(struct id_reg_test_info *sreg, uint64_t new_val, + bool guest_run) +{ + struct kvm_vm *vm; + int ret; + uint32_t vcpu = 0; + uint64_t reg_val; + struct kvm_one_reg one_reg; + + reset_id_reg_info(); + + vm = test_vm_create(1, guest_code_id_reg_check_all, NULL); + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + one_reg.addr = (uint64_t)®_val; + + reg_val = new_val; + ret = _vcpu_ioctl(vm, vcpu, KVM_SET_ONE_REG, &one_reg); + if (!guest_run) + return ret; + + TEST_ASSERT(!ret, "SET_REG(%s=0x%lx) failed, ret=0x%x", + sreg->name, new_val, ret); + sreg->user_val = new_val; + ret = TEST_RUN(vm, vcpu); + test_vm_free(vm); + return ret; +} + +int test_feature_frac_vm(struct id_reg_test_info *sreg, uint64_t new_val, + struct id_reg_test_info *frac_sreg, uint64_t frac_new_val) +{ + struct kvm_vm *vm; + int ret; + uint32_t vcpu = 0; + uint64_t reg_val; + struct kvm_one_reg one_reg; + + reset_id_reg_info(); + + vm = test_vm_create(1, guest_code_id_reg_check_all, NULL); + + /* Set feature reg field */ + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + one_reg.addr = (uint64_t)®_val; + reg_val = new_val; + ret = _vcpu_ioctl(vm, vcpu, KVM_SET_ONE_REG, &one_reg); + TEST_ASSERT(!ret, "SET_REG(%s=0x%lx) failed, ret=0x%x", + sreg->name, new_val, ret); + sreg->user_val = new_val; + + /* Set fractional reg field */ + one_reg.id = KVM_ARM64_SYS_REG(frac_sreg->id); + one_reg.addr = (uint64_t)®_val; + reg_val = frac_new_val; + vcpu_ioctl(vm, vcpu, KVM_SET_ONE_REG, &one_reg); + TEST_ASSERT(!ret, "SET_REG(%s=0x%lx) failed, ret=0x%x", + frac_sreg->name, frac_new_val, ret); + + frac_sreg->user_val = frac_new_val; + ret = TEST_RUN(vm, vcpu); + test_vm_free(vm); + return ret; +} + +struct frac_info { + char *name; + struct id_reg_test_info *sreg; + struct id_reg_test_info *frac_sreg; + int shift; + int frac_shift; +}; + +struct frac_info frac_info_table[] = { + { + .name = "RAS", + .sreg = ID_REG_INFO(ID_AA64PFR0), + .shift = ID_AA64PFR0_RAS_SHIFT, + .frac_sreg = ID_REG_INFO(ID_AA64PFR1), + .frac_shift = ID_AA64PFR1_RASFRAC_SHIFT, + }, + { + .name = "MPAM", + .sreg = ID_REG_INFO(ID_AA64PFR0), + .shift = ID_AA64PFR0_MPAM_SHIFT, + .frac_sreg = ID_REG_INFO(ID_AA64PFR1), + .frac_shift = ID_AA64PFR1_MPAMFRAC_SHIFT, + }, + { + .name = "CSV2", + .sreg = ID_REG_INFO(ID_AA64PFR0), + .shift = ID_AA64PFR0_CSV2_SHIFT, + .frac_sreg = ID_REG_INFO(ID_AA64PFR1), + .frac_shift = ID_AA64PFR1_CSV2FRAC_SHIFT, + }, +}; + +void test_feature_frac_one(struct frac_info *frac) +{ + uint64_t reg_val, org_fval, frac_reg_val, frac_org_fval; + int ret, shift, frac_shift; + struct id_reg_test_info *sreg, *frac_sreg; + + reset_id_reg_info(); + + sreg = frac->sreg; + shift = frac->shift; + frac_sreg = frac->frac_sreg; + frac_shift = frac->frac_shift; + + pr_debug("%s(%s Frac) reg:%s(shift:%d) frac reg:%s(shift:%d)\n", + __func__, frac->name, sreg->name, shift, + frac_sreg->name, frac_shift); + + frac_org_fval = GET_ID_UFIELD(frac_sreg->org_val, frac_shift); + if (frac_org_fval > 0) { + /* Test with smaller frac value */ + frac_reg_val = UPDATE_ID_UFIELD(frac_sreg->org_val, + frac_shift, frac_org_fval - 1); + ret = test_set_reg(frac_sreg, frac_reg_val, false); + TEST_ASSERT(!ret, "SET smaller %s frac (val:%lx) failed(%d)", + frac->name, frac_reg_val, ret); + + ret = test_feature_frac_vm(sreg, sreg->org_val, + frac_sreg, frac_reg_val); + TEST_ASSERT(!ret, "Test smaller %s frac (val:%lx) failed(%d)", + frac->name, frac_reg_val, ret); + } + + reset_id_reg_info(); + + if (frac_org_fval != 0xf) { + /* Test with larger frac value */ + frac_reg_val = UPDATE_ID_UFIELD(frac_sreg->org_val, frac_shift, + frac_org_fval + 1); + + /* Setting larger frac shouldn't fail (at ioctl) */ + ret = test_set_reg(frac_sreg, frac_reg_val, false); + TEST_ASSERT(!ret, + "SET larger %s frac (%s org:%lx, val:%lx) failed(%d)", + frac->name, frac_sreg->name, frac_sreg->org_val, + frac_reg_val, ret); + + /* KVM_RUN with larger frac should fail */ + ret = test_feature_frac_vm(sreg, sreg->org_val, + frac_sreg, frac_reg_val); + TEST_ASSERT(ret, + "Test with larger %s frac (%s org:%lx, val:%lx) worked", + frac->name, frac_sreg->name, frac_sreg->org_val, + frac_reg_val); + } + + reset_id_reg_info(); + + org_fval = GET_ID_UFIELD(sreg->org_val, shift); + if (org_fval == 0) { + /* Setting larger val for the feature should fail */ + reg_val = UPDATE_ID_UFIELD(sreg->org_val, shift, org_fval + 1); + ret = test_set_reg(sreg, reg_val, false); + TEST_ASSERT(ret, "SET larger %s (val:%lx) worked", + frac->name, reg_val); + return; + } + + /* Test with smaller feature value */ + reg_val = UPDATE_ID_UFIELD(sreg->org_val, shift, org_fval - 1); + ret = test_set_reg(sreg, reg_val, false); + TEST_ASSERT(!ret, "SET smaller %s (val:%lx) failed(%d)", + frac->name, reg_val, ret); + + ret = test_feature_frac_vm(sreg, reg_val, frac_sreg, frac_sreg->org_val); + TEST_ASSERT(!ret, "Test with smaller %s (val:%lx) failed(%d)", + frac->name, reg_val, ret); + + if (frac_org_fval > 0) { + /* Test with smaller feature and frac value */ + frac_reg_val = UPDATE_ID_UFIELD(frac_sreg->org_val, + frac_shift, frac_org_fval - 1); + ret = test_feature_frac_vm(sreg, reg_val, frac_sreg, + frac_reg_val); + TEST_ASSERT(!ret, + "Test with smaller %s and frac (val:%lx) failed(%d)", + frac->name, reg_val, ret); + } + + if (frac_org_fval != 0xf) { + /* Test with smaller feature and larger frac value */ + frac_reg_val = UPDATE_ID_UFIELD(frac_sreg->org_val, + frac_shift, frac_org_fval + 1); + ret = test_feature_frac_vm(sreg, reg_val, frac_sreg, + frac_reg_val); + TEST_ASSERT(!ret, + "Test with smaller %s and larger frac (val:%lx) failed(%d)", + frac->name, reg_val, ret); + } +} + +void test_feature_frac_all(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(frac_info_table); i++) + test_feature_frac_one(&frac_info_table[i]); +} + +/* Structure for test_consistent_vcpus/test_inconsistent_vcpus */ +struct thread_args { + pthread_t thread; + struct kvm_vm *vm; + uint32_t vcpuid; + void *data; +}; + +/* Structures for test_inconsistent_vcpus */ +struct run_inconsistent_test { + bool modify_id_reg; + volatile bool complete; +}; + +struct inconsistent_test_info { + uint32_t nvcpus; + struct run_inconsistent_test *vcpu_run; +}; + +static void *inconsistent_test_thread(void *arg) +{ + struct thread_args *targs = arg; + struct kvm_vm *vm = targs->vm; + uint32_t vcpuid = targs->vcpuid; + struct inconsistent_test_info *info = targs->data; + int64_t ret; + int i; + struct timespec ts = { + .tv_sec = 0, + .tv_nsec = 1000000, + }; + + if (info->vcpu_run[vcpuid].modify_id_reg) { + /* Make inconsistency in ID regs between vCPUs */ + clear_any_id_reg(vm, vcpuid); + + /* Wait for all other vCPUs to exit from KVM_RUN */ + for (i = 0; i < info->nvcpus; i++) { + if (i == vcpuid) + continue; + + while (!info->vcpu_run[i].complete) + nanosleep(&ts, NULL); + } + } + + ret = TEST_RUN_NO_SYNC_DATA(vm, vcpuid); + if (info->vcpu_run[vcpuid].modify_id_reg) { + TEST_ASSERT(ret == EPERM, + "%s: KVM_RUN retturned unexpected result (ret=%ld)", + __func__, ret); + } else { + TEST_ASSERT(ret == 0, "%s: KVM_RUN failed (ret=%ld)", + __func__, ret); + info->vcpu_run[vcpuid].complete = true; + } + + return (void *)ret; +} + +static int start_test_thread(struct kvm_vm *vm, uint32_t nvcpus, + void *(*test_func)(void *arg), void *data) +{ + int i, ret, test_ret; + uint64_t thread_ret; + pthread_t *threads; + struct thread_args *args; + + threads = calloc(nvcpus, sizeof(pthread_t)); + TEST_ASSERT(threads, "Failed to allocate threads."); + + args = calloc(nvcpus, sizeof(struct thread_args)); + TEST_ASSERT(args, "Failed to allocate args."); + + for (i = 0; i < nvcpus; i++) { + args[i].vm = vm; + args[i].vcpuid = i; + args[i].data = data; + ret = pthread_create(&threads[i], NULL, test_func, &args[i]); + TEST_ASSERT(!ret, "pthread_create failed: %d\n", ret); + } + + test_ret = 0; + for (i = 0; i < nvcpus; i++) { + thread_ret = 0; + ret = pthread_join(threads[i], (void **)&thread_ret); + TEST_ASSERT(!ret, "pthread_join failed: %d\n", ret); + if (thread_ret != 0) + test_ret = (int32_t)thread_ret; + } + free(args); + free(threads); + return test_ret; +} + +/* + * Create multiple vCPUs and we will set ID registers to different values + * from others to make sure that KVM_RUN will fail when it detects inconsistent + * ID registers across vCPUs. + */ +void test_inconsistent_vcpus(uint32_t nvcpus) +{ + struct kvm_vm *vm; + int ret; + struct inconsistent_test_info info; + + assert(nvcpus > 1); + + reset_id_reg_info(); + info.nvcpus = nvcpus; + info.vcpu_run = calloc(nvcpus, sizeof(struct run_inconsistent_test)); + assert(info.vcpu_run); + + vm = test_vm_create(nvcpus, guest_code_do_nothing, NULL); + + sync_global_to_guest(vm, id_reg_list); + + /* Let vCPU0 modify its ID register */ + info.vcpu_run[0].modify_id_reg = 1; + ret = start_test_thread(vm, nvcpus, inconsistent_test_thread, &info); + TEST_ASSERT(ret == EPERM, "inconsistent_test_thread failed\n"); + test_vm_free(vm); + free(info.vcpu_run); +} + +static void *test_vcpu_thread(void *arg) +{ + struct thread_args *targs = arg; + int64_t ret; + + ret = TEST_RUN_NO_SYNC_DATA(targs->vm, targs->vcpuid); + return (void *)ret; +} + +void test_consistent_vcpus(uint32_t nvcpus) +{ + struct kvm_vm *vm; + int ret; + + assert(nvcpus > 1); + reset_id_reg_info(); + + vm = test_vm_create(nvcpus, guest_code_do_nothing, NULL); + sync_global_to_guest(vm, id_reg_list); + + ret = start_test_thread(vm, nvcpus, test_vcpu_thread, NULL); + TEST_ASSERT(!ret, "test_vcpu_thread failed\n"); + test_vm_free(vm); +} + +void run_test(void) +{ + uint32_t nvcpus = 3; + + set_id_regs_test(); + test_feature_all(); + test_feature_ptrauth(); + test_feature_frac_all(); + test_consistent_vcpus(nvcpus); + test_inconsistent_vcpus(nvcpus); +} + +static int init_id_reg_info_one(struct id_reg_test_info *sreg, void *arg) +{ + uint64_t reg_val; + uint32_t vcpuid = 0; + int ret; + struct kvm_one_reg one_reg; + struct kvm_vm *vm = arg; + + one_reg.addr = (uint64_t)®_val; + one_reg.id = KVM_ARM64_SYS_REG(sreg->id); + vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, &one_reg); + sreg->org_val = reg_val; + sreg->user_val = reg_val; + if (sreg->org_val) { + reg_val = 0; + ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, &one_reg); + if (!ret) + sreg->can_clear = true; + } + + pr_debug("%s (0x%x): 0x%lx, %s\n", sreg->name, sreg->id, + sreg->org_val, sreg->can_clear ? "can clear" : ""); + + return 0; +} + +static void init_id_reg_info(void) +{ + struct kvm_vm *vm; + + vm = test_vm_create(1, guest_code_do_nothing, NULL); + walk_id_reg_list(init_id_reg_info_one, vm); + test_vm_free(vm); +} + +int main(void) +{ + + setbuf(stdout, NULL); + + if (kvm_check_cap(KVM_CAP_ARM_ID_REG_WRITABLE) <= 0) { + print_skip("KVM_CAP_ARM_ID_REG_WRITABLE is not supported\n"); + exit(KSFT_SKIP); + } + + init_id_reg_info(); + run_test(); + return 0; +}