From patchwork Wed Nov 3 06:24:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600161 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 AAFEEC433F5 for ; Wed, 3 Nov 2021 06:27:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8A84A60EBD for ; Wed, 3 Nov 2021 06:27:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231557AbhKCG3y (ORCPT ); Wed, 3 Nov 2021 02:29:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230152AbhKCG3x (ORCPT ); Wed, 3 Nov 2021 02:29:53 -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 D8AE5C061714 for ; Tue, 2 Nov 2021 23:27:17 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id t62-20020a625f41000000b004807e0ed462so806677pfb.22 for ; Tue, 02 Nov 2021 23:27:17 -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=eVXFsIu2A0jcHNwkwUYO+pTUIoPZ1YXwb8zzymW3agQ=; b=XD1dMhNRonxvZZ9i2UCcZCoIvIEj9v7vxdtIWeG0WTFpcrY4lN/dj+JeBCeRGtUs+b TKOC+JBs+wHF9sqEOE+NK+uX7MR7JGXuZ/97c2qmTC9prsj9gzFwFDUkQBwwEwaW3KMx /CPyyLPCvdbnsY8rtKtXzgvMrI6FOl0KEcIi7a+KusBwBBGfCdZrwuakzoKxbGaE1Hpe kEWU+ZfLgmoWcFVw+9lQjr5zGO6EGaJfXCH2ifB88gJk2oENMhuChuVILNxWj087Pa6l 3gO5JSvtCAnNz2AFkvgeb9oDEv+Cg2swChDGNWLQMmmXx65F2wRetqzAntKGaBGB/5bM /G1A== 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=eVXFsIu2A0jcHNwkwUYO+pTUIoPZ1YXwb8zzymW3agQ=; b=16I9RClf9QaE2pLDJ7DNeCDWTIu2pkWNkatvTWv36IB35uu5OZd6RSQDsoZzcWUMnS IyL2/kD6tBAue1Fl9BeGt9DlpTaIUV1P0hFHSfWJIaV2RY4wF0BQhE3X0FfgUNk1mETD q8EG2k/9JGHGDwxQl3d+6QVjJI6mJSUF2dkQsz5F9h84cZrow4qxKciZUUKnbk6fcVL3 XfRmgaJrh5jpQlY6ATUSmn4sysiHu9TQvZuD4+fMR0xzooSaheSx8zLVYwTupMYpz2wf L6O+16gKopF78ZRJle3xmj5W1vSgdPFpss405X2RI5VwGJfAWfQK2teb0THuBuFQ8s9W UB5Q== X-Gm-Message-State: AOAM531kBQXb3+lkJ/olpQRq8FLbCj+jbA3iVVMspExoKZmlXIBT1YKc /QiExC+nDLCvlS9uMUVg4ZE74VR5iQU= X-Google-Smtp-Source: ABdhPJwf4BoucPOZITph2SZD/P4CzLQM8u6ddsbijqFxfHoaATosOtV5geGGgyUp899HzSt2uQ0f+XQH+PU= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:dacb:b0:141:e931:3aff with SMTP id q11-20020a170902dacb00b00141e9313affmr17384890plx.50.1635920837395; Tue, 02 Nov 2021 23:27:17 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:53 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-2-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 01/28] 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 Reviewed-by: Oliver Upton --- 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 Wed Nov 3 06:24:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600163 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 78A72C433F5 for ; Wed, 3 Nov 2021 06:27:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5AA4660F70 for ; Wed, 3 Nov 2021 06:27:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231702AbhKCGaD (ORCPT ); Wed, 3 Nov 2021 02:30:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231542AbhKCGaC (ORCPT ); Wed, 3 Nov 2021 02:30:02 -0400 Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C67EC061714 for ; Tue, 2 Nov 2021 23:27:26 -0700 (PDT) Received: by mail-qk1-x74a.google.com with SMTP id bq14-20020a05620a468e00b0046335b327e9so1428075qkb.23 for ; Tue, 02 Nov 2021 23:27: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=n5Mpm1dPS5qrwYaJYU/agwQssFs98KR5NEscCLDHrDk=; b=ABd1koV8Gl2hJTJlzKQ2TE4i0OZM6joq3RY59RXxM78F5WprMLFsfcFyrasCljyITD OAuHWRzVkhEgUYg/9UiOGSarEqfDsv7z8ihB9IMACLrgqxFVPzNrNZNcE/o3qxfyrvBi qxITEXj6LAe5KFxUkA3kbAhJ8Z+gPSpWIEkPsKV7uK+IN/gxNPRYeIFomGHAT1wSDVtj 7axcVo+RR7e2CHo9HzXVMAupRNaJSTSe5tnL+dxGAEPW2+IcENHVw0wMmTKtC/gPlzCF vNFCTZCYiMUoul0kMxAOtPLIoZjYX+n4s8IBr+IeLGXh8RyTVrSt2V4SPwmRVGSfiCCP BLTw== 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=n5Mpm1dPS5qrwYaJYU/agwQssFs98KR5NEscCLDHrDk=; b=pqHPIN11P6yo353AvV6dH/ir7ywcocd5B4oxC4tVLXehH+RO9sz/C5m20bxSuu/OGk T4G49fquP58jOOOd4fqf2maaNimfmHyxURaRDzAlWmAdP/VPobD5f2CuOleuaApelJe3 i6S7FEgaH36I7qaFQR65xoNlwvPgoBKi/y5dcVlLnoxF5Azrfu3SfgvHxMJggDBN/k89 KlGrj3yridhC28wD7UL+uQMMQ5oeP3AZldlAH5NEtOVnozU3dYLy1NE2FAJ7DkrG09RV abDXFubRf+DYy54SdxgFy/IjnAauWhuTkchNcNPwacxIUOEqPP/pQmzMDYD1Y3Rg+PjM MFHg== X-Gm-Message-State: AOAM531pJ87pkaXQBnYk93hFnlxm6gFJsx9RYhLSIVldtLQRhySacNHQ zkqZZcU+IZAG7IS6O7YSz//dOiZtZpE= X-Google-Smtp-Source: ABdhPJz/OH1hMFPzW8wb6ElpnTc74oWf3BDGaQL86sDvpE3n7HWvwsPReTOA/V/bduCiFdD2eoOskTKhtQM= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:ac8:5a4b:: with SMTP id o11mr44697222qta.59.1635920845521; Tue, 02 Nov 2021 23:27:25 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:54 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-3-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 02/28] 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 | 24 ++++++++++++++++-------- 2 files changed, 26 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..2443440720b4 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,8 @@ 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 Wed Nov 3 06:24:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600165 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 2FD22C433EF for ; Wed, 3 Nov 2021 06:27:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 135D761139 for ; Wed, 3 Nov 2021 06:27:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231709AbhKCGaL (ORCPT ); Wed, 3 Nov 2021 02:30:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60856 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbhKCGaI (ORCPT ); Wed, 3 Nov 2021 02:30:08 -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 BE618C06120B for ; Tue, 2 Nov 2021 23:27:32 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id y125-20020a25dc83000000b005c2326bf744so2631285ybe.21 for ; Tue, 02 Nov 2021 23:27:32 -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=5NZ1PewkVBHXKHBWduRPYy68+IVzIFx45xL3upKYtFs=; b=jnCXRXMvE9ZB+MnQQVF9LzDUssipfiWrPymUniSl6L6OVOjHzZerCGTDf7uw0hSfrY WQgBXkPNeqkCU4/SlHpsIhdslXsUZ0lkqKP4SuNXitWbEnli/2AuJG0db5GqX+TL2Nnb NLuwVJi9lhBcfI/GosjLFEv3e5qNPsOV9f0J9krOP2aTC/Hc6jKzDHJS7MzMFhOVpqA2 AmtCsvswBDJQmbcJZUDCevPkTBATPE1WxJoBnl2Itd6iQIeP4bcnuBbAGnNvXEbWGq6S a5WOLMZN7mP2jBGdAFTG7XyRK/J1SA48r605zUX4enhTRO9mdlDLR+oQGjKPQ5sZZ6s2 Yrzw== 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=5NZ1PewkVBHXKHBWduRPYy68+IVzIFx45xL3upKYtFs=; b=GGLgDKtI8PwtK4Nj19iYrhEdU7sfAFilv70/8iXxLjqgtDuxvYRDzbtfqgNcb7Q4OS g71Nt+iTpx2El+Dx3w2Qohab97H0svxlIUiD+OPkBCyyyRlL+enYTQKZYO0tDkghLr7W Q5vqsU/N5AZlwl5Ztka3ZYufKl5OAm7hRf2vXLoIAvgdkKDF0BXaZTEMcG6vuZfljUbh QjQDpH7faBuJhcE+0c2YpxjA+uWDhX4TuRHLZq0ml6pgkyTJqgyZ8I/q6Ue+KbQupfjY +om8A0clVpMfTVcK4d/u4zXldpqqrWS15r0IPs4sm8v/uCVj/EvIxnN58/ahTnIyFWhZ hXTw== X-Gm-Message-State: AOAM5304YU1gMO8kqJ/q0tY02TD5c4K0KmOr2/wvVBBvrkFP5FMZb23H cyICP461SOgMihbfP3IjlPLADl+pH24= X-Google-Smtp-Source: ABdhPJyypqhuw0+qVyo6SYiqQmRnwaA+Xr/FX+o5ay5pTVVxe8nLUkcWASh53mAdIZt9sBeSXhyfbn0z3qg= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a25:74c8:: with SMTP id p191mr35571120ybc.157.1635920852001; Tue, 02 Nov 2021 23:27:32 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:55 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-4-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 03/28] 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, and provide set of functions commonly used for ID registers to make them writable. The id_reg_info 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 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/include/asm/sysreg.h | 1 + arch/arm64/kvm/sys_regs.c | 222 ++++++++++++++++++++++++++++++-- 2 files changed, 214 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index b268082d67ed..5c4890cdc29b 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1186,6 +1186,7 @@ #define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT) #define ARM64_FEATURE_FIELD_BITS 4 +#define ARM64_FEATURE_FIELD_MASK ((1ull << ARM64_FEATURE_FIELD_BITS) - 1) /* Create a mask for the feature bits of the specified feature. */ #define ARM64_FEATURE_MASK(x) (GENMASK_ULL(x##_SHIFT + ARM64_FEATURE_FIELD_BITS - 1, x##_SHIFT)) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2443440720b4..64d51aa3aee3 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -263,6 +263,181 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, return read_zero(vcpu, p); } +/* + * A value for FCT_LOWER_SAFE must be zero and changing that will affect + * ftr_check_types of id_reg_info. + */ +enum feature_check_type { + FCT_LOWER_SAFE = 0, + FCT_HIGHER_SAFE, + FCT_HIGHER_OR_ZERO_SAFE, + FCT_EXACT, + FCT_EXACT_OR_ZERO_SAFE, + FCT_IGNORE, /* Don't check (any value is fine) */ +}; + +static int arm64_check_feature_one(enum feature_check_type type, int val, + int limit) +{ + bool is_safe = false; + + if (val == limit) + return 0; + + switch (type) { + case FCT_LOWER_SAFE: + is_safe = (val <= limit); + break; + case FCT_HIGHER_OR_ZERO_SAFE: + if (val == 0) { + is_safe = true; + break; + } + fallthrough; + case FCT_HIGHER_SAFE: + is_safe = (val >= limit); + break; + case FCT_EXACT: + break; + case FCT_EXACT_OR_ZERO_SAFE: + is_safe = (val == 0); + break; + case FCT_IGNORE: + is_safe = true; + break; + default: + WARN_ONCE(1, "Unexpected feature_check_type (%d)\n", type); + break; + } + + return is_safe ? 0 : -1; +} + +#define FCT_TYPE_MASK 0x7 +#define FCT_TYPE_SHIFT 1 +#define FCT_SIGN_MASK 0x1 +#define FCT_SIGN_SHIFT 0 +#define FCT_TYPE(val) ((val >> FCT_TYPE_SHIFT) & FCT_TYPE_MASK) +#define FCT_SIGN(val) ((val >> FCT_SIGN_SHIFT) & FCT_SIGN_MASK) + +#define MAKE_FCT(shift, type, sign) \ + ((u64)((((type) & FCT_TYPE_MASK) << FCT_TYPE_SHIFT) | \ + (((sign) & FCT_SIGN_MASK) << FCT_SIGN_SHIFT)) << (shift)) + +/* For signed field */ +#define S_FCT(shift, type) MAKE_FCT(shift, type, 1) +/* For unigned field */ +#define U_FCT(shift, type) MAKE_FCT(shift, type, 0) + +/* + * @val and @lim are both a value of the ID register. The function checks + * if all features indicated in @val can be supported for guests on the host, + * which supports features indicated in @lim. @check_types indicates how + * features in the ID register needs to be checked. + * See comments for id_reg_info's ftr_check_types field for more detail. + */ +static int arm64_check_features(u64 check_types, u64 val, u64 lim) +{ + int i; + + for (i = 0; i < 64; i += ARM64_FEATURE_FIELD_BITS) { + u8 ftr_check = (check_types >> i) & ARM64_FEATURE_FIELD_MASK; + bool is_sign = FCT_SIGN(ftr_check); + enum feature_check_type fctype = FCT_TYPE(ftr_check); + int fval, flim, ret; + + fval = cpuid_feature_extract_field_width(val, i, 4, is_sign); + flim = cpuid_feature_extract_field_width(lim, i, 4, is_sign); + + ret = arm64_check_feature_one(fctype, fval, flim); + if (ret) + return -E2BIG; + } + return 0; +} + +struct id_reg_info { + u32 sys_reg; /* Register ID */ + + /* + * Limit value of the register for a vcpu. The value is the sanitized + * system value with bits cleared for unsupported features for the + * guest. + */ + u64 vcpu_limit_val; + + /* + * The ftr_check_types is comprised of a set of 4 bits fields. + * Each 4 bits field is for a feature indicated by the same bits + * field of the ID register and indicates how the feature support + * for guests needs to be checked. + * The bit 0 indicates that the corresponding ID register field + * is signed(1) or unsigned(0). + * The bits [3:1] hold feature_check_type for the field. + * If all zero, all features in the ID register are treated as unsigned + * fields and checked based on Principles of the ID scheme for fields + * in ID registers (FCT_LOWER_SAFE of feature_check_type). + */ + u64 ftr_check_types; + + /* 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, const struct id_reg_info *id_reg, + u64 val); + + /* Return the reset value of the register for the vCPU */ + u64 (*get_reset_val)(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg); +}; + +static void id_reg_info_init(struct id_reg_info *id_reg) +{ + id_reg->vcpu_limit_val = read_sanitised_ftr_reg(id_reg->sys_reg); + if (id_reg->init) + id_reg->init(id_reg); +} + +/* + * 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, check_types; + int err; + + if (id_reg) { + check_types = id_reg->ftr_check_types; + limit = id_reg->vcpu_limit_val; + } else { + /* All fields are treated as unsigned and FCT_LOWER_SAFE */ + check_types = 0; + limit = read_sanitised_ftr_reg(id); + } + + /* Check if the value indicates any feature that is not in the limit. */ + err = arm64_check_features(check_types, val, limit); + if (err) + return err; + + if (id_reg && id_reg->validate) + /* Run the ID register specific validity check. */ + err = id_reg->validate(vcpu, id_reg, 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 +1351,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 +1408,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 +1419,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 +1432,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 0; + + err = validate_id_reg(vcpu, rd, val); + if (err) + return err; + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(encoding)) = val; return 0; } @@ -2816,6 +3004,20 @@ 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; + + id_reg_info_init(id_reg); + } +} + void kvm_sys_reg_table_init(void) { unsigned int i; @@ -2850,4 +3052,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 Wed Nov 3 06:24:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600167 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 B8676C433FE for ; Wed, 3 Nov 2021 06:27:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C5B260EBD for ; Wed, 3 Nov 2021 06:27:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231749AbhKCGaN (ORCPT ); Wed, 3 Nov 2021 02:30:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231724AbhKCGaM (ORCPT ); Wed, 3 Nov 2021 02:30:12 -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 EEE62C061714 for ; Tue, 2 Nov 2021 23:27:36 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id e4-20020a630f04000000b002cc40fe16afso976873pgl.23 for ; Tue, 02 Nov 2021 23:27: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=2kkWf9Zdg9qBQvwRcMyQK3V/8Ny7lbc2Hbppz7GxNUU=; b=ZLc1WdJUS93vqQce2eG799TQxbD2srN4onYKkVcfL2Qy9TnekNN3Vl6DK8+Ri32oM7 YYTKpD6QQGLRVUs2Gep5QkIzNUqeJ3Xk3zrHbHMSNJv2EmE1u0worcGwk4rHrtl6x+Ey EGlfhtIg5LeD5CyBmJa9zwPtN17NgP+YlqYLEzSdMOo75fpLdVtX/9JyPaow0wpXj5Hh GIbKaWe1vB0I6uGb2fsaGUAWiLwVur8adMQn5JSZDCqMN2VCtyDl0k5CSAE1L1dpyJSd RCi61slMNASXPLLAxW4pmUBIseVDXZk+lfLUimHZPGz9agQQU/7wy2EsjEHbduCLM4zH T4SA== 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=2kkWf9Zdg9qBQvwRcMyQK3V/8Ny7lbc2Hbppz7GxNUU=; b=sI11GhHaaQDjt21cv64XLJ/Zm4qKanEqhqzJW+Oz1UXLg3BLAvhodvNoTV/o6eCCUK 67emWDJNnAcC6KFAriIUDL8ASM0LfJyXtmzoBtRB/5jPg/l9AmUY0w/h9NEdi48BAbW8 jtimzNN3gfjTceph05rsv19INTXS7Yn5EQV/3oA/v3NPdR8mTWGr00lrJR1alhcfgnyW /IJFj8YifJjguB+hG/g13qtcOyWQiVTJzGxZMBtLH4nc8MkIwprfR46IStK5ex+98oeL c9zaialUEuzR1jZEcwNEx6FkGPDGpWTOrFb9oepp8Z7zDDhAz4kPgGT+nqKfNUdxWUrY CH8g== X-Gm-Message-State: AOAM532sePqU3P76q8uWYMHv3oj3fw77uIk7qGqjVZMBiFfAP8QmKWHX jcnJgRe/2Uvr3N8WkQwjooOPTyPgtzY= X-Google-Smtp-Source: ABdhPJziBhn4stzQ3o4JqWAXRAPRH2k+xrO4rqj56Fh+Dx8pv+gOVGokRNBtSBx8lVyj+81XUSJwFXkbmak= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:1254:b0:481:29f7:398 with SMTP id u20-20020a056a00125400b0048129f70398mr8484996pfi.33.1635920856329; Tue, 02 Nov 2021 23:27:36 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:56 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-5-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 04/28] 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 | 4 ++++ arch/arm64/kvm/sys_regs.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 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..83cedd74de73 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -595,6 +595,10 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) return -EPERM; vcpu->arch.has_run_once = true; + if (kvm_id_regs_consistency_check(vcpu)) { + vcpu->arch.has_run_once = false; + return -EPERM; + } kvm_arm_vcpu_init_debug(vcpu); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 64d51aa3aee3..e34351fdc66c 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1436,6 +1436,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 0; @@ -3004,6 +3008,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 Wed Nov 3 06:24:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600169 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 D7C4BC433EF for ; Wed, 3 Nov 2021 06:27:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C208861166 for ; Wed, 3 Nov 2021 06:27:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231732AbhKCGaT (ORCPT ); Wed, 3 Nov 2021 02:30:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60918 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbhKCGaT (ORCPT ); Wed, 3 Nov 2021 02:30:19 -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 5528EC061714 for ; Tue, 2 Nov 2021 23:27:43 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id hg9-20020a17090b300900b001a6aa0b7d8cso504165pjb.2 for ; Tue, 02 Nov 2021 23:27: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=N0SbCRP3FKRRzXxFVtqHEMOI2H4V/KqfiyftI54n7ms=; b=nbULxAJVUgSTvzbzYkJpllo4pr/PidHqAwdpNySLT2DDGu33eW12HvREdaiWSWySLk wKofZpcvt6GZiUBmFDDtoklSlj7kX/sLAAMJz8jOAYEDgOCHe65nQCWY2bOf9r6sHiQe EeBdYkuVUoThWnF3UaaUtW0J6s6y3IhQc3H9s6FOl6Febbdvp1nH8mSeBBXQflsXaLbW D0imWPF22I5h3NPC0s/nahlgv+rKBmkKB18Y9VI8Mj81aE/iOkgI1O4AS/YW1hewwYM0 p8qbIVBpsSr9MTJxnGC+CmlwPsZNowhWWZJs4zm4tzX5syMIxC18NAsinKiwasiRbnob 4XKw== 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=N0SbCRP3FKRRzXxFVtqHEMOI2H4V/KqfiyftI54n7ms=; b=Hgf0zlwV57AFgID6HIs19R0tWsdEDzmbWsfGXkzEWjTYUnrjymKrSC6QNZEALVJf2+ 3aTU/C0e7eETeQcYbZ90DHglq81wIXdCO0fvzrZcTJPT63VX4IaO6T1wDcCsb5ddUGP1 Ltr7KBlcwdWFvF0h4eLMfIOg2dJTEzK3E5Pb+DtZaW0GtvMvidDdk8mzHLd7YztCSF6v hs+u3RRT7DFbvqqt8kabPRKogOFp+CmoKv+ffu5Fd6Ssf1qnNcTEJsTFI62EdnizQoZJ ODXw1wj9aLS8UAcSKRu6fGYnR8SX3DdtV+XJr7Zm9xPWnL9HBT0HZ2Ra74+6DiLcVh3j y+oA== X-Gm-Message-State: AOAM533ltiDSe00mE0Oy6C4+Z2npn/ettT5tFFJrN3EdfnEIPo/u9UPj NMVXc/XixN65SzRtQ68owb2Qgn9+P48= X-Google-Smtp-Source: ABdhPJzUIdVk2Gmdy05xtv+RbFBPD5/d1DZfMTtRC7rOaY/OLKNJi2PwVTXDzT8OsklcEBZV/tjKvV0G26M= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:810:b0:481:22cc:ed59 with SMTP id m16-20020a056a00081000b0048122cced59mr10926037pfk.5.1635920862755; Tue, 02 Nov 2021 23:27:42 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:57 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-6-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 05/28] 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 83cedd74de73..528058920b64 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 e34351fdc66c..c8d31976414a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -399,6 +399,70 @@ static void id_reg_info_init(struct id_reg_info *id_reg) id_reg->init(id_reg); } +static int validate_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, 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->vcpu_limit_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, + const 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, + .ftr_check_types = S_FCT(ID_AA64PFR0_ASIMD_SHIFT, FCT_LOWER_SAFE) | + S_FCT(ID_AA64PFR0_FP_SHIFT, FCT_LOWER_SAFE), + .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. @@ -407,7 +471,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) @@ -1241,15 +1307,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)) { @@ -1366,48 +1423,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, @@ -1695,8 +1710,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 Wed Nov 3 06:24:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600171 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 00E3FC433EF for ; Wed, 3 Nov 2021 06:27:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DEB7160EBD for ; Wed, 3 Nov 2021 06:27:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231757AbhKCGab (ORCPT ); Wed, 3 Nov 2021 02:30:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbhKCGaa (ORCPT ); Wed, 3 Nov 2021 02:30:30 -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 7C969C061714 for ; Tue, 2 Nov 2021 23:27:54 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id p20-20020a63fe14000000b002cc2a31eaf6so1036545pgh.6 for ; Tue, 02 Nov 2021 23:27:54 -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=u0QM1MgzkdUdWU8ieGswYiMTZQIOeeUedN1E6eFAWdI=; b=r+j4V8yijGuSg95fkOuf7DHWbWDyHpFWYTbBIFFcfFjvzCuhLBLXdytqjYmCsld4Fk kr5O7mo6mf9wuHUngxXV66j8nhy03Jxi+Vi2OngmWuwVY2XJVT/uLvNgbjpRelhTpZa3 D0Y44ckyfC9qyzhPoxK3tg83zyBk3ei/pDEFJuAR0QWBH9hn9sf3/clGz7RibFVKN/PQ 2mfINOTyKZi0j9xUtBhuxJBF3cLqBwNHzUf8CRI4fuWDyVu/8ktj2ABADZGkxkglwTKK rc6L2sa2F4GGK/VPzn7GC4GP9MtGJbr94t8/nnhI8zROXYr4VlTbs3yTdqOhS5+I/gQo +Idw== 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=u0QM1MgzkdUdWU8ieGswYiMTZQIOeeUedN1E6eFAWdI=; b=vvr8pPgGEPPdbYCPgibafQN4IWjcHVNUV/WYLE3hsyQRbLYcjXosit/LXrMyKBw3yj PoR5Hlxk6VlnuLZuBGWHjk18WHUacFQIQDzAPtRaAXiAYEodsn8UW1wQdcx6gW72imoE 5bOPjiG3W2kIH6/tmqjryv1RFzGbtdbNSP2HOVMQ2lvavKH1r8N9e6KmUTbLHlJprQow Rqu3MMLN9Hm8NdURXTHvD5ec/J08wF5irfRQ4a2vOABVbxUC163h9sMfmQbMnJ2twyWj xUd38//VeMgYwpd5N5E6eRyPWYWs0cu/ZFou+V8u1J2yWgzs5TcX8uQA97hocB4P7BEz 440w== X-Gm-Message-State: AOAM532b7f3WegmsHhjD2yM6UDOi/2ctfYj704t0Vngv21XNszDGo/MZ oq1RqksPV135DjbDbLrx/p24V+YylBw= X-Google-Smtp-Source: ABdhPJym2Kc2LkDY/dBhiRC4pLXDFMk8yWTIRAYpw89oOYo/K9kB1jpbXdjQX8d0tFwgXqr1caSe6epQw7c= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90a:1190:: with SMTP id e16mr12369998pja.209.1635920872599; Tue, 02 Nov 2021 23:27:52 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:58 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-7-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 06/28] 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. Skip fractional feature fields validation at present and they will be handled by the following patches. Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kvm/sys_regs.c | 50 ++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 5c4890cdc29b..e8acc3607590 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 c8d31976414a..00ebf4dfc4f8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -422,6 +422,21 @@ static int validate_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static int validate_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, 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 = id_reg->vcpu_limit_val; @@ -446,6 +461,12 @@ 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) +{ + if (!system_supports_mte()) + id_reg->vcpu_limit_val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE); +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct id_reg_info *idr) { @@ -454,6 +475,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, + const 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, .ftr_check_types = S_FCT(ID_AA64PFR0_ASIMD_SHIFT, FCT_LOWER_SAFE) | @@ -463,6 +492,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, + .ftr_check_types = U_FCT(ID_AA64PFR1_RASFRAC_SHIFT, FCT_IGNORE) | + U_FCT(ID_AA64PFR1_MPAMFRAC_SHIFT, FCT_IGNORE) | + U_FCT(ID_AA64PFR1_CSV2FRAC_SHIFT, FCT_IGNORE), + .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. @@ -473,6 +512,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, @@ -1307,16 +1347,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 Wed Nov 3 06:24:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600173 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 2560EC433EF for ; Wed, 3 Nov 2021 06:28:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E8246115B for ; Wed, 3 Nov 2021 06:28:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231738AbhKCGan (ORCPT ); Wed, 3 Nov 2021 02:30:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32818 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbhKCGam (ORCPT ); Wed, 3 Nov 2021 02:30:42 -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 A2FE8C061714 for ; Tue, 2 Nov 2021 23:28:06 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id e6-20020a637446000000b002993ba24bbaso1012076pgn.12 for ; Tue, 02 Nov 2021 23:28:06 -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=Gm7mR1LOrJBKTHxCMeDmedILqwUP3OMytAls+H/S7bU=; b=jPsuNnbg/QU+2caiIez8a8TyHTUk/yd+DEx9LtczN9tZprd+9kHOPY+WTAVfiBJ6ai kzBH3B3/w81JPllA73p+RDDa3TzrwdZNZYBVr/PPQyq/vNmLLXGPSIL8P1NBu7lWCoa0 dHDK9bbyO4r5QKxFc1pDDfOlPFaJhX0E0UqNp8fIB8i5SivMPXLJwe/lRK2WPY/qy32P BWUjNgmK+s8JOKv2bWAfhQZyTR1T0KE2eBP1NbGgRNZ/VWdEq7tGTvlA82xdbD8NTibE 7BsUZ7muTN/zFD1beM9hgHFZSw6BLJbETIzDlZDPiNkgkYQzNccXc5H9Dq8FNK8l41XY bUIw== 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=Gm7mR1LOrJBKTHxCMeDmedILqwUP3OMytAls+H/S7bU=; b=D8MYcmWIlACVftU1zOM/vjTu8ks+IMCu21oCreIAxXUSQM/OwC0Neb6CDj+jSF0raC nYDmJFKEIGR9ngv5TbaD3pxolqgbxjPB5aFFGe3pw+tZ7D97KNQd4sJUN6+SlLuzAQbz byNii0owsV6Txm/kTjdlCv4aAuKSHYh7K9wIfcx2do5xarOKrBc1cUhwEmiXRQ+OqWfe SsTGFO/5bVGwZssC+dToDyKmIGeWOhm00tFehinjTIsUGXfv0+UmxGiRfrZC9ttRRgu+ o5eCU8wbes1dH6QTLbBRYHH4yNm7WPjnmoEBMbda5D60n0R0XY33T1S7N9gUct9jqfJI XuHA== X-Gm-Message-State: AOAM532AZN9647cdlXvLcGgWYlFVwqXeTXyg6qZ29tydI1riftXOiJwq otLZVjKaD7GPiImsXsSKXqXtXCqcWvQ= X-Google-Smtp-Source: ABdhPJx4iUpI5oPSkMfBiiSHZTrxt3jDZPbO9Y5vkrpaP5+G0KSWuasdv0FcSGbk6TmKos+QwAbRI+dV8AU= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:ab8c:b0:13a:22d1:88d with SMTP id f12-20020a170902ab8c00b0013a22d1088dmr36282740plr.33.1635920886142; Tue, 02 Nov 2021 23:28:06 -0700 (PDT) Date: Tue, 2 Nov 2021 23:24:59 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-8-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 07/28] 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 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 00ebf4dfc4f8..7f505853b569 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -437,6 +437,29 @@ static int validate_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, return 0; } +static int validate_id_aa64isar0_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, 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 = id_reg->vcpu_limit_val; @@ -502,6 +525,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. @@ -513,6 +541,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 Wed Nov 3 06:25:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600175 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 9E37DC433FE for ; Wed, 3 Nov 2021 06:28:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8707C60240 for ; Wed, 3 Nov 2021 06:28:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231912AbhKCGao (ORCPT ); Wed, 3 Nov 2021 02:30:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbhKCGao (ORCPT ); Wed, 3 Nov 2021 02:30:44 -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 48F02C061714 for ; Tue, 2 Nov 2021 23:28:08 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id g26-20020a63521a000000b0029524f04f5aso1039383pgb.5 for ; Tue, 02 Nov 2021 23:28:08 -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=62b24VOqm1GyPCwAwjAOsxxDMNGj6sMpkNWOp6uvxsM=; b=XlbO25p2CIQboATiZM796LS9XynMuq0GihpUcYOZrTmQhvJzRJ2W/kjCoQLkW092ux iZwcnroXhOVlOrNpwyjrb4W7FhkK+5ur3AYKTrsIPhlnANtJ2ggQfqeJ8k3knJ5xm8NQ XQLwJckKsME0PRvn7JU9p+y1maCsQ7z4k+gRpL5u6lRaNtaEz9LsTgchiiQAf5AMGsZI oxxvN08C1a91mRWJHpn1VtdIZfTpqaIxzUk+dJP+qAHWgqq9gX7AdZ4Mm6fiVtJvSyJF zihzYRwoZJrmBgPEAhtAPegRJl3TYI2CLuDPM/yTxxZJwFHwrvNP0aeFRqM9Yg8gJzpy lMgQ== 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=62b24VOqm1GyPCwAwjAOsxxDMNGj6sMpkNWOp6uvxsM=; b=ZClIJhIQN8PEl6rVTiGWFE6EUlis/x5uV4VUP4H+gL9APWFPio+RxP02fYMjjJL6Tq RGhFlj24PuJISMg1krAdL/00mslCzIG5NqeBnlOzuQ2I+hsVHtErYh6TzK+Wga+j5Ooy Hx1iWEAPN5hjYSxbBnYp+F1QkvSVXMhUwAJj0knbtJ6/GqzLYsvsjIL6clUmNZJcWA0c OsR2Lc+F/S2J9jf4T+Yk4uv8SrXkCky5BZx87YpDVg6HQUeTzzWWjQkMIIPLrnvuYswN mal2aPo5OsCSJNc8q+Deno/5j1QWA0euTgOozOS//wzdqEVOq+gpCjIjV7HVO2z8jkTN cc2w== X-Gm-Message-State: AOAM5319/D1wVmf5sQOME+YgStspgTqDQY1fEEfthzQTGxG3fx6U7gdX IHaZBmqbYPC8u5fNWjVkzksEvCxxBjg= X-Google-Smtp-Source: ABdhPJyGvMyBr7tNE7aE91Wbj2mvX+2vJq4YTKJKizdjI2txUHQhqgC4yVAz0wHp3y/dUFG7WJDfQgKWMXI= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:b83:b0:47b:fbb3:9265 with SMTP id g3-20020a056a000b8300b0047bfbb39265mr41424784pfj.79.1635920887811; Tue, 02 Nov 2021 23:28:07 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:00 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-9-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 08/28] 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, which was configured by KVM_ARM_VCPU_INIT, for the guest. 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 7f505853b569..83b05d37afbd 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -356,6 +356,24 @@ static int arm64_check_features(u64 check_types, u64 val, u64 lim) return 0; } +#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 */ @@ -460,6 +478,36 @@ static int validate_id_aa64isar0_el1(struct kvm_vcpu *vcpu, return 0; } +static int validate_id_aa64isar1_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, u64 val) +{ + bool has_gpi, has_gpa, has_api, has_apa; + bool generic, address; + + has_gpi = aa64isar1_has_gpi(val); + has_gpa = aa64isar1_has_gpa(val); + has_api = aa64isar1_has_api(val); + has_apa = aa64isar1_has_apa(val); + if ((has_gpi && has_gpa) || (has_api && has_apa)) + return -EINVAL; + + generic = has_gpi || has_gpa; + address = has_api || has_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_has_ptrauth(vcpu) ^ (generic && address)) + return -EPERM; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit = id_reg->vcpu_limit_val; @@ -490,6 +538,12 @@ static void init_id_aa64pfr1_el1_info(struct id_reg_info *id_reg) id_reg->vcpu_limit_val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE); } +static void init_id_aa64isar1_el1_info(struct id_reg_info *id_reg) +{ + if (!system_has_full_ptr_auth()) + id_reg->vcpu_limit_val &= ~PTRAUTH_MASK; +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct id_reg_info *idr) { @@ -506,6 +560,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, + const 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, .ftr_check_types = S_FCT(ID_AA64PFR0_ASIMD_SHIFT, FCT_LOWER_SAFE) | @@ -530,6 +591,16 @@ 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, + .ftr_check_types = + U_FCT(ID_AA64ISAR1_API_SHIFT, FCT_EXACT_OR_ZERO_SAFE) | + U_FCT(ID_AA64ISAR1_APA_SHIFT, FCT_EXACT_OR_ZERO_SAFE), + .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. @@ -542,6 +613,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, @@ -1376,13 +1448,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 Wed Nov 3 06:25:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600177 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 48202C433F5 for ; Wed, 3 Nov 2021 06:28:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 25ED661139 for ; Wed, 3 Nov 2021 06:28:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231952AbhKCGar (ORCPT ); Wed, 3 Nov 2021 02:30:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231913AbhKCGaq (ORCPT ); Wed, 3 Nov 2021 02:30:46 -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 4A72BC061203 for ; Tue, 2 Nov 2021 23:28:10 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id f92-20020a25a465000000b005bea37bc0baso2781351ybi.5 for ; Tue, 02 Nov 2021 23:28:10 -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=lJ8r9zWPVVKmzZ6XSiFVL9KgUM/7kGO2C8okeqFq7iE=; b=GqPCo2kbDo0gSPnj0m72zxZN00OWSr6pB/bwwtdLgEnl+1CHLDmcJ7wRo2HBZZl1Uw VJGWlUmgdT15yGsf419qc5odq6L42fdhxeD/SceMwaKW+IJIpMb55xdO8oNMVCc+YC4f SPUnMH279dlDVDa4J21/pmG99XYuWQn3g9fblMyc2IXrAu3Kl1c7HVIWeA4HF7BTg1aw C/pdtC0RxeBplDs+nI9HpawzVghMQe8H06V2FUC9lXnZ8wLza/XlMnqDVLCn+a0Jnx0o vVmHmHg7dah9XVqJfLu3d7/Y8oBnftMRWwQ6gtiwA07RE9JlVNSye4iUezXitwJtiuR+ 2AvA== 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=lJ8r9zWPVVKmzZ6XSiFVL9KgUM/7kGO2C8okeqFq7iE=; b=Cdd6bFYEVuuXnz7E8tecxUVpoaKs64e8BMPHhBkkv4k8/s1B2HmoLKi/m5A/8gWLF2 MEKKKwwQLYH9qi3I8DYvuDwGz+dF1+OdtK7nVmNZYOjYHjkhVN1IVrYViASz8lxJh9PE dMNx8TYQ+vdOyhL0Aznw92HpANGOGJqjlgn5wwkpTFh0abKiYtbAa0ciP4h0ntlVfTZ3 3CC4pjqvISGcLgVeIGMccDumM0/bq9K5Vs0AleqjEIDSabFhzRtoJhwmNayDJW5H0aYs xvjMJVY9fkYboyo1MRsk56ObUGJNPdi8QydNFL7bwfCErkFAnfc1hz+QRRk4sud4MuHV mJYQ== X-Gm-Message-State: AOAM532H8vvUF3Yq+2UWaf7gXXiv5udZT6ToGucjuMaPrCWROwoBckoY NmUScUkaLoQHB1QfrDD+EIVdQ6uk3mI= X-Google-Smtp-Source: ABdhPJxFZGDuaoZmZoSlnGY8V5l2x9kpOlI3wBqVBwlIEIxhhs0O0wxDwHts1tnVSjNnd+MvZ7X1wOjo66k= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a25:2395:: with SMTP id j143mr38737153ybj.415.1635920889503; Tue, 02 Nov 2021 23:28:09 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:01 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-10-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 09/28] KVM: arm64: Make ID_AA64MMFR0_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_AA64MMFR0_EL1 to make it writable by userspace. Since ID_AA64MMFR0_EL1 stage 2 granule size fields don't follow the standard ID scheme, we need a special handling to validate those fields. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 118 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 83b05d37afbd..7c1ac456dc94 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -508,6 +508,113 @@ static int validate_id_aa64isar1_el1(struct kvm_vcpu *vcpu, return 0; } +/* + * Check if the requested stage2 translation granule size indicated in + * @mmfr0 is also indicated in @mmfr0_lim. This function assumes that + * the stage1 granule size indicated in @mmfr0 has been validated already. + */ +static int aa64mmfr0_tgran2_check(int field, u64 mmfr0, u64 mmfr0_lim) +{ + s64 tgran2, lim_tgran2, rtgran1; + int f1; + bool is_signed = true; + + tgran2 = cpuid_feature_extract_unsigned_field(mmfr0, field); + lim_tgran2 = cpuid_feature_extract_unsigned_field(mmfr0_lim, field); + if (tgran2 == lim_tgran2) + return 0; + + if (tgran2 && lim_tgran2) + return (tgran2 > lim_tgran2) ? -E2BIG : 0; + + /* + * Either tgran2 or lim_tgran2 is zero. + * Need stage1 granule size to validate tgran2. + */ + switch (field) { + case ID_AA64MMFR0_TGRAN4_2_SHIFT: + f1 = ID_AA64MMFR0_TGRAN4_SHIFT; + break; + case ID_AA64MMFR0_TGRAN64_2_SHIFT: + f1 = ID_AA64MMFR0_TGRAN64_SHIFT; + break; + case ID_AA64MMFR0_TGRAN16_2_SHIFT: + f1 = ID_AA64MMFR0_TGRAN16_SHIFT; + is_signed = false; + break; + default: + /* Should never happen */ + WARN_ONCE(1, "Unexpected stage2 granule field (%d)\n", field); + return 0; + } + + /* + * If tgran2 == 0 (&& lim_tgran2 != 0), the requested stage2 granule + * size is indicated in the stage1 granule size field of @mmfr0. + * So, validate the stage1 granule size against the stage2 limit + * granule size. + * If lim_tgran2 == 0 (&& tgran2 != 0), the stage2 limit granule size + * is indicated in the stage1 granule size field of @mmfr0_lim. + * So, validate the requested stage2 granule size against the stage1 + * limit granule size. + */ + + /* Get the relevant stage1 granule size to validate tgran2 */ + if (tgran2 == 0) + /* The requested stage1 granule size */ + rtgran1 = cpuid_feature_extract_field(mmfr0, f1, is_signed); + else /* lim_tgran2 == 0 */ + /* The stage1 limit granule size */ + rtgran1 = cpuid_feature_extract_field(mmfr0_lim, f1, is_signed); + + /* + * Adjust the value of rtgran1 to compare with stage2 granule size, + * which indicates: 1: Not supported, 2: Supported, etc. + */ + if (is_signed) + /* For signed, -1: Not supported, 0: Supported, etc. */ + rtgran1 += 0x2; + else + /* For unsigned, 0: Not supported, 1: Supported, etc. */ + rtgran1 += 0x1; + + if ((tgran2 == 0) && (rtgran1 > lim_tgran2)) + /* + * The requested stage1 granule size (== the requested stage2 + * granule size) is larger than the stage2 limit granule size. + */ + return -E2BIG; + else if ((lim_tgran2 == 0) && (tgran2 > rtgran1)) + /* + * The requested stage2 granule size is larger than the stage1 + * limit granulze size (== the stage2 limit granule size). + */ + return -E2BIG; + + return 0; +} + +static int validate_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, u64 val) +{ + u64 limit = id_reg->vcpu_limit_val; + int ret; + + ret = aa64mmfr0_tgran2_check(ID_AA64MMFR0_TGRAN4_2_SHIFT, val, limit); + if (ret) + return ret; + + ret = aa64mmfr0_tgran2_check(ID_AA64MMFR0_TGRAN64_2_SHIFT, val, limit); + if (ret) + return ret; + + ret = aa64mmfr0_tgran2_check(ID_AA64MMFR0_TGRAN16_2_SHIFT, val, limit); + if (ret) + return ret; + + return 0; +} + static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) { u64 limit = id_reg->vcpu_limit_val; @@ -601,6 +708,16 @@ static struct id_reg_info id_aa64isar1_el1_info = { .get_reset_val = get_reset_id_aa64isar1_el1, }; +static struct id_reg_info id_aa64mmfr0_el1_info = { + .sys_reg = SYS_ID_AA64MMFR0_EL1, + .ftr_check_types = S_FCT(ID_AA64MMFR0_TGRAN4_SHIFT, FCT_LOWER_SAFE) | + S_FCT(ID_AA64MMFR0_TGRAN64_SHIFT, FCT_LOWER_SAFE) | + U_FCT(ID_AA64MMFR0_TGRAN4_2_SHIFT, FCT_IGNORE) | + U_FCT(ID_AA64MMFR0_TGRAN64_2_SHIFT, FCT_IGNORE) | + U_FCT(ID_AA64MMFR0_TGRAN16_2_SHIFT, FCT_IGNORE), + .validate = validate_id_aa64mmfr0_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. @@ -614,6 +731,7 @@ static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [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, + [IDREG_IDX(SYS_ID_AA64MMFR0_EL1)] = &id_aa64mmfr0_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, From patchwork Wed Nov 3 06:25:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600179 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 75A96C433EF for ; Wed, 3 Nov 2021 06:28:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5CA3861166 for ; Wed, 3 Nov 2021 06:28:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231556AbhKCGat (ORCPT ); Wed, 3 Nov 2021 02:30:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32844 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231925AbhKCGar (ORCPT ); Wed, 3 Nov 2021 02:30:47 -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 45E78C061714 for ; Tue, 2 Nov 2021 23:28:11 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id t75-20020a63784e000000b002993a9284b0so1016290pgc.11 for ; Tue, 02 Nov 2021 23:28:11 -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=q7+v9l/nyn0AhgzFSGXemnn4ohytv9T7PB3GkiLTiSE=; b=F/5iIMozxPOo534ZUMCTMOdMx+LyGtJ/iZkeAEsUVRYifAuz8U8ZGbr6iPcr0AjzHk 6HOT5t7D04o0wT7LaJr16di3GZqV1RVebdyhB5sl8cOudvyAQaBba+mKGbq/3qe4OycH e8/0CVyXtti8MBL+PaZBrYK+DNY7pegs7toslxhljSkcdpvcgQJYxgYKl1wzHtuQxgw4 OCuWQ60zLJGsEbhCt7/x0kJsyFY6Ttk2aE492TMse1o5s9v1xZ65ISDa8M4MNHKuK0AW U/g8rvdAII/cUD9IFyW6AnLYnRBJgL1sQnz5rG6jtSyILqqFJHkyM4MtFYiL9OnTooor jNwA== 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=q7+v9l/nyn0AhgzFSGXemnn4ohytv9T7PB3GkiLTiSE=; b=6MqWEcFase135TqIk0jEm7kHi7fV5dbQZmu+JhVtHhcaABJPv0yGbdAYR4dS7zORGk AZ/vhPne58Efbder/kmaq/OHDJ57yykngBRHW9R2cdBjHKEu1vyIKEkiF1ZzTiMGxFQo Ocj1HIRkH9EoVLRbaKDft9AORLIdOdeDo8gO6/AZrIUU5/srQaIu8/10TLgiYhCyo+3o NlBS6DiJs+ulCxKDMRQKTR8cIa8MHAFnuOljvSa501lHhMXLKiW5P4RX/F449B96D23c andDi7UCDdnCxG/yYDil0IpRG5GFHB4kGRTkhFpgVvz3Ee6RbPAnr4lec0ybidp+s+hr Kzgw== X-Gm-Message-State: AOAM533ztTG4I1ibsy8E5Lj+fvuLJhSybDTyWBFk7/lgsFqYdgc2W5Hl Txq/QqOX9r1sg3HIo3WJbNAOB8I2OBo= X-Google-Smtp-Source: ABdhPJwKpyNta3uMXyyhmfNw7FgGewWUZO4qQrdHLOYgh4C4cuvOvtPwwORnahFa9CDV9cNccFbK/CUlCZY= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:14c2:b0:47c:2c90:df4f with SMTP id w2-20020a056a0014c200b0047c2c90df4fmr41652535pfu.63.1635920890804; Tue, 02 Nov 2021 23:28:10 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:02 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-11-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 10/28] KVM: arm64: Hide IMPLEMENTATION DEFINED PMU support 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 When ID_AA64DFR0_EL1.PMUVER or ID_DFR0_EL1.PERFMON is 0xf, which means IMPLEMENTATION DEFINED PMU supported, KVM unconditionally expose the value for the guest as it is. Since KVM doesn't support IMPLEMENTATION DEFINED PMU for the guest, in that case KVM should exopse 0x0 (PMU is not implemented) instead. Change cpuid_feature_cap_perfmon_field() to update the field value to 0x0 when it is 0xf. Fixes: 8e35aa642ee4 ("arm64: cpufeature: Extract capped perfmon fields") Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/cpufeature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index ef6be92b1921..fd7ad8193827 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -553,7 +553,7 @@ cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap) /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */ if (val == ID_AA64DFR0_PMUVER_IMP_DEF) - val = 0; + return (features & ~mask); if (val > cap) { features &= ~mask; From patchwork Wed Nov 3 06:25:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600181 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 DC437C433FE for ; Wed, 3 Nov 2021 06:28:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C29096117A for ; Wed, 3 Nov 2021 06:28:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231922AbhKCGau (ORCPT ); Wed, 3 Nov 2021 02:30:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231629AbhKCGas (ORCPT ); Wed, 3 Nov 2021 02:30:48 -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 15ED4C061203 for ; Tue, 2 Nov 2021 23:28:13 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id x25-20020aa79199000000b0044caf0d1ba8so857724pfa.1 for ; Tue, 02 Nov 2021 23:28:13 -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=odNn+kh1mJM9Vd30nM7BMUJpocE6S6YUrl3newH0ovg=; b=Uk/WrXnp6UTWiI4qWkD9cWC5dtMD9py++anoNbqWH45LTS0dTWf1XDifA3JnVp2wzf cM4Svvigvs6rdongOug1BrvZQJ3ExdllQjyUkpwHONJdXEX+cAaaTBEMcDqYIsL3UFrL +FeDBc6sKGmHvdRqruCtmfGaiPvtTzhzDPrEFKCwL2hiVU2+7+OfJ7ntHcgpG8GcpkEg O/o0aCHXFRgrQHQ4+aSdmFYdAueE2BOyoFI9xArIpb47uOuP+/4L6ne0v8z/AoA3do4p VYVptKUmCpuuBOQxPA1DyylxdM/OoXCT7N02uHaVTkY+xNFdKUelHARVQzm1acTqE8E5 6/pA== 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=odNn+kh1mJM9Vd30nM7BMUJpocE6S6YUrl3newH0ovg=; b=pdlCueoPJs73Q4pjWPGjtTwSrSoxLSQZq9ovERdyeCi+vG1mvFnTavl3fZGHEhQY3t ElSu1Hwn+bNWImk/rZTtyN6hV42xAt6WzsK3S/I3+Box2ujRZXGLvfSk0kvKw4VY5pqw xOgt00K1tSxaVjGcfki2/XnUbC1U4D/nFhr35s/PwLRp5H9xfrDFE4KHC4BGwF1efkGQ YUTTjGQyNT1MTH76mHbP46hLjoVi8Ri1Aze6SDcrWez9jjPkrqeXSE0eygp92KejU08Q UbMerxtxoLSQKb/WxvquQ6uckk0MSKil4k+hYUYLeaILFPfYBB9dZE/7JykBodi9Ldca hW8Q== X-Gm-Message-State: AOAM531av39RV28WaENOwKT1EzaTiOJCSGBO4v4PiBCb8JcuvYwqWl/Z DNvB0nftToXHDs3kRUNjI3E0kWAspcE= X-Google-Smtp-Source: ABdhPJzwNcnZ5x5fy33mJFN2zMuF3k+sEoLH7Zqcea22WcEnEgYTEVa6HyxhzXnd/IokK2/cxHx5dZ+fymg= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:23cc:b0:481:1399:cc40 with SMTP id g12-20020a056a0023cc00b004811399cc40mr17145121pfc.7.1635920892456; Tue, 02 Nov 2021 23:28:12 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:03 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-12-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 11/28] 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 | 84 ++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 7c1ac456dc94..54bc3641d582 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -615,6 +615,45 @@ static int validate_id_aa64mmfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static bool id_reg_has_pmu(u64 val, u64 shift, unsigned int min) +{ + unsigned int pmu = cpuid_feature_extract_unsigned_field(val, shift); + + /* + * 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, + const struct id_reg_info *id_reg, u64 val) +{ + unsigned int brps, ctx_cmps; + bool vcpu_pmu, dfr0_pmu; + + 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; + + vcpu_pmu = kvm_vcpu_has_pmu(vcpu); + dfr0_pmu = id_reg_has_pmu(val, ID_AA64DFR0_PMUVER_SHIFT, ID_AA64DFR0_PMUVER_8_0); + /* 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 = id_reg->vcpu_limit_val; @@ -651,6 +690,23 @@ static void init_id_aa64isar1_el1_info(struct id_reg_info *id_reg) id_reg->vcpu_limit_val &= ~PTRAUTH_MASK; } +static void init_id_aa64dfr0_el1_info(struct id_reg_info *id_reg) +{ + u64 limit = id_reg->vcpu_limit_val; + + /* Limit guests to PMUv3 for ARMv8.4 */ + limit = cpuid_feature_cap_perfmon_field(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, const struct id_reg_info *idr) { @@ -674,6 +730,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, + const 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, .ftr_check_types = S_FCT(ID_AA64PFR0_ASIMD_SHIFT, FCT_LOWER_SAFE) | @@ -718,6 +782,14 @@ static struct id_reg_info id_aa64mmfr0_el1_info = { .validate = validate_id_aa64mmfr0_el1, }; +static struct id_reg_info id_aa64dfr0_el1_info = { + .sys_reg = SYS_ID_AA64DFR0_EL1, + .ftr_check_types = S_FCT(ID_AA64DFR0_DOUBLELOCK_SHIFT, FCT_LOWER_SAFE), + .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. @@ -729,6 +801,7 @@ static struct id_reg_info id_aa64mmfr0_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, [IDREG_IDX(SYS_ID_AA64MMFR0_EL1)] = &id_aa64mmfr0_el1_info, @@ -1566,17 +1639,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 Wed Nov 3 06:25:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600205 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 BA2BCC433F5 for ; Wed, 3 Nov 2021 06:28:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9E1176117A for ; Wed, 3 Nov 2021 06:28:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231705AbhKCGaw (ORCPT ); Wed, 3 Nov 2021 02:30:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231960AbhKCGau (ORCPT ); Wed, 3 Nov 2021 02:30:50 -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 2D1E8C06120B for ; Tue, 2 Nov 2021 23:28:15 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id s22-20020a056a0008d600b00480fea2e96cso841300pfu.7 for ; Tue, 02 Nov 2021 23:28:15 -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=hpPFwAGTwEZ1i/HOmllQFr9pElbCJZ8JCm8mzrl1EGY=; b=mq0S+7gAP0Npdg8RBHPC2lWxXXDKc+VHlWuF1/QYsXFOVsYtMWwvZyS0M+wBMY6/63 w8/MhbJVnBgtNOQI//ywgCot6Z1cn/Utt5TWC+2JwoRBFyLfJBXFAWESwXlC7qUpEMoY HVClvfxgmmCUIfp6jufnEV8NKDk+ysqoSS1J1JGe3IV/S6GNb7yN++OgBk5PLEVpudom 2QXxG10EP0KPYk10RJ5UDb3p0bYd1R0K4CPM2/jxQGN8uT4GTtkzQxeyfn/mlhyh9+1h bRaRSJ0xyifxrKcB/YNLByWcAu12PuOU+rzhT3pHXoSFpDiqo+6Yf7WLtLJzuPepoJCr DtRA== 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=hpPFwAGTwEZ1i/HOmllQFr9pElbCJZ8JCm8mzrl1EGY=; b=WBm3EmqUNKNcoIqf8rZB7xkwyJi1lBzr/nsF/EPxJ6w7iMg0zibeOK/AGL2OZYEKrF DMSoePkePpsgxfoQOefj+ZaZJVdCsbXDzWsYaXInJw1ZalitlNjD+fAyFvV5kQOtPYOM g9wKROMvjwztNULa3padHA8kpUTdZXdRVXVCzwqJrdPPYvWGOXi74a7Onz92/JOTZXNg Z5vEugwNoKQQUqiCCfIcx6G+b3ER1ICgiFq5iwq4JbdK8k9uSfbodkaW/RaCUI+N0Opz uFlxELvM5nOzL6eZNHx8AugJK2AzCLywGF9iaKyd9tZaW75pd5TLT9NKIEaxOIYCaLsQ thVw== X-Gm-Message-State: AOAM532mzUatLhUfzIzssvNX51qxN+1kQD473sK7CpRNZX47s6ylP1Ft OsSLf8zI8QkWnzcxpbc37E4Z48843Wc= X-Google-Smtp-Source: ABdhPJydVvRuo+vjDmU3tMNH4IppD6LBdgzne8qEmR7ZMkyzecx82BglXuP8sTb11J8mDk4MAmH3CRyb248= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90a:c3:: with SMTP id v3mr397676pjd.0.1635920894183; Tue, 02 Nov 2021 23:28:14 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:04 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-13-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 12/28] 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 | 58 +++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 54bc3641d582..8abd3f6fd667 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -654,6 +654,27 @@ static int validate_id_aa64dfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static int validate_id_dfr0_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, u64 val) +{ + bool vcpu_pmu, dfr0_pmu; + unsigned int perfmon; + + perfmon = cpuid_feature_extract_unsigned_field(val, ID_DFR0_PERFMON_SHIFT); + if (perfmon == 1 || perfmon == 2) + /* PMUv1 or PMUv2 is not allowed on ARMv8. */ + return -EINVAL; + + vcpu_pmu = kvm_vcpu_has_pmu(vcpu); + dfr0_pmu = id_reg_has_pmu(val, ID_DFR0_PERFMON_SHIFT, ID_DFR0_PERFMON_8_0); + + /* 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 = id_reg->vcpu_limit_val; @@ -707,6 +728,15 @@ 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) +{ + /* Limit guests to PMUv3 for ARMv8.4 */ + id_reg->vcpu_limit_val = + cpuid_feature_cap_perfmon_field(id_reg->vcpu_limit_val, + ID_DFR0_PERFMON_SHIFT, + ID_DFR0_PERFMON_8_4); +} + static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, const struct id_reg_info *idr) { @@ -738,6 +768,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, + const 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, .ftr_check_types = S_FCT(ID_AA64PFR0_ASIMD_SHIFT, FCT_LOWER_SAFE) | @@ -790,6 +828,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. @@ -799,6 +844,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, @@ -1636,18 +1682,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 Wed Nov 3 06:25:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600207 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 36A36C4332F for ; Wed, 3 Nov 2021 06:28:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2039461179 for ; Wed, 3 Nov 2021 06:28:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231980AbhKCGay (ORCPT ); Wed, 3 Nov 2021 02:30:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231968AbhKCGaw (ORCPT ); Wed, 3 Nov 2021 02:30:52 -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 E6B76C061203 for ; Tue, 2 Nov 2021 23:28:16 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id w132-20020a25c78a000000b005c27f083240so2665867ybe.16 for ; Tue, 02 Nov 2021 23:28:16 -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=VrJ07b06nc9KbJLXSj5zehnLehuxuLDRP/US8C6hfE0=; b=ZAVnIZTP+LHKUx7NfjJFSSU8Rs4NWQlt+WSmFir11XcrpVf8vIvANzLB94WHJ6Bf60 k5sOQZOlmPiZcIyPnZc5h1IMa4HEIbaZcPfZylu7pLpRq3Wo7z+BnTX0y7I5wYkCFuoG +eGMgfwCzcXcJHpSeGXyJ+tSsUCHmpwt6ur6pHCiVAdNfjEHT3yYhu+lsxVQ5D2V2KIC qvaK+4T5DbMnZpK3Z7YkucwN2EtSX/SR0NY/oCqRV2gxlQCjWzPRe4HiWqu2PEQkt71B aKqnarAD6+0QHqmgo1zo2USfPJbv7FQerLfy1iC4jnm1iC7S985cSaZMnGyUSznXz1F/ su2g== 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=VrJ07b06nc9KbJLXSj5zehnLehuxuLDRP/US8C6hfE0=; b=Vjd0I4Etrt+LuFd2OepD3HG4eCXIu0iagiaLVN7jE23V000rYHWebZndSImHD8336E Eby/aj5MthU2GsBOczOoPjShGfQaC/1kp6xCW4pzF5vM64+aE4yoYH02QuPrtsDzOc39 bGssFlwiyADEGByBtrQ+srdlhGuNMbdq2EYAYL72wl3FyBTOrI8PbnqsQbIx1NiPJgTk RXxtQQiFaagLcQtLmC7GvWDhFOMSJgGpsYEOn3itN7Orgsrlr3RgLwdCVwu+IC12TqLu SRjUs3FOs3Cn0fb5kT5jnoS1M4nntEaHeQDXdkccUDLQId5ZKLpzV+KmclyEw1jZ5Mhv FfKQ== X-Gm-Message-State: AOAM532QoQ1PKVH8mroO20RjcslCQhBcvokfYospWgttU19mZ10JMoDt 6YN+1+Zcn4Cuu771bxX6AAsjsAUFAFY= X-Google-Smtp-Source: ABdhPJynSsKsRymAV6oD+adfOhHtjHV5sbxdoRvZmrjUVSSHvV6cZcysjNYwYVj1A9HptlBdbRlQUwIXynU= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a25:5d08:: with SMTP id r8mr43342773ybb.227.1635920896128; Tue, 02 Nov 2021 23:28:16 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:05 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-14-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 13/28] KVM: arm64: Make ID_DFR1_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_DFR1_EL1 to make it writable by userspace. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 8abd3f6fd667..f04067fdaa85 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -835,6 +835,11 @@ static struct id_reg_info id_dfr0_el1_info = { .get_reset_val = get_reset_id_dfr0_el1, }; +static struct id_reg_info id_dfr1_el1_info = { + .sys_reg = SYS_ID_DFR1_EL1, + .ftr_check_types = S_FCT(ID_DFR1_MTPMU_SHIFT, FCT_LOWER_SAFE), +}; + /* * 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. @@ -845,6 +850,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_ID_DFR1_EL1)] = &id_dfr1_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 Wed Nov 3 06:25:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600209 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 DFFF4C433FE for ; Wed, 3 Nov 2021 06:28:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C0C2961177 for ; Wed, 3 Nov 2021 06:28:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231993AbhKCGa4 (ORCPT ); Wed, 3 Nov 2021 02:30:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231979AbhKCGax (ORCPT ); Wed, 3 Nov 2021 02:30:53 -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 2DC55C061203 for ; Tue, 2 Nov 2021 23:28:18 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id nv1-20020a17090b1b4100b001a04861d474so504636pjb.5 for ; Tue, 02 Nov 2021 23:28:18 -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=Esyigd24VZzPo59EpEVlVJ1Fgs9fgw4MXQuf865VkCM=; b=F+nZxkxoiWIyyns/e6YvCovwVFgHwrPCf4W/omxTTZKZxPeieOLU5DGarIx6iQBnRA AwDOAjRjA/RTb348aoIOxmxsGOLFGENIy+5whxqZNRq2weovTQtDpvjwDDS/X/bVB5Oc 3Hksfyo6u3r8/r+WY1rwl3twBXaLZL30HbuxcePUi7SummLqW7NN8HBHD562Q92RPCB8 IYHOfGZtQruMMArAwh5rkXIi6EftMSA9wzKz2yuC9O/WL/hANK5OkQecfL7Yf7PH4cld rUB0NfkdHf/CKIXzlxHKTBdEQoiAN6AGqNtwOmqQ1pzZzKBCXDxuE5wGgmn1Fd2VVxyD oggw== 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=Esyigd24VZzPo59EpEVlVJ1Fgs9fgw4MXQuf865VkCM=; b=cw2W57ja9aahX7+eZr/vwNIXkiglIia+AZ19VS5nJ1XEV2MiLbiK0t+UANlxfSvUi9 aA7b1SW/FFW2K22c0PN1YDSWOHc75n4VvELBomeW6ybQ1iP5A0LZm6WNWvslcISgBEef wezO/ZSxyUiuHCjVMaxIAXPbVkw0GIm3C6HFqW9Fl0HTUEk+1M9oMX9oeI9HN2gS0Tm5 vC+MbVH0K29U4sO0Oha4PW7PRogLC08LIlBOYsf90mFfpK36j4LLdGL5Los/rRC35Rtl bf6XLvVB9w56yVZPTLTamLSuliTOUTA+hSvF74JR2KOzbWDRZxQW+OuhOLQHugFvrlI+ wTpA== X-Gm-Message-State: AOAM533pmA2JVGacq/DlpZqOu3M/AHeALUiCBGw9xfX5XoN3Y3ozZwxs pkqlvM4KME/foytJ+hKy3S2AwPzld7w= X-Google-Smtp-Source: ABdhPJy8zAxunqRArXzuJB5aGkOf3dPMAfmrH4e8aF0KnNXPQWSWpgHh4j0Xv7zu5BhBikqibRcVNu8SQBM= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6a00:244d:b0:44d:c279:5155 with SMTP id d13-20020a056a00244d00b0044dc2795155mr41787826pfj.0.1635920897698; Tue, 02 Nov 2021 23:28:17 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:06 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-15-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 14/28] KVM: arm64: Make ID_MMFR0_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_MMFR0_EL1 to make it writable by userspace. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index f04067fdaa85..cfa3624ee081 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -840,6 +840,12 @@ static struct id_reg_info id_dfr1_el1_info = { .ftr_check_types = S_FCT(ID_DFR1_MTPMU_SHIFT, FCT_LOWER_SAFE), }; +static struct id_reg_info id_mmfr0_el1_info = { + .sys_reg = SYS_ID_MMFR0_EL1, + .ftr_check_types = S_FCT(ID_MMFR0_INNERSHR_SHIFT, FCT_LOWER_SAFE) | + S_FCT(ID_MMFR0_OUTERSHR_SHIFT, FCT_LOWER_SAFE), +}; + /* * 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. @@ -850,6 +856,7 @@ static struct id_reg_info id_dfr1_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_MMFR0_EL1)] = &id_mmfr0_el1_info, [IDREG_IDX(SYS_ID_DFR1_EL1)] = &id_dfr1_el1_info, [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, From patchwork Wed Nov 3 06:25:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600211 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 2C89CC433EF for ; Wed, 3 Nov 2021 06:28:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 147D761177 for ; Wed, 3 Nov 2021 06:28:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231987AbhKCGa6 (ORCPT ); Wed, 3 Nov 2021 02:30:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231961AbhKCGaz (ORCPT ); Wed, 3 Nov 2021 02:30:55 -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 E4B8AC061714 for ; Tue, 2 Nov 2021 23:28:19 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id x25-20020aa79199000000b0044caf0d1ba8so857841pfa.1 for ; Tue, 02 Nov 2021 23:28:19 -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=23B18KCm6Ef3G7/a/geAU0JJefv7D3zT1xrTavh52uo=; b=TJOFxqE5MKgPy2BU7Sw3QhOpxRNeKudKuKKjMFP3BxR4yJKXV8O2GszJPdJTLi914P 3EWI/MTTzLwFoyVxXun5bBW7w7PjeHiXcT/pOhLcMtKZ3Y/vFU176tZ+yj+mmZg4N4KP 1HZ55D9w2iPe0tawLlbshFprqWovMHF+a/i7ubcg966vwylt5un5aydqLaKKfcfKfYvD 42K9dSyaMigT3QRT+Kf8hG0iHhZwIWNwP+SEbcbQ6ABkJZOEK1rpqEtklhSuteaYdMXI Wk11L8P8IC9oVFXJ/zcnmiMKqrRK2XN2+qJtrycqxmeXbPofqNkPOvGzBByVFvni9hem N92A== 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=23B18KCm6Ef3G7/a/geAU0JJefv7D3zT1xrTavh52uo=; b=4A6v5+lw8ej2XtjTr73TpkfXd27Ts1aYgz6NrkpT6KyuN6LMU9J3H9Pn3T+Z561F+y jlEzIa4P3Zz/8w++AQwCnxQwCQUHRC5ck6syMtRD4y6CZIXDuJDTgj3EBVTMT2N/ZAR2 w9wkqo8A/z0iyEBQ9aMjEvgzy2/9GFxISiYfCTdiu1oWWuyHL9ZIbIWwvLeqvi2lzwaY 1eiBpt7mBBQuaxKuVCdGJLIZ9mHGA7Mq/msgP1r0PeTcHremZz8iwIZGL6UZmZG/n+YP gcHbj+SkpLrDGB6gk+4A9+2Hs5JJ0xq+c0XNIBZ+QjmP3K482SK0EzXf+RRp5RcD4LLZ Y+gg== X-Gm-Message-State: AOAM533yqTLzBIuxPWhgWrWbdjodbFdmsp3OhIejE0CMaYje+4Qku/eS 01ypQTNYqG9SU9U+RF22DL9wuDeWqKg= X-Google-Smtp-Source: ABdhPJx0JzpdmVa2hGMrf0I8g1N0qU+cSRr0gP5gtA+oqT2tR+iwo2LuP4bq6crb6rDwpf/AuaG6Vsn/aSU= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:6b0c:b0:13f:aaf4:3db4 with SMTP id o12-20020a1709026b0c00b0013faaf43db4mr36190330plk.46.1635920899378; Tue, 02 Nov 2021 23:28:19 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:07 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-16-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 15/28] 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 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index cfa3624ee081..99dc2d622df2 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -675,6 +675,36 @@ static int validate_id_dfr0_el1(struct kvm_vcpu *vcpu, return 0; } +static int validate_mvfr1_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *id_reg, 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 = id_reg->vcpu_limit_val; @@ -846,6 +876,11 @@ static struct id_reg_info id_mmfr0_el1_info = { S_FCT(ID_MMFR0_OUTERSHR_SHIFT, FCT_LOWER_SAFE), }; +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. @@ -857,6 +892,7 @@ static struct id_reg_info id_mmfr0_el1_info = { 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_MMFR0_EL1)] = &id_mmfr0_el1_info, + [IDREG_IDX(SYS_MVFR1_EL1)] = &mvfr1_el1_info, [IDREG_IDX(SYS_ID_DFR1_EL1)] = &id_dfr1_el1_info, [IDREG_IDX(SYS_ID_AA64PFR0_EL1)] = &id_aa64pfr0_el1_info, [IDREG_IDX(SYS_ID_AA64PFR1_EL1)] = &id_aa64pfr1_el1_info, From patchwork Wed Nov 3 06:25:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600213 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 38569C433F5 for ; Wed, 3 Nov 2021 06:28:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1B6AC6115B for ; Wed, 3 Nov 2021 06:28:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232012AbhKCGbA (ORCPT ); Wed, 3 Nov 2021 02:31:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232013AbhKCGa5 (ORCPT ); Wed, 3 Nov 2021 02:30:57 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5D62C061220 for ; Tue, 2 Nov 2021 23:28:21 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id e10-20020a17090301ca00b00141fbe2569dso649155plh.14 for ; Tue, 02 Nov 2021 23:28:21 -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=kNjTPzP2KLdpBZioWjSqQb8109nySN2BIgqc7hOB6qs=; b=AfpsRAPpSTvALsHZ0QnP5jU02J0/Z3dgKDvHgH5nClQw7JMedG9qWr0ZRMiobPmrAW 0r+PYxsUEkUxjdxdJ6L556u0HVB/Zl5mq3QRWFXm8rgjLc7HTzh6VdKeU9MIgcZ/Zxml PVVe76BxFjMMsUwIcgVTvNqdrFG4LofekmP+iY8Ruvwdxe8ypsLG4ek6srsQcCs5DP3w uqjbxPp4oBvGERNCrd0lHsSx0gGRU628gRGZTlTuXm9EXjCnbiD4Qq9v2d72PNRiW/av S+s/UKR+NFVCAFmIm4FpXxK3gWC2freG//KY5OB1zKprirGGzArEsbaC69f7EAmeZg8i STFA== 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=kNjTPzP2KLdpBZioWjSqQb8109nySN2BIgqc7hOB6qs=; b=zfnHY8QrIF7ssBy1oYBGzdCCqT6ROArfTkq/A/V6sNjGajaWSbxCS912n7wlPntP1w t3Da35P7VSsQEwmjNkJGUXouuy4W0YOXF2V9Jiyt8+xQKwcmMOzDt7ZlohLCNQMOiEBj JEp/XIXNIR/cVCussCUGkDmrrqghLoeBZNz87VHdMc9q+Glu9Higs1Em5Fko9LMKnNLK 3d29IzektHIxF1/j1jKIajh4D5iAx3O/oPrIpJGGJs2/+vYinuv6KV3uLAwal4F8thDu rHILKrlGLNX1T+DxqkH3dvYBAR4hIJ8PPSVXoF8CHXmTGol1gtaXBtM24V607Nm9P6vb 1OMQ== X-Gm-Message-State: AOAM531YxfWbx2WyLBnLml7pXZOqFzHDyNZfMbdgWhVW4yyqnqU1h1Mc 0748bb3hBb3sh1MV/cyCBtr0h9cTBz0= X-Google-Smtp-Source: ABdhPJzPkyz8U9fHsTJuHQswL3KaxgisjjocgibWzmnaPNs/FZMpFacvIrZvfkYMZMGH+/n999KUp7HLIcw= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90a:a503:: with SMTP id a3mr12433259pjq.122.1635920901217; Tue, 02 Nov 2021 23:28:21 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:08 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-17-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 16/28] 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 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 99dc2d622df2..1b4ffbf539a7 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1836,16 +1836,12 @@ 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) - return 0; + return (val == 0) ? 0 : -EINVAL; err = validate_id_reg(vcpu, rd, val); if (err) From patchwork Wed Nov 3 06:25:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600215 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 29635C433FE for ; Wed, 3 Nov 2021 06:28:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1033D61166 for ; Wed, 3 Nov 2021 06:28:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231968AbhKCGbG (ORCPT ); Wed, 3 Nov 2021 02:31:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231970AbhKCGa7 (ORCPT ); Wed, 3 Nov 2021 02:30:59 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C659C061203 for ; Tue, 2 Nov 2021 23:28:23 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id v18-20020a170902e8d200b00141df2da949so664180plg.10 for ; Tue, 02 Nov 2021 23:28: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=C5yQ8yOodLMSFDUkZwymSW+rTndotw8MH+3y9C4rprM=; b=hp7Gve4yuw1Lb8fSnMTaCb1v3CrKrMIh7lOFjpQry051BYkVMJaPcmD5uXfn45bS99 ZfaZECLNPlxL6/G7mCWP2IQj+t+BiUvS7Y7/Z2vYzVGt3DqYNwOYUBfkXKPDS8se+vCE P8IXmSxPCdU/4Ch2lQfLHZFO7HOHGCK1CugfdIJmPs6PHVY6iFHCVkpYM+bN0LndC4I9 afP3BcZs/dkMnywcE0AMdAexTLcKeYGnFwwONqJ2q0CEonVmiplrXkDstgRS7mQAYPxS Q7OrAUNx5N0A8diXaGEFBUnCEl3GaFjNaJkUU1QjXmldNtoXQxMdbvwO/mZWSKOS8Exb tEBw== 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=C5yQ8yOodLMSFDUkZwymSW+rTndotw8MH+3y9C4rprM=; b=fKrYSOSuKUbeUV0FGpjJ1W5OoDtGZ4ggwQKCCQd5B1RjMVpAV9UmYSumzftKzb0Y/j 2aSlM5IFXueBfWY9RPBOv5yNOeaj1dCXIMwWPfrDkwgiTo8/92PxY36mzqNCvNkTI7bu 5u3CMUPiE5aERMRJI5Qaah0l7ashO8+GM4dIk7pgGMVTfav3LfV4POG8fNN+xrA84Glf 8dPzUUqoZ/d1KyZCcxxxvKfGI74G0LRuy3FuMNpuFf8JaAR6G8I1/ae8OrnxKictd9E4 zo3kpReXbok4GFNJIVpaB2pGZA5qck5rT6GUiWQmX1M/EI0FAUyzm5b+y8V8G/Cg51MG /2CA== X-Gm-Message-State: AOAM533HYsODzuX5ZBy4t6TGAsf+yvPFAHHcg1Pf9C7YodBXSEOSgXPD pGOTNVPaFB9T1tpBN8b/c3myZQpr2SI= X-Google-Smtp-Source: ABdhPJxcks24XT7LWQqlv4ZZTDZSBB0irMiSAQnwrrX8h6gSYkanjyBTWa61E3/HPOvc7PD9rNXtBIcbNp4= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:9b8a:b0:13f:c286:a060 with SMTP id y10-20020a1709029b8a00b0013fc286a060mr36314809plp.66.1635920903036; Tue, 02 Nov 2021 23:28:23 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:09 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-18-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 17/28] 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 | 121 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 1b4ffbf539a7..ec984fd4e319 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -817,9 +817,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, - .ftr_check_types = U_FCT(ID_AA64PFR1_RASFRAC_SHIFT, FCT_IGNORE) | - U_FCT(ID_AA64PFR1_MPAMFRAC_SHIFT, FCT_IGNORE) | - U_FCT(ID_AA64PFR1_CSV2FRAC_SHIFT, FCT_IGNORE), .init = init_id_aa64pfr1_el1_info, .validate = validate_id_aa64pfr1_el1, .get_reset_val = get_reset_id_aa64pfr1_el1, @@ -3407,10 +3404,86 @@ 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 id; + u32 shift; + u32 frac_id; + u32 frac_shift; + u8 frac_ftr_check; +}; + +static struct feature_frac feature_frac_table[] = { + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_shift = ID_AA64PFR1_RASFRAC_SHIFT, + .id = SYS_ID_AA64PFR0_EL1, + .shift = ID_AA64PFR0_RAS_SHIFT, + }, + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_shift = ID_AA64PFR1_MPAMFRAC_SHIFT, + .id = SYS_ID_AA64PFR0_EL1, + .shift = ID_AA64PFR0_MPAM_SHIFT, + }, + { + .frac_id = SYS_ID_AA64PFR1_EL1, + .frac_shift = ID_AA64PFR1_CSV2FRAC_SHIFT, + .id = SYS_ID_AA64PFR0_EL1, + .shift = ID_AA64PFR0_CSV2_SHIFT, + }, +}; + +/* + * Return non-zero if the feature/fractional fields pair are not + * supported. Return zero otherwise. + * This function only checks fractional feature field and assumes + * the feature field is valid. + */ +static int vcpu_id_reg_feature_frac_check(const struct kvm_vcpu *vcpu, + const struct feature_frac *ftr_frac) +{ + u32 id; + int fval, flim, ret; + u64 val, lim, mask; + const struct id_reg_info *id_reg; + bool sign = FCT_SIGN(ftr_frac->frac_ftr_check); + enum feature_check_type type = FCT_TYPE(ftr_frac->frac_ftr_check); + + /* Check if the feature field value is same as the limit */ + id = ftr_frac->id; + id_reg = GET_ID_REG_INFO(id); + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); + lim = id_reg ? id_reg->vcpu_limit_val : read_sanitised_ftr_reg(id); + + mask = (u64)ARM64_FEATURE_FIELD_MASK << ftr_frac->shift; + if ((val & mask) != (lim & mask)) + /* + * The feature level is smaller than the limit. + * Any fractional version should be fine. + */ + return 0; + + /* Check the fractional feature field */ + id = ftr_frac->frac_id; + id_reg = GET_ID_REG_INFO(id); + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); + fval = cpuid_feature_extract_field(val, ftr_frac->frac_shift, sign); + + lim = id_reg ? id_reg->vcpu_limit_val : read_sanitised_ftr_reg(id); + flim = cpuid_feature_extract_field(lim, ftr_frac->frac_shift, sign); + + ret = arm64_check_feature_one(type, fval, flim); + return ret ? -E2BIG : 0; +} + 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 @@ -3431,6 +3504,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 + * at KVM_SET_ONE_REG. + */ + 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; } @@ -3438,6 +3522,9 @@ static void id_reg_info_init_all(void) { int i; struct id_reg_info *id_reg; + struct feature_frac *frac; + u64 mask = ARM64_FEATURE_FIELD_MASK; + u64 org; for (i = 0; i < ARRAY_SIZE(id_reg_info_table); i++) { id_reg = (struct id_reg_info *)id_reg_info_table[i]; @@ -3446,6 +3533,32 @@ static void id_reg_info_init_all(void) id_reg_info_init(id_reg); } + + for (i = 0; i < ARRAY_SIZE(feature_frac_table); i++) { + frac = &feature_frac_table[i]; + id_reg = GET_ID_REG_INFO(frac->frac_id); + + /* + * An ID register that has fractional fields is expected + * to have its own id_reg_info. + */ + if (WARN_ON_ONCE(!id_reg)) + continue; + + /* + * Update the id_reg's ftr_check_types for the fractional + * field with FCT_IGNORE so that the field won't be validated + * when the ID register is set by userspace, which could + * temporarily cause an inconsistency if its (main) feature + * field is not set yet. Save the original ftr_check_types + * for the fractional field to validate the field later. + */ + org = (id_reg->ftr_check_types >> frac->frac_shift) & mask; + id_reg->ftr_check_types &= ~(mask << frac->frac_shift); + id_reg->ftr_check_types |= + MAKE_FCT(frac->frac_shift, FCT_IGNORE, FCT_SIGN(org)); + frac->frac_ftr_check = org; + } } void kvm_sys_reg_table_init(void) From patchwork Wed Nov 3 06:25:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12600217 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 1CBD9C4332F for ; Wed, 3 Nov 2021 06:28:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0432861166 for ; Wed, 3 Nov 2021 06:28:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231974AbhKCGbG (ORCPT ); Wed, 3 Nov 2021 02:31:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232005AbhKCGbA (ORCPT ); Wed, 3 Nov 2021 02:31:00 -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 06B81C06120C for ; Tue, 2 Nov 2021 23:28:25 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id t62-20020a625f41000000b004807e0ed462so807732pfb.22 for ; Tue, 02 Nov 2021 23:28: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=LPEo6E0odusyrNggBByLPHmUhPl/zAKGlEQeNEdskuA=; b=bUNM+pxcYjjNldjizqCPZrdfmrJ570sn9wZ2+V56DnjdvPvtesjhdX/PSW+VQDoFfO 4yc25e1h0xFAlZIhbOGpVQZrhoK267T/BxRH6QH3HLqV/1XTLHt0bmLoDFG2mBLwR2n5 4qjERrwJ999xwEgl++TYoXgA9t9wDvO8RsuGQMJaJ5XEvCaVXN3vs4Fn3idvHHMy8lzJ eIuynnNTqqXtqERgV/dwYp/hbLg3cZOLT2Hz/eodY1pJ69D1yTMVzvEJPhuK+3Cgtg/n 7U3CmnMjBBgBG4VlAeldkwlh/C5NaaZXwcCDPKbztqhLXOUTFjDOyPzZXSoH329hztzx 1ZYg== 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=LPEo6E0odusyrNggBByLPHmUhPl/zAKGlEQeNEdskuA=; b=mEaTqPfjqs+GCfFm5jt0ySpuRTJg+pdxez9xZiEk8Ax6zWy8cm2DKaAAdQg4sx58Es 8KxG0URzqwya6SQY/mso+BfNSfSqCR+a/JK/Y1ihdoyuwdmJQ+D98zKPPVvHIKSy0wiz GNRN4Tain6X//ORdOAozPLZZqO7ev5CkxvtrGG+D3hj/izT7eCuje/VwSIS9LvQi+/tp HyFbovmBP6nMfS+5AU+6YyvNA38zVaSLMCc6sct7vU1k53fYe5ViUaJW4yc9eD7fVrWj 1eTAGyd6QRLCKxTbGCHSjqDsC8IMMRF9NOmS2M4YkW2/w0Jh2DUoE/V8p7NO07EmBehm geFA== X-Gm-Message-State: AOAM530tuBZCtcYk1rNLZvnb6r7zamHRjTk/eoxctxtiDmIDHEmQA6j9 iOI8mmT7S3q0SaFVPkCds4w80e5Ianc= X-Google-Smtp-Source: ABdhPJxPQlTZgemwz/ej9COOHQof1/L/+yDn2lMn62bmlzOf2+lYhTzbKkH4dxYFVrp4EA9bFyTluvTF1D0= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a62:1904:0:b0:480:816c:1d3e with SMTP id 4-20020a621904000000b00480816c1d3emr27606490pfz.83.1635920904536; Tue, 02 Nov 2021 23:28:24 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:10 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-19-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 18/28] 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 528058920b64..87b8432f5719 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 Wed Nov 3 06:25: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: 12600219 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 9BA67C433F5 for ; Wed, 3 Nov 2021 06:28:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7AE0E611AE for ; Wed, 3 Nov 2021 06:28:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232024AbhKCGbN (ORCPT ); Wed, 3 Nov 2021 02:31:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32954 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232057AbhKCGbD (ORCPT ); Wed, 3 Nov 2021 02:31:03 -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 D06CDC061220 for ; Tue, 2 Nov 2021 23:28:26 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id y125-20020a25dc83000000b005c2326bf744so2633444ybe.21 for ; Tue, 02 Nov 2021 23:28: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=IlnnjjxcxTrjMcB8yaJXHdEazmlLXcchfy7IakmUdZE=; b=lEBh0vzvOlg1yr5SMNuPf3yBIYSLDFvr1+EhJDIadybQX+1BavYADneMp+UbZDfKsT tDPsBoGaE4kyOUe/JIe67Ksbi+weqOPFfbtyfHVxSYKGdGcksQlY3dnWhQYd1hiGjHPG QihaOhYE+Yo95wwBLm4eNb7CZ5VFRYkk3X49wCCgsrP/AZ3nrKt+4OyMd5xoaYtofZNB ajFywJ1SApAGz1A7JqrmSMnA6QwV1OMcmtLp8YIo3m/HnGubXt2oFhz+uRsKghNKaL/Y vuhuosSxAuArRsnX6D/7btRUWlFtcQRaD2wrvvrZCNg6KmjmQaR0AxIBHlUiPshtz796 xj8A== 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=IlnnjjxcxTrjMcB8yaJXHdEazmlLXcchfy7IakmUdZE=; b=0yebLUP3D8EY2toutAnV6gYbF2v+ehrnOBmq78RcTOZqdTYqwsvPKw6amP6czcR0pi pOzG2Qqkw4f0l001QTJTdJwfX4ChtLMuEDsjqVu5Be6DPuEwSYsh/WLl6HKsfDxOQrZd 4jsLyS4M4VctAODhDVmBMnl0dbjTMWp3ycP5+OsHwuZ4SWh+ZVZjUyzPiYUZ1E8303QD XN6XbW+tg1UpJ8qXyPnUceBl9RxqZg4z5wS2B55iryAMbfY6iu2ZaBIr8ZRsxgBxTU8n gOflgKYq1HCgd/Ee6BLXm/kDvYw3GiAJ4/ityMQUEvKTvF9gteNKRg0uCHvwCfw/IKnl 5f3w== X-Gm-Message-State: AOAM533rhfZMHMieAI4Ig2szyHQYzDOe826lbGFt3FHBaYdIsDWQ4VTa xjzG3h0yBnRDKABb3fKXKXxVieGWrVg= X-Google-Smtp-Source: ABdhPJxgJ+HzJWMr3mZLEymaTOFsSPvpEYoeWmz+ySBuR2iPwDl/R17Ye21Yh4kCJ8QQZzyP3Hjs7R3utuo= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a05:6902:114c:: with SMTP id p12mr51484992ybu.408.1635920906196; Tue, 02 Nov 2021 23:28:26 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:11 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-20-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 19/28] 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 87b8432f5719..37e1e07a19eb 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1109,7 +1109,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 Wed Nov 3 06:25: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: 12600221 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 7D222C433EF for ; Wed, 3 Nov 2021 06:28:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 65FC46117A for ; Wed, 3 Nov 2021 06:28:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231542AbhKCGbO (ORCPT ); Wed, 3 Nov 2021 02:31:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232046AbhKCGbE (ORCPT ); Wed, 3 Nov 2021 02:31:04 -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 50BB3C061227 for ; Tue, 2 Nov 2021 23:28:28 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id m26-20020a62a21a000000b0041361973ba7so821931pff.15 for ; Tue, 02 Nov 2021 23:28: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=EdHJWCMm4NV+zJRBLh5gcwFmb5wMlFeWAuDD1adtoYc=; b=HSIF6NAUdvPrgANSGhYIWgwF1jUyd5ydPLTE79DZ9GKwqdi036Iq+H7of25JO5e6QO umAl6yAgnerVr6PWB6ELJ4/bNlbhFTPmq+769yQkggLo2BDo4rY4IcgwqzPw5hx0OgWo V3iAXr6tcodFhfG1PFdOabRJ4EXdUoj/4ooYpZnAFCRHQ1XioG7JGWBmnWlF0N6JYooe h9IwcEfMH8qHkHGXf4DHyysQEvkHDkbVKvlQ7nXFWVIA9IXR2Ckbl99aKRXB2z6ASgBy WmOSDDwfDj9BFFVvgyAtiRUFgkjGfi8VjzYnUYx22kef6omdekETv0DAvl8JL0KQT3w5 hctA== 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=EdHJWCMm4NV+zJRBLh5gcwFmb5wMlFeWAuDD1adtoYc=; b=YteCAltsLXiF5T7liSHbBGN35kNMlowrcRPrklydFuCTPEUgc1br7luEHzZ1DtRXyA XWqg7h+luNZpQ1dzT+rORScBRd8akOtpjZXHzOloqZZbqgVEK037Z+M2vifuQX8y3Nud doL69q4tHlf12rOaHvox/tcWFfNe+yciYoe9eLVJAQZOA5IAAE8FjNmWHtojjJq4q7gh Tw3XiNJEbPxvSCWLQOCnJZYbqT39pRNqHZe8xKZDMkff0vm03N0+VNIxkTPSlSS8WP3i yitco3sMfkdAmYtH6RWLuhA68LEYPKeEycjQtlWWipGK5WPQT1tw6EPVuChLgDEV8+mS uiIQ== X-Gm-Message-State: AOAM531T90r1r9R9I/Wbr/i44nwldIsBWOc3eNm63AUHRoOLKEQh6sWu dZJ4HZRvIVgkd3LQ0ApAhjBzrgPUEiQ= X-Google-Smtp-Source: ABdhPJy425WLxwtQdf0ugi+KRB/vHRkkXwn77RmTJo/tV5q3EUWFYunH8uYLN9iDLTTqEDRgvoHtud2mw8I= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:aa7:848a:0:b0:47f:d648:2df4 with SMTP id u10-20020aa7848a000000b0047fd6482df4mr30111827pfn.63.1635920907782; Tue, 02 Nov 2021 23:28:27 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:12 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-21-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 20/28] 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 37e1e07a19eb..afc49d2faa9a 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1109,6 +1109,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 Wed Nov 3 06:25: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: 12600237 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 E7346C4332F for ; Wed, 3 Nov 2021 06:28:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D4F5160240 for ; Wed, 3 Nov 2021 06:28:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232066AbhKCGb0 (ORCPT ); Wed, 3 Nov 2021 02:31:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231960AbhKCGbG (ORCPT ); Wed, 3 Nov 2021 02:31:06 -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 467EAC061714 for ; Tue, 2 Nov 2021 23:28:30 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id t24-20020a252d18000000b005c225ae9e16so2707039ybt.15 for ; Tue, 02 Nov 2021 23:28: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=1lfGW3uUgr0CY8K4JFTRsimFp+SzJHY9CklAaedGo2Y=; b=dgJhd+anU5DKo0ONOMzDKNE6v++uX3EutjlLi0DF0IBxu8EIpJbKZAmnyMCqM+9n/u /W+zFwLfODB4FQSatwb6maKrJl4LTaQD6G69c92UEMNlrJL2ZuIhL/tCOiefnP46XGzv qtj7trpqD7yk2tzPZm4PqrW45VUdPoyAJztmw7rND2Fm4Me9TEj/1VrH39xJrHj39xPm J36BktdLXaNNipzmQmrEGhSXCCUJqFNk11sVmdxf0LKxZCiYocE3pzbqt+GSIqYH4eIf aUa9weuyfvgS7c9SD6RWM/rYu8esqEKaJelpblOjoXciFtcmHz6FOGdQltyOlUeFf1Xg l4wg== 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=1lfGW3uUgr0CY8K4JFTRsimFp+SzJHY9CklAaedGo2Y=; b=fndcq/u6zqmcBr52MDk8bsrsilMr4Ie+fu2gWZFu2fEaYURbQbpIiws4p2SWoLdwvf XiHdj8dYJ72PE42UdbwR7Bt8e27+VHfrIRfWGRig/SWsMqVAeXATZbixHEWwm3V08roD E1sFCO80R/2DOQv0ndnAqc5OT8RHSlTOg8a8A+Q33nd29kCXDLWslPOCPPVGAHpGAojn HIgkl7LeQ+OEwR0vaG6cDkMuEVL2IWio9KCTePFSysROWYSlq63KO5+f16w/WFX4NF5f LuwajzarofyweEEdDkNq2mSp/ZoClIp4mntUfWZvL88oekjhm8djNtYueEIh/IOabjFR temQ== X-Gm-Message-State: AOAM5339Y761O3Tpw8aE3ANWNWFH8iyd2G/7DKCEryNTm7zXlkiChPqh EPeMb8yk3MwV8bp2BNR3q+jr5seDuwY= X-Google-Smtp-Source: ABdhPJzvRlzhHgCrOc1A3vUiZK4QFvFi8eSsp2hkt/8T54a+0Czu4C02OOJz24SVVzhytf8yVh6SIQeMn1Y= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a25:74c8:: with SMTP id p191mr35575047ybc.157.1635920909508; Tue, 02 Nov 2021 23:28:29 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:13 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-22-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 21/28] 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 | 121 +++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index ec984fd4e319..504e1ff86848 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -374,8 +374,38 @@ static int arm64_check_features(u64 check_types, u64 val, u64 lim) (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 */ /* * Limit value of the register for a vcpu. The value is the sanitized @@ -408,11 +438,15 @@ struct id_reg_info { /* Return the reset value of the register for the vCPU */ u64 (*get_reset_val)(struct kvm_vcpu *vcpu, const 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) { - id_reg->vcpu_limit_val = read_sanitised_ftr_reg(id_reg->sys_reg); + id_reg->sys_val = read_sanitised_ftr_reg(id_reg->sys_reg); + id_reg->vcpu_limit_val = id_reg->sys_val; if (id_reg->init) id_reg->init(id_reg); } @@ -928,6 +962,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 @@ -1781,6 +1856,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) @@ -3404,6 +3515,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 id; From patchwork Wed Nov 3 06:25: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: 12600235 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 21FDEC433F5 for ; Wed, 3 Nov 2021 06:28:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0B34D60240 for ; Wed, 3 Nov 2021 06:28:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232027AbhKCGbZ (ORCPT ); Wed, 3 Nov 2021 02:31:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232000AbhKCGbH (ORCPT ); Wed, 3 Nov 2021 02:31:07 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 902F5C06120B for ; Tue, 2 Nov 2021 23:28:31 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id w4-20020a1709029a8400b00138e222b06aso655548plp.12 for ; Tue, 02 Nov 2021 23:28: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=stxvqpS43GKPlFzuxNRd3Kw5X/pb/WSIMK3gN777H7I=; b=IHQDLDOYeY7XgsxKhEsFtXdkfK0mb0dBJWK6OuGaazo3Fodx/+jp4nrjFwRFVhyf8Q WR5kQW/dlUUPyoN4Csr/tkwoR4oeMQFo4PU+ByF5vABq5NYxNtsU9XzLKHlFVCxmX0dk yCleWxaFhOu04rzcLR+dHqVTHnSA0BjtHB8ePBqvn0h7+juHuxd50058AWol7qNsbdzA SLNYI4gL1xpNByWHOuyijeCltzuSHRy46GyVjmnAPwTjnAnxiY8+yForLk4w5vzN780E sR9Jqel9nyYzQyKNO36FT/oNO9q2IBIG5degiaLbnrU07lZn6gHFLZFihfGRbBufIsYe 8rrw== 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=stxvqpS43GKPlFzuxNRd3Kw5X/pb/WSIMK3gN777H7I=; b=X3dDi4WFJcnR3U48G1pPbThIwkSMXhTUj1x6xNm3O0ozwjw64goLMB0YiygBubYX0G lJoOa6R9KdwVZdFp19VImdv9j8VgLmnQMHrPp34u6aE6QJFFvLx2+OnATzJc5PWCZYKK LTfdKkyaojEPatkgqKk3y/NA+uWXRqYNdmo5A9Oo3VWYAevw/OZ/v1s6s19/aR6Fomd9 REfNDLqZrhEpJSjfOZoBGSfs383crW2oOfNCHXHpiJejesHMR0pI4Ddz1KZPKQOSS26E 3AQ16VBRMr/LqqL1LRjtoRdOcSixifKlYoMnr/I8B+e1p9P3hVrQvhjsiVzSHAxrNYL5 EIZg== X-Gm-Message-State: AOAM530biSlGiHrOpXDQLfzKYNci66NOzD5PKbITKdRXm99Y+Gqv1K25 JqZfsWBwAmUTwsYY1wuxDvZPaFcFDoc= X-Google-Smtp-Source: ABdhPJwKC5UfgtW/4DN0Ud9DJaQEbXi5o3b0e5aheeOv71jnjTZGp0cYDLSH5/u/wOzSZOUSW+HvFY2qmz0= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:f24a:b0:141:c6fc:2e18 with SMTP id j10-20020a170902f24a00b00141c6fc2e18mr23852030plc.55.1635920911096; Tue, 02 Nov 2021 23:28:31 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:14 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-23-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 22/28] 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 504e1ff86848..99cbfa865864 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -403,6 +403,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 */ @@ -847,6 +868,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 = { @@ -1003,6 +1029,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 @@ -2265,14 +2303,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 Wed Nov 3 06:25: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: 12600223 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 28106C433EF for ; Wed, 3 Nov 2021 06:28:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1008E61175 for ; Wed, 3 Nov 2021 06:28:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232093AbhKCGbR (ORCPT ); Wed, 3 Nov 2021 02:31:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232040AbhKCGbM (ORCPT ); Wed, 3 Nov 2021 02:31:12 -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 DFA63C061224 for ; Tue, 2 Nov 2021 23:28:33 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id a127-20020a627f85000000b0047feae4a8d9so814064pfd.19 for ; Tue, 02 Nov 2021 23:28: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=W1vWCSi6sD57/ju+MVWHrUzS8zlg3LpW8mzLjXGDeDs=; b=rEWlkDyGEepBbZ57FgoY7ltu6LDMAMHAOOx0P/jG/yyYU9fE274fG1o7BMK5p8Jp2e fKv91hIezGvLwOizMBpz+AGj+d7MNMWHzgrQEysT3B7rt4Cp7Hu+m7xk6d2ehFoxHzVf 8ZsFFC+z/yC6oU3DBJCC5pHkNs3qfHXH5hX1KYvrxNfMTfQb5XAKyb1fQNOyJnOzxS0E Ow9wk2a0+f4tCA215T3nAoEa4t5ki9eX3BzTu4su6xHI1ULMqLRc6leSTSVCTDmAW13x zJ7Aej7Nw9Y5mBEo2nNT/L3287ObrbtpP7EDuyzAm/WpYJnwmG2D4adVYA9LvZJp8Dne fUaA== 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=W1vWCSi6sD57/ju+MVWHrUzS8zlg3LpW8mzLjXGDeDs=; b=UU5UJJfYhc5LcFsWXMlRuA5bw2w5YsU1g583OIJLPqPi62eAj/WY3MsNzSOe+OOdZh T3rJqCYnrhRJCaklobaq/aG0oG266YvK5nwVTxk7+ErMfdJT9oksSv28RidIb21HbNIR jm8dtaNvUOIC4P+tXl9fzxRMRwrOUq/RCBOTWmgHSP7trDzuh7lZWraOQkfI+oO7uvvP hXzo2hBGFlhzV/cVnVlMek8eUtxZWLWbuqXU8Mi8Q8IcqXQoFH01lW/t4qtzzwLUB94N heqYz8b4rzs/NhevMavJhDhWFY7icv+issYF1/VECIXPvaD/Fimz4uKZRiMz95gVvNrR wXbw== X-Gm-Message-State: AOAM530Q4ENkYeE4pRx4b1Yk1EY8lprKLkHt0JOrCtAXGsspO1zW76eB YNmipIaZ49XnuP8GcjH2/GY3X7VgrQc= X-Google-Smtp-Source: ABdhPJxpQrRh12VLHNp/Qx/9xMnEFQ2hpQUSo9QzZqIcUPAIyKeeunNcRbGPMB0s9Ps8/EYxlzsFOQYqYNw= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:6bc8:b0:13f:8a54:1188 with SMTP id m8-20020a1709026bc800b0013f8a541188mr35966678plt.49.1635920912830; Tue, 02 Nov 2021 23:28:32 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:15 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-24-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 23/28] 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 99cbfa865864..da6bc87d2d38 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -424,6 +424,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 */ @@ -880,6 +891,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 Wed Nov 3 06:25: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: 12600225 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 F3161C4332F for ; Wed, 3 Nov 2021 06:28:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DB2E761177 for ; Wed, 3 Nov 2021 06:28:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231728AbhKCGbU (ORCPT ); Wed, 3 Nov 2021 02:31:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232051AbhKCGbM (ORCPT ); Wed, 3 Nov 2021 02:31:12 -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 E441FC061225 for ; Tue, 2 Nov 2021 23:28:35 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id 3-20020a620403000000b0044dbf310032so873804pfe.0 for ; Tue, 02 Nov 2021 23:28:35 -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=Hg/kro78g0TD8dT23Op8aR6UZ26HEbXSuTGyujN0oMQ=; b=NWpHbvILfrGgHLj3IALBhGeMx0dFw9T/x+CEZkaF6/ls/KeWRL8OEjI6ueSJgrk37e 0EpvU7aOphG/YeOsfMrsAYRbk2DKnJkafSm+ba7/IF8sUUVB9OYDIpxXyA2m1hfqcALt MixSxIfe2UxmJ5NzHW50IZw/4g8OTtvR7pZOCXmObmcVObu4WU9+i1x5qnqs9lT7aIiH /OzbT/sL03brKXDQKwxxGY5LwYJo5c+hdNqnBaEcX+Yx7DDHrMzKWBI0UyDR9KfCO4BK mTUDrQWhccBy/jRpf08B3lM6ELMcFMGtlikPwk2hv67YChVhUXhXqdzyW8ies0C424eX HWyw== 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=Hg/kro78g0TD8dT23Op8aR6UZ26HEbXSuTGyujN0oMQ=; b=7Vx/LpyGArtKEPccibqX9fZfKrJMnEeYNPzcwRe0kzQe7LsWe9mkvx24MtsfFMdsNZ UbgO/vuQbFEGM63XDPw3eyWiSFZti9JqrKbCXttCskd4mkUZCYzN5NOgcguC6ZmWrqfk w/4jqSMFn9KCLci8bPimscAuhl4/S9qevF9cOSjw7mc7FjNajE5ACsVrIL5/Px8cLPws 83F/N0EQ3t0RBlnGw7AtTLOY/zgfNK90Og6wvqAnV5NyLVZYNZBMPMXYKa/2FndC8/ow 1U+JpY8JsDmljZlOgGDdwfMlux6DVNQxxfrLuaqVhNpHx9Ru+4ACDf3vlzwydGAYY0ha SO8Q== X-Gm-Message-State: AOAM530TkLQljILRYJLYVIdJ47Wy+POkjnPLPDZW+RPtw+ZGiowHJZc+ aztsv8cVpiHZrQYDLwEU4nBgC0uynpg= X-Google-Smtp-Source: ABdhPJykbvGDPOO+pKErSwcFqQxn6Duu2EjZ6XP9dA7WAuHgFBYsENxD6RKzhtb+qlAkqPnymOleI2x7vXE= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:8b8b:b0:13d:e91c:a1b9 with SMTP id ay11-20020a1709028b8b00b0013de91ca1b9mr36970820plb.60.1635920914546; Tue, 02 Nov 2021 23:28:34 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:16 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-25-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 24/28] 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 da6bc87d2d38..67f56ff08e41 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -435,6 +435,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 */ @@ -928,6 +960,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 Wed Nov 3 06:25: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: 12600227 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 9CC51C43217 for ; Wed, 3 Nov 2021 06:28:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 87D0760240 for ; Wed, 3 Nov 2021 06:28:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232054AbhKCGbV (ORCPT ); Wed, 3 Nov 2021 02:31:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232064AbhKCGbM (ORCPT ); Wed, 3 Nov 2021 02:31:12 -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 EBFF8C061227 for ; Tue, 2 Nov 2021 23:28:36 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id n22-20020a6563d6000000b0029261ffde9bso981321pgv.22 for ; Tue, 02 Nov 2021 23:28: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=BX4KfiOrqcyrws1uL0O/L9kuIJ9ad1jF0+cPWSoKuUE=; b=Cq+Ej5Dj1LWD30hdNkPSEz0exbwNZnXqqPulw8Gmqzc7LR4lC1jHqktbHVxfhABplQ R9YrjUB/wF/5c0X663TPQAoEyOgm2s8MaUCPKA//pe+hdhCLIELWB9f+c9MePXEfkwwW S8xGsHcZfNSrlUrYoq6iTdvI/MQQWKbzxBHM6OKfL4DXiEjS+klxjDQ17u8YAMZ4cVP2 eiuRKwsTRikzUj11zQXxroBCJhKZccdC9rinDOvLf0fMqGJuRQcPqsdJ4iIfKBUMsgbH N/tn/NDfYP5FFFbw+eq2fsqG/DGZb//M8atMntiHRDwqK81M/PBJJDc+T+kczg87BNrG wnSw== 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=BX4KfiOrqcyrws1uL0O/L9kuIJ9ad1jF0+cPWSoKuUE=; b=NAubZKSDd/2KAtCYRk+5NPav7nP2siRQTllS3lK8k/xxI5lCAiB9G7/94gWI0bRmUc Cmued+BATEAE0RULs/AmgRr8yBu1Cs19GppAConPcVSZl5Wp5qgqljgljjtNIO4JspSO Ei7xQokuAVS40m/7KlDbB4ceQQkyDW54Yb078lRTwTrqI/ESDI01gSVmjdSpRY90B6XJ P+IT9xOKvCXjKUX3H/yRE1PJmnQuC/YpRNnixDu0p3HKd6cPQgR2BkY9TcslTCjCRg2X wCQmWkV5a7DC/Gt9Gpf7EtHa6C4BY6MSDwD2xg7Gu4khZCopyXUItu4/s2NV4BqqSVyg ElEQ== X-Gm-Message-State: AOAM532ZjTrrggK5eWNb6qPN9iewfQ99FCo0KK9WQim/VMNEMMExfOS3 o8EXWg/zCXAbbS5W450JCktU7/vwOn0= X-Google-Smtp-Source: ABdhPJzuUEYjbQ+VthWhEtBAz70l7/XdAP5N4DRm0ePAhD1+zGjxBUKsgIracOcC41SAcK82UPr9qsMgAzE= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:902:a5c2:b0:140:14bb:8efd with SMTP id t2-20020a170902a5c200b0014014bb8efdmr36677073plq.31.1635920916024; Tue, 02 Nov 2021 23:28:36 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:17 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-26-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 25/28] 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 67f56ff08e41..2d2263abac90 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -467,6 +467,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 */ @@ -968,6 +979,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, @@ -1010,6 +1029,7 @@ static struct id_reg_info *id_reg_info_table[KVM_ARM_ID_REG_MAX_NUM] = { [IDREG_IDX(SYS_ID_AA64ISAR0_EL1)] = &id_aa64isar0_el1_info, [IDREG_IDX(SYS_ID_AA64ISAR1_EL1)] = &id_aa64isar1_el1_info, [IDREG_IDX(SYS_ID_AA64MMFR0_EL1)] = &id_aa64mmfr0_el1_info, + [IDREG_IDX(SYS_ID_AA64MMFR1_EL1)] = &id_aa64mmfr1_el1_info, }; static int validate_id_reg(struct kvm_vcpu *vcpu, @@ -1104,10 +1124,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 Wed Nov 3 06:25: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: 12600233 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 DBB9BC4332F for ; Wed, 3 Nov 2021 06:28:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C735961175 for ; Wed, 3 Nov 2021 06:28:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231955AbhKCGbY (ORCPT ); Wed, 3 Nov 2021 02:31:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231992AbhKCGbN (ORCPT ); Wed, 3 Nov 2021 02:31:13 -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 1D3F1C061203 for ; Tue, 2 Nov 2021 23:28:38 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id p20-20020a63fe14000000b002cc2a31eaf6so1037241pgh.6 for ; Tue, 02 Nov 2021 23:28: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=Ep2NTeFQHRtb1x7tniQeG2pd+DzpIaqpLIGDyxGNaak=; b=fFT02gdqViWYrbCdTEQFZh2dd8gF3sRFDKawTgXYqjLI7nmc2vVWIHc5fQYX9NKzEd OrN0S2OhP0OEbUusgLIOJ24ho/2alYvcos4x7SolFhapIn6YxL0Q/VDzjpdSyamRXq5s RrMyR8gjtsL8vUcd0lgvbJ6rN2iAQkzAgkFYvLsnRwgoEAjFhXUV3qEsGRMH+1yMZEsW 29uITSD/EwfM2NeAOOpPDlb7zlKc6xEPzSf2xyfOc7+pQtJPKZvN+WxtlnnDnD9b2L8D LRn27uaxX+R+rYFbVrWjFF0aBcTVeCPiqJg9ZhuOt107MpCcOF6wgHso+ZYIQoYbVD/j HDkQ== 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=Ep2NTeFQHRtb1x7tniQeG2pd+DzpIaqpLIGDyxGNaak=; b=ERFecq8BvUNgsg/339cBRRLDOnSB65nJbffxk4+afFDeEFG9z3cmECCoFAaSOW9rmX 1yV8M2AmOk19mo/GoAO3U8jNeHsAkqJm9XAP3GWpoTCRubHngSbbN1Ekm3PqcHgz6tly 3kLXQAxhwJFf314SSKH7aLfBcV3EMIVhxidMmHtOVZeSDH1BgrDD78EJhxp7vy+S/ECb ErXrgJVwX87qnQOXGxQCrT4LZU7J1c7jV4iWcc9RoH+5xPuzTL+S8TJXJW3TVQHUZT56 iceCEBF9PnQNjzZH6fLPbKhPI63NUc0AS3bNLkddVOkIX2jbBvJ8uFU1mIbma5TUeLIz orbg== X-Gm-Message-State: AOAM530ez/DiWRrvatdlMfYmChxXXbYVtNnae54xNH2jxnP2xOxMgUe3 WoQ9YL8BAFjiij1/wP+y9O2fp9x4XWs= X-Google-Smtp-Source: ABdhPJxq8mVjnPJ20WpU44gAZn9NtxzZ4+sWrLWZuqNplD2biJyP84pZy1BiGUiTUN9ebm+egsfYYdatDyg= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:903:24c:b0:13f:2377:ef3a with SMTP id j12-20020a170903024c00b0013f2377ef3amr36514167plh.59.1635920917622; Tue, 02 Nov 2021 23:28:37 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:18 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-27-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 26/28] 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 | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2d2263abac90..fd38b3574864 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -374,6 +374,30 @@ static int arm64_check_features(u64 check_types, u64 val, u64 lim) (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; + bool 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)); + generic = aa64isar1_has_gpi(val) || aa64isar1_has_gpa(val); + address = aa64isar1_has_api(val) || aa64isar1_has_apa(val); + 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, @@ -478,6 +502,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 */ @@ -953,6 +985,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_aa64mmfr0_el1_info = { From patchwork Wed Nov 3 06:25: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: 12600231 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 B1642C433FE for ; Wed, 3 Nov 2021 06:28:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9B19F60240 for ; Wed, 3 Nov 2021 06:28:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231979AbhKCGbX (ORCPT ); Wed, 3 Nov 2021 02:31:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232050AbhKCGbP (ORCPT ); Wed, 3 Nov 2021 02:31:15 -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 82ED2C06120C for ; Tue, 2 Nov 2021 23:28:39 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id 84-20020a621457000000b0048080f5764dso826108pfu.13 for ; Tue, 02 Nov 2021 23:28: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=ugTp3pj0zYJHc3RiE+6osaY4VwnihaeWletwlGqcNzU=; b=R3uU4a/mva3/sHp7C4ovXEbTpY7IYU6h/nzYCMUJp+ghGJCGhatLHR1IKqI10LJdsq metLBMGZYNoR04MfVYDKXlUey3kGDSwo0EjdTYks9XJKbommPpi8BgxoxZsCJFWVn+FH suf/FuoQtsLvDHUgsMRQSKYW6N1T76XjKMIT5Nofnr4EqXt5x9/XND18vMR8omRCh86s lmj2LyQP8xjLWfKoCds4tFt8KtCS6W5Xvnfb9Ast3913Gm3/3W7g9o2hEZ70yRhH9PIb d85b0EGtsmqV1k28mIcfQVqisSh3ApCaLI0unMYmbjVQtkJP9vVP6MdUcTHer2id1sPz 46RA== 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=ugTp3pj0zYJHc3RiE+6osaY4VwnihaeWletwlGqcNzU=; b=Tks3IMWu3O0fJmlkfAzW75tTl2znxoBgyVB/9aR6J2zi64AnV2o/Mk+TNwDxqyuWv4 dpDD2vn33yNfUMrHUWGLOf+zkbIAKRiuslLD+GzFD/C3UG/gjHNeF7sr8FOylE3l4TT6 i7M6vNd5IR2fRb3MKsVstwm9ArGy5L/psf8MvlDzTbxltZ0h0K4ci/AhKU6hvyM1V3Df vXQgK6AdMzJxofQOTOK+o2IQp12GFnADWkV8tJyr52bU0AmBFcffgPuVWmAG/YyL7T57 IXN7HDZCB4qrA5ACQj0Fxr9jt19SNl42jgJU/3Rviw4HrghHT0LltNsijEGdty23n+KG Uxgw== X-Gm-Message-State: AOAM533Yo5NAZxQIybdBGl2h0N34pplNT6uQK96vEmjRsBMOSwNBx/vP jwD8Swts5aXggeoiO2x9kChE6Hdn3CY= X-Google-Smtp-Source: ABdhPJxwjlhoTqnj4E9V//tM6ijYmQGHJIKCJ/YZeqcBnm3mpZgLE3LmRBu6b58jjITFPpnfBiYA1pEZdDg= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90a:353:: with SMTP id 19mr12674037pjf.83.1635920918981; Tue, 02 Nov 2021 23:28:38 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:19 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-28-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 27/28] 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 afc49d2faa9a..330a35217987 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -583,6 +583,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) return -EPERM; } + kvm_vcpu_id_regs_trap_activate(vcpu); + kvm_arm_vcpu_init_debug(vcpu); if (likely(irqchip_in_kernel(kvm))) { From patchwork Wed Nov 3 06:25: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: 12600229 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 4D266C433F5 for ; Wed, 3 Nov 2021 06:28:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2D39F6115B for ; Wed, 3 Nov 2021 06:28:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232004AbhKCGbW (ORCPT ); Wed, 3 Nov 2021 02:31:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232079AbhKCGbR (ORCPT ); Wed, 3 Nov 2021 02:31:17 -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 DB283C06120F for ; Tue, 2 Nov 2021 23:28:40 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id nv1-20020a17090b1b4100b001a04861d474so505006pjb.5 for ; Tue, 02 Nov 2021 23:28:40 -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=uGlSnRcaNHymGPv34TB0+rWD5Rk0aLTiMtzuI3iMsCw=; b=bJoyxOCuQMHHRKTMrWPw38QhwQ+KXIXG10feFWlvAWzPGdq/4o7QTgA6CDruIqiLR1 Lc/hFo8ZgMlM5BcJDroMV+LwMtCx2oS+qBt2oIO15+Fpg4Qdxg+29zDaU/1aakuEtD/M 8uvcB+xVmmKTXeV7PfgnEBwJELPHXEvAKVsHQPaAv6Re01mqdjHCs5Fv9Ty5IxE9pdyY c5lZe6kYY+S9IiRuWKGXwufY70+yENEcUrWDBWMSoH++BNtdnl+WSRF2VJ35AKepXg/A JX9IViN9ip5StZOZL8csn3AM9kIbWu0/flVAdyat06G7YjT/Zoef8tNK4Ane4IdSx6yv nR6Q== 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=uGlSnRcaNHymGPv34TB0+rWD5Rk0aLTiMtzuI3iMsCw=; b=tMWf5H0pqqRIHd4Sr2HDbKHZv5OqjHByltD7ybsffAis2ii6Wc1u9FCDOgrqVGvKZL pskSW7AAjLJBKXd6KqHECqsnAjxNGX+34/faGngOxqx0wc7ObPV+gbcrRC5/sf52nUtm gpBnPhvkrfa82Y3tQeIKDHNTMwMGEfElkS+2UBu7YgbJaYVPS7T4/IAAdem3G3YvT6pf 0NXKhmE4IE676ak5CDJOg7ylx7Mdi7VMrlJ6goe3CuN8KCdSV4TuwwQ3dwo6yS0MEHhq AAe3U+Z/rlCz0n3Iebghd2R3iKc0fReFzNaLMkVtmQfUQZtGSXid/b3dlPwpVqmNX3ES KOuw== X-Gm-Message-State: AOAM530ho3ugd7R6bH76aSH0rHrWkXXndlSl7lP4IPpbJEF8mogSuMCh cx2OAg4fQqSjHG30Ik+5O0qKaDaxeeA= X-Google-Smtp-Source: ABdhPJw7+LVkKcBZEx3hr9id4PKqz81Hxyn5OmFF6RfIT/QbrCgH42hHiL4uBhoiDu7A2iWKTJ3SDTLleyg= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a63:790b:: with SMTP id u11mr31096584pgc.71.1635920920412; Tue, 02 Nov 2021 23:28:40 -0700 (PDT) Date: Tue, 2 Nov 2021 23:25:20 -0700 In-Reply-To: <20211103062520.1445832-1-reijiw@google.com> Message-Id: <20211103062520.1445832-29-reijiw@google.com> Mime-Version: 1.0 References: <20211103062520.1445832-1-reijiw@google.com> X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [RFC PATCH v2 28/28] 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; +}