From patchwork Wed Nov 17 06:43:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623815 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 E00C7C433F5 for ; Wed, 17 Nov 2021 06:46:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C56726128B for ; Wed, 17 Nov 2021 06:46:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233856AbhKQGte (ORCPT ); Wed, 17 Nov 2021 01:49:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233035AbhKQGtd (ORCPT ); Wed, 17 Nov 2021 01:49:33 -0500 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 7B739C061570 for ; Tue, 16 Nov 2021 22:46:35 -0800 (PST) Received: by mail-pf1-x449.google.com with SMTP id l8-20020a056a0016c800b0049ffee8cebfso1086616pfc.20 for ; Tue, 16 Nov 2021 22:46:35 -0800 (PST) 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=N8fXLZvqvLp46Vlb4MzkHW+PGd4Y1uV4+vNk1MNsoX0=; b=elNT4EfICJasbMSr/sYT0V1/WkFPMoqyqLRbGmG7zbzGDFT6A4OQRNMQGgcXR0LaSX oLEu/mbv1y3wwz3gKGrHjlgyRVltbe5BnSEaGEUFHNujVkdVYM7yEnqle/1ENDCe59t4 yfQK7K/JOWgUWTTmlLUj+CgQjQgrgQnltIJ9mc065L65W9UDIAtVBzxY/T9FxKVtGU4Z pPabu4FCY5kW58/Np0jr4Pmd1Hg6LcbQkgOzQJShJfb9aqtddBl85imtFziYKFyKIRWj ArwDotwmWfET5LLJ55ke68oyxkVYzKI0hR/rDvAIfOw37WfDwQ5rBxhavWPRQtst24dk XTrw== 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=N8fXLZvqvLp46Vlb4MzkHW+PGd4Y1uV4+vNk1MNsoX0=; b=HHKtYRTL0Frg/aKrTUvFZHI4qKInnGsP0Ef/i5CdHvCgvTd5YM9ffOUdlH6q2dHWON jrKkpFmBwBRkLNu5iXi6VX55tfKmF0R3toFqOoJp8m1EPBTdqFlZ+uF/Sepu2w+9qw3x kEoBLJg3EX1m93+JGr/TNke7pkE5BcWARBEm3JVWaVgdAyXyGIWv0mNonRCj9gW4mguQ +KeQWiKOnhM8v+4pESTfgzpsfRexqbolW6G/QfPSmBlUsYWKQyif7sF8IN9c3laxXuz6 8pCiuH0fr/nL4Z3uiF5aeZ5h304kEZQO1kkMFTp0MscdNqEss95gip2vUSG6pxLt7Ke9 MT+A== X-Gm-Message-State: AOAM5321eCyOvoU578SBPh8FccrdjGCDJH9SpP9JZ21mLuyst005YFKd bFh7nEOdxYEMeiphWfq5G49bTQ2CBj8= X-Google-Smtp-Source: ABdhPJwNBUSOEB1JuFJIrJfbR51JUxxZJ1OON4wodu+1NC7Urx/fRiLZJ4etkL1sB/ACUMvvsEJ5yqyqc0k= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a62:15d0:0:b0:4a0:2dd5:ee4e with SMTP id 199-20020a6215d0000000b004a02dd5ee4emr46726718pfv.14.1637131594948; Tue, 16 Nov 2021 22:46:34 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:31 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-2-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 01/29] 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 2a5f7f38006f..edbe2cb21947 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -385,6 +385,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() */ @@ -450,6 +451,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 426bd7fbc3fd..c3a91ab370fa 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 17 06:43:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623817 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 6E8D1C433EF for ; Wed, 17 Nov 2021 06:49:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 511526128B for ; Wed, 17 Nov 2021 06:49:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233866AbhKQGwJ (ORCPT ); Wed, 17 Nov 2021 01:52:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229474AbhKQGv4 (ORCPT ); Wed, 17 Nov 2021 01:51:56 -0500 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 86879C061570 for ; Tue, 16 Nov 2021 22:48:57 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id p8-20020a17090a748800b001a6cceee8afso761301pjk.4 for ; Tue, 16 Nov 2021 22:48:57 -0800 (PST) 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=2eOkydO3aK8psZwx8Y6ejKnu0TttLN3rQcK8oU4rowQ=; b=sdBJMLTCs36EcokYsAIZerM6fzM+A7dkhUcEe3eCuRqL1SCNd1qCBuexvgc5pQpgeL P52pZMirZcFvVkx+y6BOo3547P/eSKcnjflIY/U7oa9uV/UUvRzg1Hsv0AHI5PQQG0V3 ErJJeu3Qdw5AoPk3JOe4eKcKDTzC54Ua0px8es+IJSWUPUWB/Mgjv2CF4WWBR0LwgIBN doh2Hq07LP1UOmiVLCyFHp9SWY5dxvT24sjzAbYc3Gf4NKyoQKXMS0EX/hyRrangyPor zrsbHGNIf11eKu3rTEn9v+X980f26RAjtcXR3sr1kzVmHMsTm5xXa5iwpOSfUDFCIX7b fEPA== 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=2eOkydO3aK8psZwx8Y6ejKnu0TttLN3rQcK8oU4rowQ=; b=n4HMt4UOWaJ2sFwt5GWbwUAgrgh3GM4O/dyNI/G6k4F1sGrtcDV0ytg3SYaAUJ+Wr7 2oRpNhocYKEs+fJ5Qj9AqPwlqFwhovOpfXYW+zfK2y1T+v5kGA7YsD6Y3EicnrXHsVvN 7WbboyFxlSpg5e1u5mFqGO2Kuokep8RwvxACGTqixV07qOsqYvBiGinxMJ9UADiDYsVX ePxsFxPn4oZJ4hvEu9e6rksH9UhTlfg9js0LsFUyXruWcmoFFYvIHDdZ+po7ngOG+boX iQuA3oBYRV8OpKBLOI1559O0ZHFRwiWUZHRbtc2TSMxNuV5euI79NE6T9kEBHFw2Ac8Q GDwQ== X-Gm-Message-State: AOAM530mENZ1E3+rEWcKYk5L9/7xtnHt90nVHZQtThHcQmJY79M2eTBq /iCriPLfgPuMbVxxEayRKxoiPBeb+w0= X-Google-Smtp-Source: ABdhPJz/AyRbGlm/9OYeriA4BlIWqodYO0uDJARf+tGRmDDLMq0c2Q4JUMHp6DmDYDXFY0qZhRvEHXRXmsc= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a65:40c3:: with SMTP id u3mr3746373pgp.160.1637131737085; Tue, 16 Nov 2021 22:48:57 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:32 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-3-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 02/29] 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 | 43 +++++++++++++++++++------------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index edbe2cb21947..72db73c79403 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -146,6 +146,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 */ @@ -210,6 +218,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 e3ec1a44f94d..5608d3410660 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -33,6 +33,8 @@ #include "trace.h" +static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id); + /* * All of this file is extremely similar to the ARM coproc.c, but the * types are different. My gut feeling is that it should be pretty @@ -273,7 +275,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 = __read_id_reg(vcpu, SYS_ID_AA64MMFR1_EL1); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { @@ -1059,17 +1061,9 @@ 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) +static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) { - u32 id = reg_to_encoding(r); - u64 val; - - if (raz) - return 0; - - val = read_sanitised_ftr_reg(id); + u64 val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); switch (id) { case SYS_ID_AA64PFR0_EL1: @@ -1119,6 +1113,14 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, return val; } +static u64 read_id_reg(const struct kvm_vcpu *vcpu, + struct sys_reg_desc const *r, bool raz) +{ + u32 id = reg_to_encoding(r); + + return raz ? 0 : __read_id_reg(vcpu, id); +} + static unsigned int id_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -1178,6 +1180,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) @@ -1223,9 +1235,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, @@ -1382,6 +1392,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, \ @@ -1837,8 +1848,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 = __read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1); + u64 pfr = __read_id_reg(vcpu, 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 17 06:43:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623819 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 6BEFBC433F5 for ; Wed, 17 Nov 2021 06:49:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5205463231 for ; Wed, 17 Nov 2021 06:49:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233868AbhKQGwl (ORCPT ); Wed, 17 Nov 2021 01:52:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229474AbhKQGwk (ORCPT ); Wed, 17 Nov 2021 01:52:40 -0500 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 E09CBC061570 for ; Tue, 16 Nov 2021 22:49:41 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id hg9-20020a17090b300900b001a6aa0b7d8cso860120pjb.2 for ; Tue, 16 Nov 2021 22:49:41 -0800 (PST) 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=qDRe5fuo80YmvUNtfD5Ja6z7ccR/RWV02RqftfcvCIs=; b=p4IgY7M5dzGUm0FTOHN6RojbbXL8qCy1PuaurY9cIgw4B01w5Viyh2M0dH8YaUxi7R Ah1olmBugu2Z59OdOWWwkqgb5amrTrGkPe7C94JyMl/rxZkJZUzdj0F8/m8U4eN+wsGi Mki64bQf0DLumBFb1JOdfRDGP4115BaU/C3IqtAqvw8IQwsIClrQXlBbpxj0m6Gql2qJ C2bbo4JzPoC/RNpnVImycQeOAKS+gm5zTk5sKgoopxCbcf6VVT1SiPIOE2bk7X6M4+Pd KXYJk2uKHxbOuFp+jRrx5WO5UulcGoZ1y1O/BmQXdNiT1701SnvqauJlEp5rB9NJpiWr kXzQ== 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=qDRe5fuo80YmvUNtfD5Ja6z7ccR/RWV02RqftfcvCIs=; b=CodC5EfbgO9vXqADOTV8unZ5KsRdUVdQrJutNn0wv2DkUhJ94tjcGIfZQj9X/+lLWk SNZCGWf15qSCP/kOT29xXcxzeaUD0W9ZoBzu8d6rGid5m193fTQ63w45g1ndOXCHBU3B E1B+JTPxB9zUwjOmdrslvfiPjt1wTUQnmpzg5gNMvfVmCdiX1r9SfD6yQKeTCeQ3HuIw vJD7lwzj92CAXLoNoDjRl70d7RPl1f49AMbnrtLHn7KzNiybbqjD+amE5IBd2RAYRhXe rwUvAtpvgYmIvK/Nwxr1jC1SUdMcwGTEsjZTeQp29j4e7DwMVRA9eMTkJtbSNsXl1uN/ HbVw== X-Gm-Message-State: AOAM531St7HQe7NZ7KaJC2P2eHJTfQgCqf/8+EVGwzFsHxokkGxcOtbH xhXzlhS4BTGIURDI2koO65xTV1W57wE= X-Google-Smtp-Source: ABdhPJxYms5sy9/Vws06L9k+7Ejmbx9NzNqqi7zJjdpiKjILO6Zl1rCaYDrhCNDTTderhUgOfEsUL2+4eE4= 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:390c:: with SMTP id y12mr313015pjb.0.1637131781162; Tue, 16 Nov 2021 22:49:41 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:33 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-4-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 03/29] 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 | 226 ++++++++++++++++++++++++++++++-- 2 files changed, 218 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 16b3f1a1d468..597609f26331 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1197,6 +1197,7 @@ #define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_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 5608d3410660..1552cd5581b7 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -265,6 +265,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(val, i, is_sign); + flim = cpuid_feature_extract_field(lim, i, 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 @@ -1183,11 +1358,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, @@ -1232,11 +1415,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) @@ -1247,11 +1426,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; @@ -1259,10 +1439,22 @@ 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; + + /* Don't allow to change the reg after the first KVM_RUN. */ + if (vcpu->arch.has_run_once) + return -EINVAL; + + err = validate_id_reg(vcpu, rd, val); + if (err) + return err; + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(encoding)) = val; return 0; } @@ -2826,6 +3018,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; @@ -2860,4 +3066,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 17 06:43:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623821 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 6961FC433F5 for ; Wed, 17 Nov 2021 06:49:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4A0526321B for ; Wed, 17 Nov 2021 06:49:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233873AbhKQGwz (ORCPT ); Wed, 17 Nov 2021 01:52:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233872AbhKQGwx (ORCPT ); Wed, 17 Nov 2021 01:52:53 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68DD3C061570 for ; Tue, 16 Nov 2021 22:49:55 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id x6-20020a17090a6c0600b001a724a5696cso842710pjj.6 for ; Tue, 16 Nov 2021 22:49:55 -0800 (PST) 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=pnVV0dDUXWANaZ8aWNvfjhrF5PhVCI804E2zH0wOM3E=; b=ceapl6AvPZI3/vC2mwRnLl7KjxDguO+n/2FhAKPMEsWeJcr6nh2z5ML5Zyspn+X+oi eOG5b9oMdf4M0ijZrTl3BB+twEpz7SLT3PQGPwwee7YEWvqiKhz4kpHkQkPFScEOubhh PHmDRXKLhg8b0bK463OW3zcR6hYneuOfXGsKWWo0vpCxB5Qab3vX428m4V6U9V6ADRMU LHifHn8XYOmf6vtXXDBZNhcbWng3mx7aesw+zV7tK1qcFe0GJ3Eed3XMfN+CafmGWV7W 3nbmgaPA40qIFpGunX/KR6GztN7/vjVwbUY5DsFDQ2Av8jeR4NKCYgtkakr8LNjARLVp VoQw== 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=pnVV0dDUXWANaZ8aWNvfjhrF5PhVCI804E2zH0wOM3E=; b=hXklFy+XI3NG4mh/b9Om55QXzH/w4y0KvY7TULi7F5BE0T0GUCWqnxjE4+7yL0ZlU5 mEwpvPQ5FU00BGjwFg43diWQ2iURN4ruTj15aNKKCApOqZUnlivxig2JQXMtRQ2ho5e4 ZsIepIz3JnFWk/f9vQIouYU6/F+lsvLzeetlDvz/ax16nKBhR6X5s/ezzYVEYSxPuD3t nJgENC6h3KgcE8wxV61/yRvo6DPA7TXZG5l3O645sT2sXEjGPIc46g3tShWYOSTJ1Fu5 /tdZEqtIRcm9J1Fi5NEMHltHxVSXr+NR0frqwK1Mt566mQB5lnISmtJvmibEoedM/kJr w0UA== X-Gm-Message-State: AOAM533T0RVoWjeGmBBAuoA81nIbe0QW0eZyDvFVnTcqx4LD39Kdp1KY ZgXrA87+4PfU7YikCLvDXlo9Oes6MCo= X-Google-Smtp-Source: ABdhPJyGFmsrlVNrwecF2T+roRV3vrXO6UsZB0R8DGqP/IeotHb/4HF1tiOSvziAZ09+qdqIbL0UHS+Zs7Q= 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:408c:b0:142:45a9:672c with SMTP id z12-20020a170903408c00b0014245a9672cmr51484560plc.7.1637131794924; Tue, 16 Nov 2021 22:49:54 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:34 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-5-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 04/29] 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/GIC field of the register to a value that conflicts with SVE/GIC configuration for the guest. SIMD/FP/SVE fields of the requested value are validated according to Arm ARM. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs.c | 159 ++++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 56 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 1552cd5581b7..35400869067a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -401,6 +401,92 @@ static void id_reg_info_init(struct id_reg_info *id_reg) id_reg->init(id_reg); } +#define kvm_has_gic3(kvm) \ + (irqchip_in_kernel(kvm) && \ + (kvm)->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) + +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); + int gic; + + 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; + + gic = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_GIC_SHIFT); + if ((gic > 0) ^ kvm_has_gic3(vcpu->kvm)) + return -EPERM; + + return 0; +} + +static void init_id_aa64pfr0_el1_info(struct id_reg_info *id_reg) +{ + u64 limit = id_reg->vcpu_limit_val; + unsigned int gic; + + 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); + + gic = cpuid_feature_extract_unsigned_field(limit, ID_AA64PFR0_GIC_SHIFT); + if (gic > 1) { + /* Limit to GICv3.0/4.0 */ + limit &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_GIC); + limit |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), 1); + } + id_reg->vcpu_limit_val = limit; +} + +static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, + const struct id_reg_info *idr) +{ + u64 val = idr->vcpu_limit_val; + + if (!vcpu_has_sve(vcpu)) + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_SVE); + + if (!kvm_has_gic3(vcpu->kvm)) + val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_GIC); + + return val; +} + +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. @@ -409,7 +495,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) @@ -1239,20 +1327,22 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) { u64 val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)); + u64 lim, gic, gic_lim; + const struct id_reg_info *id_reg; 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); - if (irqchip_in_kernel(vcpu->kvm) && - vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_GIC); - val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), 1); + gic = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_GIC_SHIFT); + if (kvm_has_gic3(vcpu->kvm) && (gic == 0)) { + /* + * This is a case where userspace configured gic3 after + * the vcpu was created, and then it didn't set + * ID_AA64PFR0_EL1. + */ + id_reg = GET_ID_REG_INFO(id); + lim = id_reg->vcpu_limit_val; + gic_lim = cpuid_feature_extract_unsigned_field(lim, ID_AA64PFR0_GIC_SHIFT); + val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), gic_lim); } break; case SYS_ID_AA64PFR1_EL1: @@ -1373,48 +1463,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, @@ -1705,8 +1753,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 17 06:43:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623823 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 AF429C433EF for ; Wed, 17 Nov 2021 06:50:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9513E63212 for ; Wed, 17 Nov 2021 06:50:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233877AbhKQGxG (ORCPT ); Wed, 17 Nov 2021 01:53:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229777AbhKQGxF (ORCPT ); Wed, 17 Nov 2021 01:53:05 -0500 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 92753C061764 for ; Tue, 16 Nov 2021 22:50:07 -0800 (PST) Received: by mail-pf1-x449.google.com with SMTP id l8-20020a056a0016c800b0049ffee8cebfso1090606pfc.20 for ; Tue, 16 Nov 2021 22:50:07 -0800 (PST) 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=tq9EsnBDsIULQVxeorKH97JMfxdcU3KwA0yIbRqb8nc=; b=Yfc5AyPfrAryp4Ly0NWpHvWkMzvobkI4oVp3ewLCX41K3bjSVjPldr2kYS+ztybCjt 5AnGjw8annOa4qaveRkzMBLnQpwxpITb5wACIILLFPP2l9bfKYll9XOqxL1IZAcwgqEU vhCleY0OFQjLwmop8/zWloUH6byFk+JUA+H2YmwXO0sZbMLIstxFWsRJ8MIpgYqoKQ9y 45HqmWmuC0xStSdr5Fkp3mxIBc/rGMey5VtzYvSkGP2jAQ9RQDDjXFlFXw60NEMHPRJM 3vXEJRG1XJpl+8b5kL2rVtzwOqc4Ulx7Q528xcpC/XAExBQYk+yyrJcxLxuOBrZUy1nQ 5+dg== 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=tq9EsnBDsIULQVxeorKH97JMfxdcU3KwA0yIbRqb8nc=; b=HfrKqcgMPSHzYtehQ+2l5jIQxxZnptkgiVE7zsAx+2ToKaNO200NBzxs4Fn2h0Uwsz zV0yCoX775uzU7lQiu0OX8YGIMRYU3OHB3cq52OJJF4r94xWDF8skYcPMWAHA6pyoRuz JtjAj7QQA5xqBqvTsEBDzrO+Db+d2W6MUzDoC0hbeOZVdk9SXAUHYcf8aR5I5MusErAK U6IeYLUp/oFr9dbmQH+2iQmBeuY4oEnPjaWG/rbF+B/fae0Bd+gYeyDHCsR6GQ7TdPNN yVqEJu6fhfikN/Tvk+gCrBWIAqZAPHsV40Eb2z6Jwt8N+KD9dSD0dZErZ2Fs25ZHzVXt q0PQ== X-Gm-Message-State: AOAM532UkCSC0Y/MQNMY3/TYrxBtdm6RuOTUkMwRxj084Oa0H9U907Hf 8JPchYqONouoShdDgGDruGb7DtZrbb4= X-Google-Smtp-Source: ABdhPJyw3+jvRUQTNuXU0Rs/FuDUFQG75ZnH7tR0+PpZD5NxVMfLc/BgVA4P+9YHIUJfIQCNVEBtndUZ0eA= 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:9692:b0:143:d9ad:d151 with SMTP id n18-20020a170902969200b00143d9add151mr5223500plp.40.1637131807111; Tue, 16 Nov 2021 22:50:07 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:35 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-6-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 05/29] 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 | 44 ++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 597609f26331..b7ad59fd22e2 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -800,6 +800,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 35400869067a..7dc2b0d41b75 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -433,6 +433,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; @@ -464,6 +479,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) { @@ -478,6 +499,14 @@ static u64 get_reset_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, return val; } +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) | @@ -487,6 +516,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. @@ -497,6 +536,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, @@ -1345,10 +1385,6 @@ static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), gic_lim); } break; - case SYS_ID_AA64PFR1_EL1: - if (!kvm_has_mte(vcpu->kvm)) - val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_MTE); - break; case SYS_ID_AA64ISAR1_EL1: if (!vcpu_has_ptrauth(vcpu)) val &= ~(ARM64_FEATURE_MASK(ID_AA64ISAR1_APA) | From patchwork Wed Nov 17 06:43:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623825 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 9AF41C433EF for ; Wed, 17 Nov 2021 06:50:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 810B163212 for ; Wed, 17 Nov 2021 06:50:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233889AbhKQGxc (ORCPT ); Wed, 17 Nov 2021 01:53:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233959AbhKQGxX (ORCPT ); Wed, 17 Nov 2021 01:53:23 -0500 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 E8BF3C061570 for ; Tue, 16 Nov 2021 22:50:24 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id a4-20020a170902ecc400b00142562309c7so570337plh.6 for ; Tue, 16 Nov 2021 22:50:24 -0800 (PST) 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=LMhbb8z+xm9w4/dja4Fw2MViuPAGvmmbQ+PVrYP0i5Q=; b=SHNcn7oF3x+HutlCWfvIjEAcuL9nEimGUkVvMDgZQWTx6O+yl+XGGHBSaV4C4FE9Hd r00c15U+WA/c/IC5ocEZq7Xo1J9td6jlOfz7tLGtc0DzkplgSJaZai2mGzwHpHOJJcJ3 mntmYW8ApfOYm/CMasymg9RgoGV3hB6XEG8roGM5q7qI8dhIiTyXIpTSNJEPSEY11kZr TA7jjU63CGF/1Ds1KIhKHcysXlmGwvLJGJW5xXRqJTQCnLk1K2HXho0wMctqMKCNvp/r gqBI19+OFVf7Z0+X/Ltrx8hqOclgC3e3HmVDOL7XtGmdlv07TZqPfbNemzRwNjRoQdZc kWIA== 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=LMhbb8z+xm9w4/dja4Fw2MViuPAGvmmbQ+PVrYP0i5Q=; b=UnZVgH66ceKnZ37q/RVxKEfH26AiPV+KA8agxfwIQ4dSek1W068fmkw690nTMqVOs1 /z8IZhNnKkEyJZqbOPAcYqsm3j3yLR5Pu4ZulihXTQA9nb6O8ClhXeKQCpBQ+E6Xy/KG 9Kem6isxbmaKRG9UcHlNw+5bTWDRdR+Ne/wyLG5ji7QVXqHt8z/YRyJa5tg2qvKeTNT5 mQiZ3+I8MY4MF6W2N9gxA/QAoxN9PPm7004w+NqdeUjhRukDn+imh6x5E7fHdRLfNxCG jFbtoWS0RdE1PZ7iyKIzp2quHHWIWks9TnpJAaJ+qavXp9gAoV94Si9ccPR7A8W0/nZj w1GA== X-Gm-Message-State: AOAM5329kQ/ruagBgolvi7SJRnxAHsW7xUWJ2vYrEJmDAfGss0/OpJUB 5SyV71PWt8Lh23rH14yFVJ9TRWaFx70= X-Google-Smtp-Source: ABdhPJyqvIkcOzg9kv5HN+bRx6bfyb/Kt8VaG6o4P5ZXqPuVs07Jl4gjrYMSnip9n9ksQ1DhnYmfpYKYXKE= 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:284f:: with SMTP id p15mr312752pjf.1.1637131824128; Tue, 16 Nov 2021 22:50:24 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:36 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-7-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 06/29] 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 7dc2b0d41b75..fdd707462fa8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -448,6 +448,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; @@ -526,6 +549,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. @@ -537,6 +565,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 17 06:43:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623827 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 12DE2C433EF for ; Wed, 17 Nov 2021 06:52:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DF7226321B for ; Wed, 17 Nov 2021 06:52:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232556AbhKQGzi (ORCPT ); Wed, 17 Nov 2021 01:55:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229777AbhKQGzh (ORCPT ); Wed, 17 Nov 2021 01:55:37 -0500 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 A4FD1C061570 for ; Tue, 16 Nov 2021 22:52:39 -0800 (PST) Received: by mail-pf1-x44a.google.com with SMTP id l8-20020a056a0016c800b0049ffee8cebfso1093536pfc.20 for ; Tue, 16 Nov 2021 22:52:39 -0800 (PST) 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=+QM3vxnIY5ebG82kJmilfb/kEzJ5uds/3O+I1dlEIvk=; b=EZYIu6hRvSKsmk4QDlfw/1oaSm7K9pAmp16YJZndakKVaHT40P+1YH2Wv5+ZEWzivU odVdvfxwvHkVN+HLLWpxNd0JzQLFifHDo3lBDzaDkHv43dflu4A1cM0Z519KV5TLebja TnI8bUB1lY8FzCQ8HQnlZCSLZiz4X4ADVMAOe3Gh63zazWMB6iDzKS9XZ9vTRR2cM1TP /6gxGnlIlBAzu4aWWzTdq3sQVNdw8XctrPDaonPM2BGrQB9oQRXJBKNTrWph9ChuLV6S RUphRiV46Nwnp+2QL38ooleyWaT89WpMaMQunAP/6V6DNBix32380PwpUVuhDfG7+oYG MNKQ== 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=+QM3vxnIY5ebG82kJmilfb/kEzJ5uds/3O+I1dlEIvk=; b=XX9v1BqsUZDnXXeJHpqIg6CWyLRzweH+IWBCPJHE+CSWGlZG445oXA5oQUaB2INiXu /+j15AtssgFNTzdl3oz1nUNsz0Ct7PoWF+mGlblS42Y9Lgj01H//VhHIo7Ayhn+aWweq 7GCSzyWWxgynifbC7T+4/Ys6uPTGSER2+Fcces3fUoyOjJHQwLe0FhgfgwkZCo3Fz2cf 27p4NYO6kINsvQxwwTwVqwb5WtFs+91trmmX5PdrBld1KZ7QoforuhJxwQXz9lAr5A4y PG2NQJ4dS6LSfnfHMArz2Gu7E/u3Leif/qXHGpnjA7QJnmCqexc7IQKSbmecEmD86nor b3TQ== X-Gm-Message-State: AOAM533Y5MAHvMP2ObqFh3uChIDsThzSzqO+JRByoRfqm9ViR3rz8TAd w18szXYmyE21QkMi+xU9Osa1KqzdhuE= X-Google-Smtp-Source: ABdhPJxotgq01k/w6uRxD8N6KAp8kDUMHpCn7kEiA8krb4HdDzKMIROjffEwMWJnsJlwqjvRMerWHPCmEb0= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a62:7b8e:0:b0:49f:a0ba:67ff with SMTP id w136-20020a627b8e000000b0049fa0ba67ffmr5007355pfc.64.1637131959115; Tue, 16 Nov 2021 22:52:39 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:37 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-8-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 07/29] 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 fdd707462fa8..5812e39602fe 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -358,6 +358,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 */ @@ -471,6 +489,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; @@ -508,6 +556,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) { @@ -530,6 +584,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) | @@ -554,6 +615,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. @@ -566,6 +637,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, @@ -1414,13 +1486,6 @@ static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), gic_lim); } break; - 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 17 06:43:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623829 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 79D04C433F5 for ; Wed, 17 Nov 2021 06:52:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 58FB561BF5 for ; Wed, 17 Nov 2021 06:52:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233507AbhKQGzx (ORCPT ); Wed, 17 Nov 2021 01:55:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233879AbhKQGzt (ORCPT ); Wed, 17 Nov 2021 01:55:49 -0500 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39C55C061570 for ; Tue, 16 Nov 2021 22:52:51 -0800 (PST) Received: by mail-pl1-x649.google.com with SMTP id m17-20020a170902db1100b001421cb34857so559617plx.15 for ; Tue, 16 Nov 2021 22:52:51 -0800 (PST) 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=NoLQttS74SYAnZZthD/shZb12TIR6ivBDSUsCWLtqtc=; b=CcxMAc+SL67BI3kc2oW+z3/3vhXp1OKwrkvUCJJiZR/3EX4i6JPRnvpelk7wPBPBDS loQ++iTRyW/M/9G24JLkAJuw/ycM5ncLFq0mQyMCSTUVGqeBf7zrkbHMcJnDBlqE7WDA M0NqrZxyd1gwAC+bkfO0LBziewV70xBpkp83V6vBDDoODYGupcWpnYLUjMZwiNptnv0+ moiBG0qv/ghVnuNs3l+pGyBQv6KLsr9beO3ZYw7cPz2aV3dnnsl7fIuA0bzW3VeaHn6R 5G0KQ4G7bYsZrSUL70BxK4/IDHV9ZLfH8YZ55x7He5r+xUnaZUzViBNFmIDDj1Ujd/Fh iVPw== 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=NoLQttS74SYAnZZthD/shZb12TIR6ivBDSUsCWLtqtc=; b=w7c7lUCOp6ZiEPMJdOVSpEH4VTlgYnDJYWszm+QEA/uucXgFqRBx0jyD/unrFIq/3Y RjaciPsrkKDCZ8B7tq11Jo3jlEvhlQiOTQkMDllW/MO12ZEYuk8L3oR1gMGgNbqsDcdW 8M+XhK0cAxF55esSIVw4VsSHdqxGs/+lSEN250T4KnNrqq88InAGo5pM6+t92vjGzW2Y 9vPH6usXrlpUBxDykly+0WOMtKsWPWAz06GlT/9DzTED2H8/Tguk6/xqiYuzRiJCbD/M 3AuBmoVCWkWZF883E33p4fb1zDRADmZ2kmIni7haph5mAqFvnSC241wKW/+g2yXXc2Nb DA4Q== X-Gm-Message-State: AOAM532GSQjwRjt/dya9btmJgs1s+zutH2gyEyp5pmX8VU8jwAzOqR54 IJ92NrcK5HomH/e7qJq6GQSPM6/Zxm4= X-Google-Smtp-Source: ABdhPJwuLMc8Oqfj6238AuyyJCo4QKQmSwYQgaXokQqy8EDcMnL0mZW0RsTCGldUYu8oGZZPxcOr8EMF+yI= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90b:30c6:: with SMTP id hi6mr6846337pjb.201.1637131970736; Tue, 16 Nov 2021 22:52:50 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:38 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-9-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 08/29] 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 5812e39602fe..772e3d3067b2 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -519,6 +519,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; @@ -625,6 +732,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. @@ -638,6 +755,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 17 06:43:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623831 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 B5D29C433EF for ; Wed, 17 Nov 2021 06:53:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9AB6B619F6 for ; Wed, 17 Nov 2021 06:53:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233925AbhKQG4A (ORCPT ); Wed, 17 Nov 2021 01:56:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233537AbhKQGz7 (ORCPT ); Wed, 17 Nov 2021 01:55:59 -0500 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 3A5F5C061570 for ; Tue, 16 Nov 2021 22:53:01 -0800 (PST) Received: by mail-pf1-x449.google.com with SMTP id l8-20020a056a0016c800b0049ffee8cebfso1093947pfc.20 for ; Tue, 16 Nov 2021 22:53:01 -0800 (PST) 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=EWy90w7C8DEQ1vuhiOPoGiKAV2Py3BtH8vbgtJOob/M=; b=farwWaGHDp+BJPkIl9cjFCayMUEmwN32tMCgYlXLKI11ppCFUHe2zJGtjZbWjUwkRr yPM9N8gd7kYnReGOSL1Za3CcPR79kRzCUVmBh9dHLbUPbJIcE7b1HaqIoka5NOGOMUD9 KjuFnNcXm4Y0gjLrBTYa4TPv7PV19P+647eUqA1GmjiA5J9+NxB5Ju9jfzOyadu6PCF4 HwH660ONcWXcuuecLlZycXkSp3eaaEtZmZ8v9Cm1VreF4Mkr9lOEOWzuDQCqyg/szpTS dXe+J145D096FZQIdLj37NnlGYV0cirsUNPWclerfciCDssRW3GgCD70vV3vp3KEetIL P4ng== 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=EWy90w7C8DEQ1vuhiOPoGiKAV2Py3BtH8vbgtJOob/M=; b=gbwDopCZQdZT9H50wHZz9Yvv4sCoy7PDvWDN/buq8YF5BL+wmbol7JELFtSstu8Aj2 Pc+lsh8B3M9Kaavm0OCUmRwv7JmQg20t0Cf9k83V2F7/9nlma4cD/HjimL47aqtc6/93 9RJpvjVeCTczMEmMAi0oCvYuD17Jp5XfVRX3qBjrz1ZAPgcwocuC+W1JOxnlTH3TWzu0 UAS++ESU+JGPVb/ofwMdmshugklIFUZBtSqna4UhgnIbYnmHKW+Fp2NC8wwFvYxZKF36 UrBle7NqsLl/6dLtuSmvYwAnTtYOCBg37Qj94JNl6ZxVJrZUcxNFdjzfnhNre9LGPY5b RSgw== X-Gm-Message-State: AOAM5330LWRZNjdl2zEWr19KVbQGDa8KTmV6snNNbobQzukrvDWIYBhS t4iCXxTCzhQM+kkJGOHHMz3Rpx8P/sU= X-Google-Smtp-Source: ABdhPJxTX5Ui25fj7I1/W09kifmBD7hv5qJ71Mwl9g4XyAIXdzKDt8IM28bi7JUXoF+/FHXLa6ILu2RhNVw= 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:390c:: with SMTP id y12mr314550pjb.0.1637131980501; Tue, 16 Nov 2021 22:53:00 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:39 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-10-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 09/29] 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 17 06:43:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623833 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 CF305C433F5 for ; Wed, 17 Nov 2021 06:53:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B3EF461BF5 for ; Wed, 17 Nov 2021 06:53:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233927AbhKQG4G (ORCPT ); Wed, 17 Nov 2021 01:56:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233886AbhKQG4E (ORCPT ); Wed, 17 Nov 2021 01:56:04 -0500 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 EF498C061570 for ; Tue, 16 Nov 2021 22:53:06 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id x1-20020a17090a294100b001a6e7ba6b4eso841430pjf.9 for ; Tue, 16 Nov 2021 22:53:06 -0800 (PST) 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=xIn1TXsOInH4444HBtq8lDE6nz5k0hEewQ+rXZOcsIo=; b=RubVz5vGyInFZsyOsKQbph78wzeGOs27T9Z3/e1OzOz0GK8ra7LTlWSCfJX57EC9Cb LQjSU7gdcytATbmn1/T8Jiq/nHHVJ/mSvgFMtSpGHvao8Fwgd4wNtcKhhiUpUFkNokqK bwYTwyifKaj5au/rfC7Ee8GyrrAEgrUxm8GQ4fKrafiB/J2IMk1+XXSV30Gri7npBHs5 6cvPjPzgAHsDbs2X4SR5GO5aIsZCYhQ2N2RksEX8uQNwbtpDSZTUbrQ0w0opO9BjjteF RlwcFSohKKnjlVjWqzzn8IGAD8VsE9ZUb3H2uFSt2e/t1B8mhqO86lZ3EOwwZ1HgFUge H5IQ== 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=xIn1TXsOInH4444HBtq8lDE6nz5k0hEewQ+rXZOcsIo=; b=Y+FPSP+KFfmJGQ0UPjwNbIa80gpQ3sKGPVNbtB1vo8Bgm/jiZvKSo02i0RwYrHaDdN NJr3ngYguIspa/4rPOua8As/blmM6t6ri5nIohr2WZ/NWWtZ7huokZxZo60DpWdQWLby zorokB08y6j2HcrGn/SSWimyeoyzJHtF7RGDaXwkcJgWzaKPpEPPZFlgAonUvH2drS/v yiMiE4ZEHpXBbUASd1oQH979E4NQL7RCJNmZZ+DJgLTQhREEcWPv/uUP60Hrnc1OOO6j zraZKaIWuxL5kVEe8USMDOZ+T7fMxnYGA+dz1a/vLCoPFOuwRsSknYh9esunZF7Ga3kR mU7w== X-Gm-Message-State: AOAM533ETB4rW8+JEkvkMmX5EntuoOjUGpMRvUWvjZXr1JgVIhtVEhcw PXsNNFjxpKVS5/+Q7/P9alTlptNnd1Y= X-Google-Smtp-Source: ABdhPJzViDRuBcyE/NWMOeuexd9lVDAnAWnZc3xo/3UeavDavxUZRDOs2MBp/eMgCfy7MThZKNO4ybEXDiY= 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:1208:b0:143:e4e9:4ce3 with SMTP id l8-20020a170903120800b00143e4e94ce3mr753877plh.21.1637131986440; Tue, 16 Nov 2021 22:53:06 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:40 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-11-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 10/29] 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 772e3d3067b2..0faf458b0efb 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -626,6 +626,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; @@ -669,6 +708,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) { @@ -698,6 +754,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) | @@ -742,6 +806,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. @@ -753,6 +825,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, @@ -1604,17 +1677,6 @@ static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), gic_lim); } break; - 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 17 06:43:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623835 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 CE0CDC433FE for ; Wed, 17 Nov 2021 06:53:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B52D063222 for ; Wed, 17 Nov 2021 06:53:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233886AbhKQG4S (ORCPT ); Wed, 17 Nov 2021 01:56:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233431AbhKQG4M (ORCPT ); Wed, 17 Nov 2021 01:56:12 -0500 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 E3B56C061570 for ; Tue, 16 Nov 2021 22:53:14 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id d3-20020a17090a6a4300b001a70e45f34cso885468pjm.0 for ; Tue, 16 Nov 2021 22:53:14 -0800 (PST) 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=SC5T9znPBLTNrmN/sDQzNw6Ub+Qjzd3qc7h2EDRdpsw=; b=g/3NbKzHcUiXa+m/7cvTZ1xTKPYSz37HHs47wNPYPhkDUo2NjRSjilyLwR4i+nLrVY k0CyX97TWk0Ody6mji2CZ9wWp/OcbHpfT4FtJsU1gbn77p2NN7zZtfirQFP8PPlYzo20 YUfM7RQLCGQ6yDYJEdVosYHXiP07cGB1dOF/k4W92QCz4TZq+K5R1vc8xRxXvio+osdY EQUK9mid9FV0hbYPr+2j51+1uvBX/aVW4JJCmwY5C/TFtfjmSwhvueqc2g4XdxRV1RNc 9ei+QRh2fRv8siqh7/suv9Icey8MMkuKJH9+w84TprS+t0kZ0ym6L1+IAhlfY/I0lCPJ ASUw== 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=SC5T9znPBLTNrmN/sDQzNw6Ub+Qjzd3qc7h2EDRdpsw=; b=xuD/wuF1owrCFccOg+5bEIm656eCmo58lXNx2T7Gt5T6id82vFoE9HS4b3FqyfY35F L9klwjnuerFaAYV6ziR315V64adCNK+uLRtrPKq2ULMczy7d+f4VQnK9I+0StEIXieqv 1RchhgEfZf1bP0FnagB7d51/64Ts2Ws9pPM5XIPntMrdq9Q07QW4ra3HiKH4LjZX1COS Hf20+Mga4ryVwSh/C6sJeTHLbM4Dpc2aj5+lpf7nTSxnqcEUY2pLnkwJp9kt8FgDHwKo DI8fPu17e9PXfevERJyQs7N3SHtJ2U/OpDd1HL+5vjPRZ8591gQXT2hEa9wGA9M/5Ik7 pXuA== X-Gm-Message-State: AOAM532cb0dGhxogzDCNxb7PV1ROa25fssN+A8p3JqHBqnsRFTEZuAd0 sXA73HofJa7dsPcUxqQt1WXnwX3Xqg4= X-Google-Smtp-Source: ABdhPJzxco6E3AqetETiY0RA3xGyLBBSVtg3Qx53KDDwdkXujTql0gFgly7E7xEMCFlAmqMkTH074Ke6ZUQ= 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:c58e:: with SMTP id l14mr6765135pjt.214.1637131993894; Tue, 16 Nov 2021 22:53:13 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:41 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-12-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 11/29] 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 | 52 ++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 0faf458b0efb..fbd335ac5e6b 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -665,6 +665,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; @@ -725,6 +746,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) { @@ -762,6 +792,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) | @@ -814,6 +852,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. @@ -823,6 +868,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, @@ -1677,12 +1723,6 @@ static u64 __read_id_reg(const struct kvm_vcpu *vcpu, u32 id) val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_GIC), gic_lim); } break; - 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; From patchwork Wed Nov 17 06:43:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623837 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 33912C433F5 for ; Wed, 17 Nov 2021 06:53:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 125F7619F6 for ; Wed, 17 Nov 2021 06:53:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233937AbhKQG4U (ORCPT ); Wed, 17 Nov 2021 01:56:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233931AbhKQG4T (ORCPT ); Wed, 17 Nov 2021 01:56:19 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 023FFC061570 for ; Tue, 16 Nov 2021 22:53:22 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id mv1-20020a17090b198100b001a67d5901d2so2618205pjb.7 for ; Tue, 16 Nov 2021 22:53:21 -0800 (PST) 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=qC/eXS2nFGbe5LWPRqIYtTbFYtBHmQ7GJKQdVVP+A0A=; b=ghbQ96p4mvC9twAH0Tuj9lFaRHB0m+8uJQPFzZ/CIBytnHC1y3VVqa5GIPtE6fyT9m +nnTxOjPfBRykrURArKpX2lWueXwUYmbzzd1B19UzxxMpqE4r5tms+Hsh7VPek4W+Kh3 w3pKoJUfdsAarCISRa5BiPct5PvoCMPMOX+U7d+0giU2WFUZ06dfLr+8kseGJABiQtfO uIN6ChXyDtLWyDwej87qXdsZippbWA6S84KHonLZMfYhMIK4+n/AZWFLeoAqSGsIDWoP OGFO9nIob2MxsERrirI2PCI8fIqEfdqOZGLzdc5U3v0awu3fxsk7lv4JAfnpteT3tp1Z CymQ== 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=qC/eXS2nFGbe5LWPRqIYtTbFYtBHmQ7GJKQdVVP+A0A=; b=V8L9J3BpR8VFQGZgyVfFHGMTxIhojcYiU+mccwSAX1HjE1HhPFr7bKsH+6RC6fYKW0 o6RYdLWOrhOskaCDX/2SEaX+pDApJlvzvp8bEzGkUJHxhoswhpSIs7x5N+5rGQ+IxoL/ RvAi7IB5/kz8AvrPGtL9XjSIEgWiBpzz1OQxJ7l7kf5Nq8v41G4wVI8OKLk0uw2vmkaC L6Jmc1baxDuvauZZzISSU6bsN5goq9ahu3PSia2JjupKCner3ePqHrXDBklybyM6I4Sv L9AO52hGgXg1biWcbSwBwBVvjVWk9o/8vqboHtWMmUzPqydwISTpm+cPuW3Txf4DDbqb ZPzg== X-Gm-Message-State: AOAM531R+ZuI8zmrsLf/n9TZLsA+8pNHJY01vseO6cE8SLtyHmiQIXMo kMOIMLPT4AYubVH0PkdkfoQpNMIgyUU= X-Google-Smtp-Source: ABdhPJwC4wjg1VuToYTvSJudxfPpKWjHgt+8qmyxs2CKjFyvyU3SEzO1OSgLiJ1kbIUegF9tuwn3xYxJOOg= 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:748c:b0:142:5f2f:1828 with SMTP id h12-20020a170902748c00b001425f2f1828mr52715009pll.4.1637132001549; Tue, 16 Nov 2021 22:53:21 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:42 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-13-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 12/29] 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 fbd335ac5e6b..dda7001959f6 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -859,6 +859,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. @@ -869,6 +874,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 17 06:43:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623839 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 4B85EC433F5 for ; Wed, 17 Nov 2021 06:53:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3124763236 for ; Wed, 17 Nov 2021 06:53:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229448AbhKQG4a (ORCPT ); Wed, 17 Nov 2021 01:56:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233425AbhKQG42 (ORCPT ); Wed, 17 Nov 2021 01:56:28 -0500 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 6903CC061202 for ; Tue, 16 Nov 2021 22:53:29 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id gx17-20020a17090b125100b001a6f72e2dbdso770157pjb.7 for ; Tue, 16 Nov 2021 22:53:29 -0800 (PST) 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=ypuzSw/4IsFfP8hg4NDwxw7HgMl3eu3z0C9tC8AgYeo=; b=siCkxe7qZ1oXtFSP6PtWcHf9JCEx5P8MAKaxj8jRAZjR8TfN4niqzdgqkLMpfQaN0M rdSPyeCBX127qnv7K5czfSo/LvwTRLRDcXnzdNgvwE5IRGkZ8xGT03jhc8dwV/2RgR8P AWe670/xztmm7gjkaEv9Pa6NhvqJFPjCrCMYUmExN16V2e37k0q7bIznyTmf4bnI7Aap r46yZAFdRIAih428DLTPDiNrKorKOddvISj9yDv4t6ecov2NQayo4OZUfHgvYMaVQF3C 3mdP1/hAF5VI6iemKG4j4BoxYnitUxtZwT4DfeyfxKH3tSqDswy3euhaPi9Bxg2V5kZI Zxdg== 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=ypuzSw/4IsFfP8hg4NDwxw7HgMl3eu3z0C9tC8AgYeo=; b=Tiqkesf9HsqiL/HeEvr88smPdQ8b7tLqAM6gDq17/zA7KBA76/2Bm70lN6tL/Yta/s XrIn3Vhn/wXDGVysJtG2DWHXg7Z1/RTw22bv7F2Ac60c/DJRIgFs2AIUtuwy0tfFSRGr JZfWDAGxUwwkXORjArRyPgVLgBghvTeuA0lmTKJAU46YiFPjndXaV85DBjjIa2+9YMqk ZZdnJom+0YwqZLhc/akd7BCQ3PtDVZdMHKKFp06VzFhSiQESwyOwajKs/QkEbM9Wntow xKgSq+Zr3isWNMrnGFtiLDnk7D1oQwJ1xR1MROgcebXY42KuWDS/5J7nvVw2DYwMMEHl +Ihw== X-Gm-Message-State: AOAM533nql96LiRjBEoJ6jWWV5ekJniDA8u0gk5ss6F5yEpGQNQK8VZD ykn7K9mRxnRnNx2QO8e0NCINekyL9R4= X-Google-Smtp-Source: ABdhPJwI9+DJbTQSPl234ZhGbVm/QrbU+RAS+b9ok3vE7uJCrhlFZeqke6v/rSWf7WrZlyw307Ylal6Fomo= 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:21c2:b0:44c:fa0b:f72 with SMTP id t2-20020a056a0021c200b0044cfa0b0f72mr4939021pfj.13.1637132008899; Tue, 16 Nov 2021 22:53:28 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:43 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-14-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 13/29] 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 dda7001959f6..5b16d422b37d 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -864,6 +864,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. @@ -874,6 +880,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 17 06:43:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623841 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 A7AFBC433EF for ; Wed, 17 Nov 2021 06:53:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F6EB63232 for ; Wed, 17 Nov 2021 06:53:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233454AbhKQG4b (ORCPT ); Wed, 17 Nov 2021 01:56:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36836 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233281AbhKQG43 (ORCPT ); Wed, 17 Nov 2021 01:56:29 -0500 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 52767C061570 for ; Tue, 16 Nov 2021 22:53:31 -0800 (PST) Received: by mail-pf1-x449.google.com with SMTP id e12-20020aa7980c000000b0049fa3fc29d0so1117850pfl.10 for ; Tue, 16 Nov 2021 22:53:31 -0800 (PST) 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=yLVjb77owO5ybb+blXdLB2u8TBEDp8SiZFpXOiEwz6E=; b=fDzUBhciz6ab1h3rP9Ucku2G59ZHon7OMlm9GJaTcxGw2QIj3w2oxTr1XbvW+YZGLK 7wlw21isyxEL1SzBvtRO/6hdnL6njQInjzEyBb2El4SNEGGElu1d4+EsGvx58kgvAnZM 8Gz4R4bDwans0su5HW0IxJMKTcNsIDR45GF3PbE/M5ON0BtbzheJDgH3qDgKegWzIKAT tFxMfu1B4/TO71tiG8E2e62rlo237Abtbxy+MpcnGSQV+Xh+nRNyk7K2+ULWma3kgQDz O01BmklYF4syu1w6IWWxuSSa6AoJyckwb7/7v5xiN3vqEvebFLzUrS3vaFD+4jTLJLsA 5Yxg== 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=yLVjb77owO5ybb+blXdLB2u8TBEDp8SiZFpXOiEwz6E=; b=KM9L1h1r39ML+CVhwASQYQbPyJGzsvj2iSeYbgo/gxVnmdeODidPwRb37U3rkPqG6p zQTBMBoER80bRIzHzM0YUMvBCfZi0XAQFDBoalDUoJBL+e/CKLmpAMDs1nYAnm5bxY53 /z5RHgp5ngOSO1VP5npg3DMNIKQS7WqAOFxS5AnDY0xvSfkBIDA4Lb+IUCuri+J92MxH nUF4aWB3nU08CkCOoYSOBC23WNXLjMEpzkvIAtVGj+iTjvWzLl4jQLHVuPqm5AxbXPTM PfgkVZiObr99AefT8qrKmDtAV7ZGL2gdntxrMdMZTw4KoDk9nfujqRxBvsy8f+DbE9gQ +1mQ== X-Gm-Message-State: AOAM533mP+m8TYYUFxV+jcaMXWIpA1g3M+SR4L2MuOC4jYN0ppFgO0Vr g5eapuCQReDGfEpHszlBSjqhkH1C0H8= X-Google-Smtp-Source: ABdhPJwT4TE1Cp4Q7rnEHEKQedPKGeSfrSxBPQGD89L53thUMmYvU82rt7nCRoE3lbp7K0eH1lqvYb0pO6M= 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:284f:: with SMTP id p15mr314180pjf.1.1637132010579; Tue, 16 Nov 2021 22:53:30 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:44 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-15-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 14/29] 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 5b16d422b37d..659ec880d527 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -686,6 +686,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; @@ -870,6 +900,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. @@ -881,6 +916,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 17 06:43:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623843 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 66386C433FE for ; Wed, 17 Nov 2021 06:53:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4BFFD63222 for ; Wed, 17 Nov 2021 06:53:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233945AbhKQG4b (ORCPT ); Wed, 17 Nov 2021 01:56:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233425AbhKQG4a (ORCPT ); Wed, 17 Nov 2021 01:56:30 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDC48C061570 for ; Tue, 16 Nov 2021 22:53:32 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id b11-20020a17090acc0b00b001a9179dc89fso2617584pju.6 for ; Tue, 16 Nov 2021 22:53:32 -0800 (PST) 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=/e/xNL5It/1lgtF/0hW/wqDeGrof7OdzTDTZVLebiuk=; b=j8pwdmWpIEuKWCZTRLwhV0+yRYK3NzWzVXsmOkuXQzk/OITLmHs/oBnz8G1QX/wawM vs/bKWw6PmUCIDTWmNiky72jPMXuslIt8VIV+XhSIsXueL3rJKxq3aQVwCNkYiS+WskV KSFv80YxL2vasMGa26Vxi07q1hIQCE9jdF0u9iYfui/TDeSHIRYjdmEK2M9GYYIa/FZe 85y6czf4vcPBsfW3i3cPheItf4k/flPl08wAWMmMijyctX3SCjp28ZETpem0wYop5kpl 9e8t18BWLfV9DVa5XK0CrUpd+qB8wfxyE99Fg55DGuKFJtIgdotQ+TTftSsKefX8RpHb y22w== 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=/e/xNL5It/1lgtF/0hW/wqDeGrof7OdzTDTZVLebiuk=; b=DwgQU16RHJ7lVjpqXV7LirCxS0kIwf3p4DezAklOpgZDFTc99ueSJfmZ6sc8rf4ZuZ /xW0Z1zQAnY4xA7vzzSr1AT8ZfDhhAVb35QngF7gOiQSqlZPsQmF9mxTVhOJsZ6xd1dF dPCKlzNZ3+hwA2nCLeai2VjcVy0B9i2I2evwubNEibRievFaNJichi8ewwutcTWEzYt8 aOyKld1zn8C20BESn2rIYm1V97gEk4Q6ThxANNsSE5rMON7bGMjQ/ur/mHpjvNcAVOr2 kYY0H3xdgwypOsim9lSIvuU4NweBQfle37YLLmmQFkUucFNvCWuTxOa5CepQ39vCshfR 54Zg== X-Gm-Message-State: AOAM5307uGPtmTMxQi9zp0bdrdvs4xe5/VCuQj7BhpWsqiXx7jVVuSDR Wyckog39W5NPv1B31JEaa+67nMI5Yks= X-Google-Smtp-Source: ABdhPJx7YvjvD0kd3GLB1QJ2fQn3bsN7bXTUBhqNwC5FXsbEwUxuXuwxajhhtCcErhPR8bvE7NcX2/AhwX8= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90b:4d0a:: with SMTP id mw10mr6995057pjb.89.1637132012388; Tue, 16 Nov 2021 22:53:32 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:45 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-16-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 15/29] 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 | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 659ec880d527..35e458cc1e1d 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1886,16 +1886,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)) + /* Don't allow to change the reg after the first KVM_RUN. */ + if ((val != read_id_reg(vcpu, rd, raz)) && vcpu->arch.has_run_once) return -EINVAL; if (raz) - return 0; - - /* Don't allow to change the reg after the first KVM_RUN. */ - if (vcpu->arch.has_run_once) - return -EINVAL; + return (val == 0) ? 0 : -EINVAL; err = validate_id_reg(vcpu, rd, val); if (err) From patchwork Wed Nov 17 06:43:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623845 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 01FAEC433EF for ; Wed, 17 Nov 2021 06:53:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE11063222 for ; Wed, 17 Nov 2021 06:53:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233958AbhKQG4d (ORCPT ); Wed, 17 Nov 2021 01:56:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233478AbhKQG4c (ORCPT ); Wed, 17 Nov 2021 01:56:32 -0500 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 7320FC061570 for ; Tue, 16 Nov 2021 22:53:34 -0800 (PST) Received: by mail-pf1-x44a.google.com with SMTP id a127-20020a627f85000000b0047feae4a8d9so1098164pfd.19 for ; Tue, 16 Nov 2021 22:53:34 -0800 (PST) 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=psTrxtwmxcm5rWooRpuQaAR3nVgY0IlcZBqer69Z6tc=; b=UBXpZukQ5zrpL7SsqvdkAikI4NJd2P3kp46lyiX+NiYdeleul7dfOIZgS5AoRGDAT4 YT8MM21cnN42v5+kuoXy96L507UgNYucGn+LJ1AWuJFcPmKKav0LaCJxD6GZf2bPQ/qd 0thX01zvsbvmKoRZ4xTE+OFYeFCwKTEYUwP7iwEK5b7lYJGki0/dVul6DGDRieTcsONv oLw0mgBPd3y16/s9uWKcxKV2SvXuPMl+jA6dHY1bMwEeiOpYdg0teT7dZWlpwwrm6D7l VJgrzmujyZHFg1hc/Dx3ZdLy2MkcA/+Je/I/Bm8skN9QNUpa/DD3ABdw+EjxlPRfxwkN 9cqQ== 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=psTrxtwmxcm5rWooRpuQaAR3nVgY0IlcZBqer69Z6tc=; b=ea8Cw+hUzE1huMf1u+a2rkptpHMqLUpogKc1WAa5cH0RPNWjwLlDTtg/Ped5AzFiox ew0OS25muvV5GSrElHYyvytZNGyAkO2hN3mNE8Erued8Z9A06hDgAWpN5FwG/OOe3BmN X8tg/sjpLmfx4BEnP8c1glTx/1m9E02OJQ1oEDttckd7DwptiSY1Zh2HCg7OCe4wYQpT Pjms81THHajvEPGP2KMuPN3weg9736/kRSfm4vgthsSBq3nIqCiIQSl/E035FREwXePE H7RsGP9DAapir6Ca3TzH5mY8doLZqPzpoCGPiExQnPS8bt5N8UOKN47vhF62JmT/DKxc /O0Q== X-Gm-Message-State: AOAM533Gh1TPixQafx5DjugK9TyS+tSJHiKJTvMTGykTpTONzCORzImJ ZhpNphYlsbVCrl0zSAKFJgpbWzvwwys= X-Google-Smtp-Source: ABdhPJw8RPq/1UnPllZ/jYUntq5PJiPUgqtorRSt/EgY0E8lnwwEIidYAysxQZUIwRz0bj4FwGjlkwwQcX8= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90b:390a:: with SMTP id ob10mr6950955pjb.216.1637132013923; Tue, 16 Nov 2021 22:53:33 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:46 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-17-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 16/29] 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/include/asm/kvm_host.h | 2 + arch/arm64/kvm/arm.c | 3 + arch/arm64/kvm/sys_regs.c | 125 +++++++++++++++++++++++++++++- 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 72db73c79403..9dc9970a2d46 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -746,6 +746,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 2f03cbfefe67..19c4a78f931d 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -588,6 +588,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) if (!kvm_arm_vcpu_is_finalized(vcpu)) return -EPERM; + if (!kvm_vm_is_protected(kvm) && kvm_id_regs_consistency_check(vcpu)) + return -EPERM; + vcpu->arch.has_run_once = true; kvm_arm_vcpu_init_debug(vcpu); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 35e458cc1e1d..b848ecea0c59 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -841,9 +841,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, @@ -3460,10 +3457,106 @@ 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 = __read_id_reg(vcpu, 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 = __read_id_reg(vcpu, 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, err; + const struct feature_frac *frac; + + /* + * 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; +} + 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]; @@ -3472,6 +3565,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 17 06:43:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623847 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 79522C433EF for ; Wed, 17 Nov 2021 06:53:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5C23663232 for ; Wed, 17 Nov 2021 06:53:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233966AbhKQG4g (ORCPT ); Wed, 17 Nov 2021 01:56:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233478AbhKQG4d (ORCPT ); Wed, 17 Nov 2021 01:56:33 -0500 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 B9526C061570 for ; Tue, 16 Nov 2021 22:53:35 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id e4-20020a170902b78400b00143c2e300ddso554560pls.17 for ; Tue, 16 Nov 2021 22:53:35 -0800 (PST) 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=ngr4hW3OQO25yW6Z4QPAPb06Z9XdAyw5TZaaZf4PQgw=; b=d3k4dD7DeKSt+dZdlIRs7mm6LnVHJVt6MJBZO8D+xJd0gunFXbHBYuDqyARKCcDfGh lPKrp5Qqr21sujBqw3NCYXc3O43g3ZYZnFgqWmbcB4gG1evEu0MvTQuF7I/6Lzlf0clV TRzdRmPYVy9yUTIciVPd1fE3vQ+EA6smRJ9+4HS5nnIz6N4rpcGlS1yb6+kvIsR36f54 uaj8JsNWz14aQ5SL8POTavCae1N9dzpidU/epMp9T9i+QrevGG54XO7wmqkbd1YGLTT5 px1AJdtDdiH9/WKiDIhjGHBLJKS375Z4uLZVXZ85mhrHMhrAW3Gl+0Ukb1ZERUVRfoeJ CpBg== 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=ngr4hW3OQO25yW6Z4QPAPb06Z9XdAyw5TZaaZf4PQgw=; b=76lxkUN/UuDafLx3uZwNGKj0OXA9pignFdUh42LknzhjgXodmSvJIhvckTAXzPbQFB tfmpfgbcQO+oEcpFQwrOa5Igahkbghg6oujPFQzDr2j+N6EQXYI5Tvb1/PTOPrPhitZF KEskZQdNc2UOi8V8V42Y70WE1hGKe466hUOg5xNCOzuYgwEbYlBQUj3HoPyWgbuHyT+7 R5hjDtmC6HugMp95MUDU6RmRXHSxH2SnZvGJJfjIIlL4UmJKMc5TvInJ2ObntoMRgHJt 2prKvnqHugoJVZsGd/H4AHj3+hgV/to70L5BwS3M45npGq+kFfpe04lRCiM48u5jVzGu UvXA== X-Gm-Message-State: AOAM531YQoS/JWWx/wl5fxRZv+RS+sESNH+DZh3fM4jT2ENIE8tSFN1r 2SyEad5xx6Nw/Hqj+iLvnx5wxXUKtBU= X-Google-Smtp-Source: ABdhPJzMTnMi5u59+kPQqdzefOhB/wBSglPLL+HhxruNL4kxrs/Un5EiZfa6yoeZ23QBUnLS38Laa1NvHts= 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:22c4:b0:141:deda:a744 with SMTP id y4-20020a17090322c400b00141dedaa744mr53364712plg.25.1637132015299; Tue, 16 Nov 2021 22:53:35 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:47 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-18-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 17/29] KVM: arm64: Introduce KVM_CAP_ARM_ID_REG_CONFIGURABLE 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_CONFIGURABLE 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 aeeb071c7688..022effa4454d 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7484,3 +7484,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_CONFIGURABLE +------------------------------------ + +: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 19c4a78f931d..a54579e7ac91 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -215,6 +215,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_CONFIGURABLE: r = 1; break; case KVM_CAP_SET_GUEST_DEBUG2: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 1daa45268de2..9697c06a7f5b 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1131,6 +1131,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_ARM_MTE 205 #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206 +#define KVM_CAP_ARM_ID_REG_CONFIGURABLE 207 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Wed Nov 17 06:43:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623851 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 D21B8C4332F for ; Wed, 17 Nov 2021 06:53:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B3C6563237 for ; Wed, 17 Nov 2021 06:53:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233476AbhKQG4h (ORCPT ); Wed, 17 Nov 2021 01:56:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233959AbhKQG4f (ORCPT ); Wed, 17 Nov 2021 01:56:35 -0500 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 56EC0C061570 for ; Tue, 16 Nov 2021 22:53:37 -0800 (PST) Received: by mail-pf1-x44a.google.com with SMTP id l7-20020a622507000000b00494608c84a4so1128793pfl.6 for ; Tue, 16 Nov 2021 22:53:37 -0800 (PST) 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=RHoCEP+RyOR/HV9iNPiomfNv7ul8MH2rBqrRr7QAURo=; b=bSlIdu0vgD02Z71Rv6UYf3entcYwXwLIe9uzKVa9d84HVgK1hz+qp3Zq2nUwu0Gho7 vpMyMGDIbDOj2xS1heR7meQPaElPePl8GwKg3DTQ/1xilReuAK68rSf3ouhkk3FWxqpz aHMe0gNu0xPNduP4ZwA1g4RbTwj5TOrx3ktbhizcB7BdO9fEFu8B48P289ky+JZNLJVR ZGkFoQ9RnZfMDlUv2aaBgeR1sTFdtBycQIEEV7f2dXcmxIBERDkfAQxTy4MsXQ/onk9l MF9e0iXMrSerSQIep7G8hdQtjNJjSJ+woXKhCsjf9KVEGFZEfJNNVs2lYruWm9uHyWD0 F3Tw== 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=RHoCEP+RyOR/HV9iNPiomfNv7ul8MH2rBqrRr7QAURo=; b=n5M5eAHfcgPGN3cO4ciDiEplMYhydihfGYTE0OxoOmvY3DKdK7f/pYvrRmnYtF5Pmt Yinmo4+q14AykaLDAadN9iPaF0sLUqrTeXPLs1O0xDwGM59HWlhyyCzK6xJm710rBlUz 2zq1J+xiZ5sVmbxkgYjz32kkq97D5plfJNAq258jF+TQgJhm9eFnUrSbJRkXCv1+LVJN uhsR+X1AHzVJfXUASTUyYVO6gK7Q+2z2nSrAkZIgiwZpowBWu/EvP2fecMA/4YxMhw11 hk7tdjYZwxkAWnJP8n3oQp0wXG/t8jluc4RkZKx3XwwlhyRiy7Veo2ac94hhPeNd+SCH 6ZWQ== X-Gm-Message-State: AOAM533MOQVeeuvL5kUrY+JKj6wDeoC5IB8BZxXVQwVr7hmZfpOAY/3P YTQpdUMXdCncnGZEWmwiVPeHsnYDrZ0= X-Google-Smtp-Source: ABdhPJzRBrBQ3yiWgcfeQXijGQ8XxjTXwR/EIFMKT2Bq8TAtIEXtizZ6lbfAezu4UsXdDLo3yiwO6usTUYA= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a62:8c55:0:b0:49f:df22:c4ca with SMTP id m82-20020a628c55000000b0049fdf22c4camr46411533pfd.11.1637132016850; Tue, 16 Nov 2021 22:53:36 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:48 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-19-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 18/29] KVM: arm64: Add kunit test for ID register validation 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 kunit tests for functions that are used for validation of ID registers and CONFIG_KVM_KUNIT_TEST option to enable the tests. Since those tests only cover ID register validation so far, only a few lines of change are needed in the default arm64.py to run all of those tests as follows. ----------------------------------------------------------------------- $ diff tools/testing/kunit/qemu_configs/arm64.py arm64_kvm_min.py 4a5,7 > CONFIG_VIRTUALIZATION=y > CONFIG_KVM=y > CONFIG_KVM_KUNIT_TEST=y 12c15 < extra_qemu_params=['-machine virt', '-cpu cortex-a57']) --- > extra_qemu_params=['-M virt,virtualization=on,mte=on', '-cpu max,sve=on']) $ tools/testing/kunit/kunit.py run --timeout=60 --jobs=16 --arch=arm64 --cross_compile=aarch64-linux-gnu- --qemu_config arm64_kvm_min.py [19:58:09] Configuring KUnit Kernel ... [19:58:09] Building KUnit Kernel ... Populating config with: $ make ARCH=arm64 olddefconfig CROSS_COMPILE=aarch64-linux-gnu- O=.kunit Building with: $ make ARCH=arm64 --jobs=16 CROSS_COMPILE=aarch64-linux-gnu- O=.kunit [19:58:12] Starting KUnit Kernel (1/1)... [19:58:12] ============================================================ Running tests with: $ qemu-system-aarch64 -nodefaults -m 1024 -kernel .kunit/arch/arm64/boot/Image.gz -append 'mem=1G console=tty kunit_shutdown=halt console=ttyAMA0 kunit_shutdown=reboot' -no-reboot -nographic -serial stdio -M virt,virtualization=on,mte=on -cpu max,sve=on [19:58:14] ========== kvm-sys-regs-test-suite (14 subtests) =========== [19:58:14] [PASSED] arm64_check_feature_one_test [19:58:14] [PASSED] arm64_check_features_test [19:58:14] [PASSED] vcpu_id_reg_feature_frac_check_test [19:58:14] [PASSED] validate_id_aa64mmfr0_tgran2_test [19:58:14] [PASSED] validate_id_aa64mmfr0_tgran2_test [19:58:14] [PASSED] validate_id_aa64mmfr0_tgran2_test [19:58:14] [PASSED] validate_id_aa64pfr0_el1_test [19:58:14] [PASSED] validate_id_aa64pfr1_el1_test [19:58:14] [PASSED] validate_id_aa64isar0_el1_test [19:58:14] [PASSED] validate_id_aa64isar1_el1_test [19:58:14] [PASSED] validate_id_aa64mmfr0_el1_test [19:58:14] [PASSED] validate_id_aa64dfr0_el1_test [19:58:14] [PASSED] validate_id_dfr0_el1_test [19:58:14] [PASSED] validate_mvfr1_el1_test [19:58:14] ============= [PASSED] kvm-sys-regs-test-suite ============= [19:58:14] ============================================================ [19:58:14] Testing complete. Passed: 14, Failed: 0, Crashed: 0, Skipped: 0, Errors: 0 [19:58:14] Elapsed time: 4.644s total, 0.002s configuring, 2.959s building, 1.682s running ----------------------------------------------------------------------- Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/Kconfig | 11 + arch/arm64/kvm/sys_regs.c | 4 + arch/arm64/kvm/sys_regs_test.c | 871 +++++++++++++++++++++++++++++++++ 3 files changed, 886 insertions(+) create mode 100644 arch/arm64/kvm/sys_regs_test.c diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 8ffcbe29395e..48fbdd17b2fd 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -54,4 +54,15 @@ config NVHE_EL2_DEBUG If unsure, say N. +config KVM_KUNIT_TEST + bool "KUnit tests for KVM on ARM64 processors" if !KUNIT_ALL_TESTS + depends on KVM && KUNIT + default KUNIT_ALL_TESTS + help + Say Y here to enable KUnit tests for the KVM on ARM64. + Only useful for KVM/ARM development and are not for inclusion into + a production build. + + If unsure, say N. + endif # VIRTUALIZATION diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index b848ecea0c59..2f96103fc0d2 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -3630,3 +3630,7 @@ void kvm_sys_reg_table_init(void) id_reg_info_init_all(); } + +#if IS_ENABLED(CONFIG_KVM_KUNIT_TEST) +#include "sys_regs_test.c" +#endif diff --git a/arch/arm64/kvm/sys_regs_test.c b/arch/arm64/kvm/sys_regs_test.c new file mode 100644 index 000000000000..8d27c7c361fb --- /dev/null +++ b/arch/arm64/kvm/sys_regs_test.c @@ -0,0 +1,871 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KUnit tests for arch/arm64/kvm/sys_regs.c. + */ + +#include +#include +#include +#include +#include +#include "asm/sysreg.h" + +/* Some utilities for minimal vcpu/kvm setup for existing testings. */ +static struct kvm_vcpu *test_vcpu_init(struct kunit *test, u32 id, + struct kvm *kvm) +{ + struct kvm_vcpu *vcpu; + + vcpu = kunit_kzalloc(test, sizeof(*vcpu), GFP_KERNEL); + if (!vcpu) + return NULL; + + vcpu->cpu = -1; + vcpu->kvm = kvm; + vcpu->vcpu_id = id; + + return vcpu; +} + +static void test_vcpu_fini(struct kunit *test, struct kvm_vcpu *vcpu) +{ + kunit_kfree(test, vcpu); +} + +static struct kvm *test_kvm_init(struct kunit *test) +{ + struct kvm *kvm; + + kvm = kunit_kzalloc(test, sizeof(struct kvm), GFP_KERNEL); + if (!kvm) + return NULL; + + return kvm; +} + +static void test_kvm_fini(struct kunit *test, struct kvm *kvm) +{ + kunit_kfree(test, kvm); +} + +static struct kvm_vcpu *test_kvm_vcpu_init(struct kunit *test) +{ + struct kvm_vcpu *vcpu; + struct kvm *kvm; + + kvm = test_kvm_init(test); + if (!kvm) + return NULL; + + vcpu = test_vcpu_init(test, 0, kvm); + if (!vcpu) { + test_kvm_fini(test, kvm); + return NULL; + } + return vcpu; +} + +static void test_kvm_vcpu_fini(struct kunit *test, struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + + test_vcpu_fini(test, vcpu); + if (kvm) + test_kvm_fini(test, kvm); +} + +/* Test parameter information to test arm64_check_feature_one() */ +struct check_feature_one_test { + enum feature_check_type type; + int value; + int limit; + int expected; +}; + +struct check_feature_one_test feature_one_params[] = { + {FCT_LOWER_SAFE, 0, 0, 0}, + {FCT_LOWER_SAFE, -1, -1, 0}, + {FCT_LOWER_SAFE, 1, 1, 0}, + {FCT_LOWER_SAFE, 1, 2, 0}, + {FCT_LOWER_SAFE, -1, 0, 0}, + {FCT_LOWER_SAFE, 2, 1, -1}, + {FCT_LOWER_SAFE, -1, -2, -1}, + + {FCT_HIGHER_SAFE, 0, 0, 0}, + {FCT_HIGHER_SAFE, -1, -1, 0}, + {FCT_HIGHER_SAFE, 1, 1, 0}, + {FCT_HIGHER_SAFE, 1, 2, -1}, + {FCT_HIGHER_SAFE, -1, 0, -1}, + {FCT_HIGHER_SAFE, 2, 1, 0}, + {FCT_HIGHER_SAFE, -1, -2, 0}, + + {FCT_HIGHER_OR_ZERO_SAFE, 0, 0, 0}, + {FCT_HIGHER_OR_ZERO_SAFE, -1, -1, 0}, + {FCT_HIGHER_OR_ZERO_SAFE, 1, 1, 0}, + {FCT_HIGHER_OR_ZERO_SAFE, 1, 2, -1}, + {FCT_HIGHER_OR_ZERO_SAFE, -1, 0, -1}, + {FCT_HIGHER_OR_ZERO_SAFE, 2, 1, 0}, + {FCT_HIGHER_OR_ZERO_SAFE, -1, -2, 0}, + {FCT_HIGHER_OR_ZERO_SAFE, 0, 2, 0}, + + {FCT_EXACT, 0, 0, 0}, + {FCT_EXACT, -1, -1, 0}, + {FCT_EXACT, 1, 1, 0}, + {FCT_EXACT, 1, 2, -1}, + {FCT_EXACT, -1, 0, -1}, + {FCT_EXACT, 2, 1, -1}, + {FCT_EXACT, -1, -2, -1}, + + {FCT_IGNORE, 0, 0, 0}, + {FCT_IGNORE, -1, -1, 0}, + {FCT_IGNORE, 1, 1, 0}, + {FCT_IGNORE, 1, 2, 0}, + {FCT_IGNORE, -1, 0, 0}, + {FCT_IGNORE, 2, 1, 0}, + {FCT_IGNORE, -1, -2, 0}, +}; + +static void feature_one_case_to_desc(struct check_feature_one_test *t, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "type:%x, value:%d, limit:%d\n", t->type, t->value, t->limit); +} + +void arm64_check_feature_one_test(struct kunit *test) +{ + const struct check_feature_one_test *ft = test->param_value; + + KUNIT_EXPECT_EQ(test, + arm64_check_feature_one(ft->type, ft->value, ft->limit), + ft->expected); +} + +KUNIT_ARRAY_PARAM(feature_one, feature_one_params, feature_one_case_to_desc); + + +/* Test parameter information to test arm64_check_features */ +struct check_features_test { + u64 check_types; + u64 value; + u64 limit; + int expected; +}; + +#define U_FEAT_TEST(shift, type, value, limit, exp) \ + {U_FCT(shift, type), (u64)value << shift, (u64)limit << shift, exp} + +#define S_FEAT_TEST(shift, type, value, limit, exp) \ + {S_FCT(shift, type), (u64)value << shift, (u64)limit << shift, exp} + +struct check_features_test features_params[] = { + /* Unsigned */ + U_FEAT_TEST(0, FCT_LOWER_SAFE, 1, 2, 0), + U_FEAT_TEST(0, FCT_HIGHER_SAFE, 1, 2, -E2BIG), + U_FEAT_TEST(0, FCT_HIGHER_OR_ZERO_SAFE, 1, 2, -E2BIG), + U_FEAT_TEST(0, FCT_EXACT, 1, 2, -E2BIG), + U_FEAT_TEST(0, FCT_IGNORE, 1, 2, 0), + U_FEAT_TEST(0, FCT_LOWER_SAFE, 1, 0xf, 0), + U_FEAT_TEST(0, FCT_HIGHER_SAFE, 1, 0xf, -E2BIG), + U_FEAT_TEST(0, FCT_HIGHER_OR_ZERO_SAFE, 1, 0xf, -E2BIG), + U_FEAT_TEST(0, FCT_EXACT, 1, 0xf, -E2BIG), + U_FEAT_TEST(0, FCT_IGNORE, 1, 0xf, 0), + U_FEAT_TEST(60, FCT_LOWER_SAFE, 1, 2, 0), + U_FEAT_TEST(60, FCT_HIGHER_SAFE, 1, 2, -E2BIG), + U_FEAT_TEST(60, FCT_HIGHER_OR_ZERO_SAFE, 1, 2, -E2BIG), + U_FEAT_TEST(60, FCT_EXACT, 1, 2, -E2BIG), + U_FEAT_TEST(60, FCT_IGNORE, 1, 2, 0), + U_FEAT_TEST(60, FCT_LOWER_SAFE, 1, 0xf, 0), + U_FEAT_TEST(60, FCT_HIGHER_SAFE, 1, 0xf, -E2BIG), + U_FEAT_TEST(60, FCT_HIGHER_OR_ZERO_SAFE, 1, 0xf, -E2BIG), + U_FEAT_TEST(60, FCT_EXACT, 1, 0xf, -E2BIG), + U_FEAT_TEST(60, FCT_IGNORE, 1, 0xf, 0), + + /* Signed */ + S_FEAT_TEST(0, FCT_LOWER_SAFE, 1, 2, 0), + S_FEAT_TEST(0, FCT_HIGHER_SAFE, 1, 2, -E2BIG), + S_FEAT_TEST(0, FCT_HIGHER_OR_ZERO_SAFE, 1, 2, -E2BIG), + S_FEAT_TEST(0, FCT_EXACT, 1, 2, -E2BIG), + S_FEAT_TEST(0, FCT_IGNORE, 1, 2, 0), + S_FEAT_TEST(0, FCT_LOWER_SAFE, 1, 0xf, -E2BIG), + S_FEAT_TEST(0, FCT_HIGHER_SAFE, 1, 0xf, 0), + S_FEAT_TEST(0, FCT_HIGHER_OR_ZERO_SAFE, 1, 0xf, 0), + S_FEAT_TEST(0, FCT_EXACT, 1, 0xf, -E2BIG), + S_FEAT_TEST(0, FCT_IGNORE, 1, 0xf, 0), + S_FEAT_TEST(60, FCT_LOWER_SAFE, 1, 2, 0), + S_FEAT_TEST(60, FCT_HIGHER_SAFE, 1, 2, -E2BIG), + S_FEAT_TEST(60, FCT_HIGHER_OR_ZERO_SAFE, 1, 2, -E2BIG), + S_FEAT_TEST(60, FCT_EXACT, 1, 2, -E2BIG), + S_FEAT_TEST(60, FCT_IGNORE, 1, 2, 0), + S_FEAT_TEST(60, FCT_LOWER_SAFE, 1, 0xf, -E2BIG), + S_FEAT_TEST(60, FCT_HIGHER_SAFE, 1, 0xf, 0), + S_FEAT_TEST(60, FCT_HIGHER_OR_ZERO_SAFE, 1, 0xf, 0), + S_FEAT_TEST(60, FCT_EXACT, 1, 0xf, -E2BIG), + S_FEAT_TEST(60, FCT_IGNORE, 1, 0xf, 0), +}; + +static void features_case_to_desc(struct check_features_test *t, char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "check_types:0x%llx, value:0x%llx, limit:0x%llx\n", + t->check_types, t->value, t->limit); +} + +KUNIT_ARRAY_PARAM(features, features_params, features_case_to_desc); + + +void arm64_check_features_test(struct kunit *test) +{ + const struct check_features_test *ft = test->param_value; + + KUNIT_EXPECT_EQ(test, + arm64_check_features(ft->check_types, ft->value, ft->limit), + ft->expected); +} + + +/* Test parameter information to test vcpu_id_reg_feature_frac_check */ +struct feat_info { + u32 id; + u32 shift; + u32 value; + u32 limit; + u8 check_type; +}; + +struct frac_check_test { + struct feat_info feat; + struct feat_info frac_feat; + int ret; +}; + +#define FEAT(id, shift, value, limit, type) {id, shift, value, limit, type} + +struct frac_check_test frac_params[] = { + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 2, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 1, 1, U_FCT(0, FCT_LOWER_SAFE)), + 0, + }, + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 2, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 1, 2, U_FCT(0, FCT_LOWER_SAFE)), + 0, + }, + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 2, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 2, 1, U_FCT(0, FCT_LOWER_SAFE)), + 0, + }, + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 1, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 1, 1, U_FCT(0, FCT_LOWER_SAFE)), + 0, + }, + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 1, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 1, 2, U_FCT(0, FCT_LOWER_SAFE)), + 0, + }, + { + FEAT(SYS_ID_AA64PFR1_EL1, 12, 1, 1, U_FCT(0, FCT_LOWER_SAFE)), + FEAT(SYS_ID_AA64PFR1_EL1, 32, 2, 1, U_FCT(0, FCT_LOWER_SAFE)), + -E2BIG, + }, + +}; + +static void frac_case_to_desc(struct frac_check_test *t, char *desc) +{ + struct feat_info *feat = &t->feat; + struct feat_info *frac = &t->frac_feat; + + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "feat - shift:%d, val:%d, lim:%d, frac - shift:%d, val:%d, lim:%d, type:%x\n", + feat->shift, feat->value, feat->limit, + frac->shift, frac->value, frac->limit, frac->check_type); +} + +KUNIT_ARRAY_PARAM(frac, frac_params, frac_case_to_desc); + +static void vcpu_id_reg_feature_frac_check_test(struct kunit *test) +{ + struct kvm_vcpu *vcpu; + u32 id, frac_id; + struct id_reg_info id_data, frac_id_data; + struct id_reg_info *idr, *frac_idr; + struct feature_frac frac_data, *frac = &frac_data; + const struct frac_check_test *frct = test->param_value; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id = frct->feat.id; + frac_id = frct->frac_feat.id; + + frac->id = id; + frac->shift = frct->feat.shift; + frac->frac_id = frac_id; + frac->frac_shift = frct->frac_feat.shift; + frac->frac_ftr_check = frct->frac_feat.check_type; + + idr = GET_ID_REG_INFO(id); + frac_idr = GET_ID_REG_INFO(frac_id); + + /* Save the original id_reg_info (and restore later) */ + memcpy(&id_data, idr, sizeof(id_data)); + memcpy(&frac_id_data, frac_idr, sizeof(frac_id_data)); + + /* The id could be same as the frac_id */ + idr->vcpu_limit_val = (u64)frct->feat.limit << frac->shift; + frac_idr->vcpu_limit_val |= + (u64)frct->frac_feat.limit << frac->frac_shift; + + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = + (u64)frct->feat.value << frac->shift; + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(frac_id)) |= + (u64)frct->frac_feat.value << frac->frac_shift; + + KUNIT_EXPECT_EQ(test, + vcpu_id_reg_feature_frac_check(vcpu, frac), + frct->ret); + + test_kvm_vcpu_fini(test, vcpu); + + /* Restore id_reg_info */ + memcpy(idr, &id_data, sizeof(id_data)); + memcpy(frac_idr, &frac_id_data, sizeof(frac_id_data)); +} + +/* + * Test parameter information to test validate_id_aa64mmfr0_tgran2 + * and validate_id_aa64mmfr0_el1_test. + */ +struct tgran_test { + int gran2_field; + int gran2; + int gran2_lim; + int gran1; + int gran1_lim; + int ret; +}; + +struct tgran_test tgran4_2_test_params[] = { + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 2, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 2, 1, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 1, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 0, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 0, 1, -1, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 0, 1, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 0, 2, -1, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 0, 2, 1, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 1, 0, 0, -1, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 1, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 2, 0, 0, -1, -E2BIG}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 2, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN4_2_SHIFT, 2, 0, 0, 2, 0}, +}; + +struct tgran_test tgran64_2_test_params[] = { + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 2, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 2, 1, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 1, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 0, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 0, 1, -1, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 0, 1, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 0, 2, -1, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 0, 2, 1, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 1, 0, 0, -1, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 1, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 2, 0, 0, -1, -E2BIG}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 2, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN64_2_SHIFT, 2, 0, 0, 2, 0}, +}; + +struct tgran_test tgran16_2_test_params[] = { + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 2, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 2, 1, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 1, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 0, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 0, 1, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 0, 1, 1, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 0, 2, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 0, 2, 2, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 1, 0, 0, 0, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 1, 0, 0, 1, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 2, 0, 0, 0, -E2BIG}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 2, 0, 0, 1, 0}, + {ID_AA64MMFR0_TGRAN16_2_SHIFT, 2, 0, 0, 2, 0}, +}; + +static void tgran2_case_to_desc(struct tgran_test *t, char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "gran2(field=%d): val=%d, lim=%d gran1: val=%d limit=%d\n", + t->gran2_field, t->gran2, t->gran2_lim, + t->gran1, t->gran1_lim); +} + +KUNIT_ARRAY_PARAM(tgran4_2, tgran4_2_test_params, tgran2_case_to_desc); +KUNIT_ARRAY_PARAM(tgran64_2, tgran64_2_test_params, tgran2_case_to_desc); +KUNIT_ARRAY_PARAM(tgran16_2, tgran16_2_test_params, tgran2_case_to_desc); + +#define MAKE_MMFR0_TGRAN(shift1, gran1, shift2, gran2) \ + (((u64)((gran1) & 0xf) << (shift1)) | \ + ((u64)((gran2) & 0xf) << (shift2))) + +static int tgran2_to_tgran1_shift(int tgran2_shift) +{ + int tgran1_shift = -1; + + switch (tgran2_shift) { + case ID_AA64MMFR0_TGRAN4_2_SHIFT: + tgran1_shift = ID_AA64MMFR0_TGRAN4_SHIFT; + break; + case ID_AA64MMFR0_TGRAN64_2_SHIFT: + tgran1_shift = ID_AA64MMFR0_TGRAN64_SHIFT; + break; + case ID_AA64MMFR0_TGRAN16_2_SHIFT: + tgran1_shift = ID_AA64MMFR0_TGRAN16_SHIFT; + break; + default: + break; + } + + return tgran1_shift; +} + +static void validate_id_aa64mmfr0_tgran2_test(struct kunit *test) +{ + const struct tgran_test *t = test->param_value; + int shift1, shift2; + u64 v, lim; + + shift2 = t->gran2_field; + shift1 = tgran2_to_tgran1_shift(shift2); + v = MAKE_MMFR0_TGRAN(shift1, t->gran1, shift2, t->gran2); + lim = MAKE_MMFR0_TGRAN(shift1, t->gran1_lim, shift2, t->gran2_lim); + + KUNIT_EXPECT_EQ(test, aa64mmfr0_tgran2_check(shift2, v, lim), t->ret); +} + +static void validate_id_aa64pfr0_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64PFR0_EL1); + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x000010000; /* ASIMD = 0, FP = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x000100000; /* ASIMD = 1, FP = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x000ff0000; /* ASIMD = 0xf, FP = 0xf */ + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x100000000; /* SVE =1, ASIMD = 0, FP = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + if (!system_supports_sve()) { + test_kvm_vcpu_fini(test, vcpu); + kunit_skip(test, "No SVE support. Partial skip)"); + /* Not reached */ + } + + vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE; + + v = 0x100000000; /* SVE =1, ASIMD = 0, FP = 0 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x100ff0000; /* SVE =1, ASIMD = 0, FP = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + vcpu->arch.flags &= ~KVM_ARM64_GUEST_HAS_SVE; + + v = 0x1000000; /* GIC = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + vcpu->kvm->arch.vgic.in_kernel = true; + v = 0x1000000; /* GIC = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + vcpu->kvm->arch.vgic.vgic_model = KVM_DEV_TYPE_ARM_VGIC_V2; + v = 0x1000000; /* GIC = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0; /* GIC = 0 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + v = 0x1000000; /* GIC = 1 */ + vcpu->kvm->arch.vgic.vgic_model = KVM_DEV_TYPE_ARM_VGIC_V3; + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr0_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_aa64pfr1_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64PFR1_EL1); + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr1_el1(vcpu, id_reg, v), 0); + + v = 0x100; /* MTE = 1*/ + KUNIT_EXPECT_NE(test, validate_id_aa64pfr1_el1(vcpu, id_reg, v), 0); + + if (!system_supports_mte()) { + test_kvm_vcpu_fini(test, vcpu); + kunit_skip(test, "(No MTE support. Partial skip)"); + /* Not reached */ + } + + vcpu->kvm->arch.mte_enabled = true; + + v = 0x100; /* MTE = 1*/ + KUNIT_EXPECT_EQ(test, validate_id_aa64pfr1_el1(vcpu, id_reg, v), 0); + + v = 0x0; + vcpu->kvm->arch.mte_enabled = true; + KUNIT_EXPECT_NE(test, validate_id_aa64pfr1_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_aa64isar0_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64ISAR0_EL1); + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x01000000000; /* SM4 = 0, SM3 = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x10000000000; /* SM4 = 1, SM3 = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x11000000000; /* SM3 = SM4 = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x000000100; /* SHA2 = 0, SHA1 = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x000001000; /* SHA2 = 1, SHA1 = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x000001100; /* SHA2 = 1, SHA1 = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x100002000; /* SHA3 = 1, SHA2 = 2 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x000002000; /* SHA3 = 0, SHA2 = 2 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x100001000; /* SHA3 = 1, SHA2 = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x200000000; /* SHA3 = 2, SHA1 = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x200001100; /* SHA3 = 2, SHA2= 1, SHA1 = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + v = 0x300003300; /* SHA3 = 3, SHA2 = 3, SHA1 = 3 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar0_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_aa64isar1_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64ISAR1_EL1); + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x11000110; /* GPI = 1, GPA = 1, API = 1, APA = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x11000100; /* GPI = 1, GPA = 1, API = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x11000010; /* GPI = 1, GPA = 1, APA = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x10000110; /* GPI = 1, API = 1, APA = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x01000110; /* GPA = 1, API = 1, APA = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + if (!system_has_full_ptr_auth()) { + test_kvm_vcpu_fini(test, vcpu); + kunit_skip(test, "(No PTRAUTH support. Partial skip)"); + /* Not reached */ + } + + vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_PTRAUTH; + + v = 0x10000100; /* GPI = 1, API = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x10000010; /* GPI = 1, APA = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x01000100; /* GPA = 1, API = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0x01000010; /* GPA = 1, APA = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + v = 0; + KUNIT_EXPECT_NE(test, validate_id_aa64isar1_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_aa64mmfr0_el1_test(struct kunit *test) +{ + struct id_reg_info id_data, *id_reg; + const struct tgran_test *t4, *t64, *t16; + struct kvm_vcpu *vcpu; + int field4, field4_2, field64, field64_2, field16, field16_2; + u64 v, v4, lim4, v64, lim64, v16, lim16; + int i, j, ret; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64MMFR0_EL1); + + /* Save the original id_reg_info (and restore later) */ + memcpy(&id_data, id_reg, sizeof(id_data)); + + vcpu = test_kvm_vcpu_init(test); + + t4 = test->param_value; + field4_2 = t4->gran2_field; + field4 = tgran2_to_tgran1_shift(field4_2); + v4 = MAKE_MMFR0_TGRAN(field4, t4->gran1, field4_2, t4->gran2); + lim4 = MAKE_MMFR0_TGRAN(field4, t4->gran1_lim, field4_2, t4->gran2_lim); + + /* + * For each given gran4_2 params, test validate_id_aa64mmfr0_el1 + * with each of tgran64_2 and tgran16_2 params. + */ + for (i = 0; i < ARRAY_SIZE(tgran64_2_test_params); i++) { + t64 = &tgran64_2_test_params[i]; + field64_2 = t64->gran2_field; + field64 = tgran2_to_tgran1_shift(field64_2); + v64 = MAKE_MMFR0_TGRAN(field64, t64->gran1, + field64_2, t64->gran2); + lim64 = MAKE_MMFR0_TGRAN(field64, t64->gran1_lim, + field64_2, t64->gran2_lim); + + for (j = 0; j < ARRAY_SIZE(tgran16_2_test_params); j++) { + t16 = &tgran16_2_test_params[j]; + + field16_2 = t16->gran2_field; + field16 = tgran2_to_tgran1_shift(field16_2); + v16 = MAKE_MMFR0_TGRAN(field16, t16->gran1, + field16_2, t16->gran2); + lim16 = MAKE_MMFR0_TGRAN(field16, t16->gran1_lim, + field16_2, t16->gran2_lim); + + /* Build id_aa64mmfr0_el1 from tgran16/64/4 values */ + v = v16 | v64 | v4; + id_reg->vcpu_limit_val = lim16 | lim64 | lim4; + + ret = t4->ret ? t4->ret : t64->ret; + ret = ret ? ret : t16->ret; + KUNIT_EXPECT_EQ(test, + validate_id_aa64mmfr0_el1(vcpu, id_reg, v), + ret); + } + } + + /* Restore id_reg_info */ + memcpy(id_reg, &id_data, sizeof(id_data)); + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_aa64dfr0_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + id_reg = GET_ID_REG_INFO(SYS_ID_AA64DFR0_EL1); + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x10001000; /* CTX_CMPS = 2, BRPS = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x20001000; /* CTX_CMPS = 2, BRPS = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + v = 0xf00; /* PMUVER = 0xf */ + KUNIT_EXPECT_EQ(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x100; /* PMUVER = 1 */ + KUNIT_EXPECT_NE(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + set_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features); + + v = 0x100; /* PMUVER = 1 */ + KUNIT_EXPECT_EQ(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x0; /* PMUVER = 0 */ + KUNIT_EXPECT_NE(test, validate_id_aa64dfr0_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_id_dfr0_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + id_reg = GET_ID_REG_INFO(SYS_ID_DFR0_EL1); + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + v = 0; + KUNIT_EXPECT_EQ(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0xf000000; /* PERFMON = 0xf */ + KUNIT_EXPECT_EQ(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x1000000; /* PERFMON = 1 */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x2000000; /* PERFMON = 2 */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x3000000; /* PERFMON = 3 */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + set_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features); + + v = 0x1000000; /* PERFMON = 1 */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x2000000; /* PERFMON = 2 */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0x3000000; /* PERFMON = 3 */ + KUNIT_EXPECT_EQ(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + v = 0xf000000; /* PERFMON = 0xf */ + KUNIT_EXPECT_NE(test, validate_id_dfr0_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void validate_mvfr1_el1_test(struct kunit *test) +{ + struct id_reg_info *id_reg; + struct kvm_vcpu *vcpu; + u64 v; + + id_reg = GET_ID_REG_INFO(SYS_MVFR1_EL1); + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + v = 0; + KUNIT_EXPECT_EQ(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = 0x2100000; /* FPHP = 2, SIMDHP = 1 */ + KUNIT_EXPECT_EQ(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = 0x3200000; /* FPHP = 3, SIMDHP = 2 */ + KUNIT_EXPECT_EQ(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = 0x1100000; /* FPHP = 1, SIMDHP = 1 */ + KUNIT_EXPECT_NE(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = 0x2200000; /* FPHP = 2, SIMDHP = 2 */ + KUNIT_EXPECT_NE(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = 0x3300000; /* FPHP = 3, SIMDHP = 3 */ + KUNIT_EXPECT_NE(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + v = (u64)-1; + KUNIT_EXPECT_NE(test, validate_mvfr1_el1(vcpu, id_reg, v), 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static struct kunit_case kvm_sys_regs_test_cases[] = { + KUNIT_CASE_PARAM(arm64_check_feature_one_test, feature_one_gen_params), + KUNIT_CASE_PARAM(arm64_check_features_test, features_gen_params), + KUNIT_CASE_PARAM(vcpu_id_reg_feature_frac_check_test, frac_gen_params), + KUNIT_CASE_PARAM(validate_id_aa64mmfr0_tgran2_test, tgran4_2_gen_params), + KUNIT_CASE_PARAM(validate_id_aa64mmfr0_tgran2_test, tgran64_2_gen_params), + KUNIT_CASE_PARAM(validate_id_aa64mmfr0_tgran2_test, tgran16_2_gen_params), + KUNIT_CASE(validate_id_aa64pfr0_el1_test), + KUNIT_CASE(validate_id_aa64pfr1_el1_test), + KUNIT_CASE(validate_id_aa64isar0_el1_test), + KUNIT_CASE(validate_id_aa64isar1_el1_test), + KUNIT_CASE_PARAM(validate_id_aa64mmfr0_el1_test, tgran4_2_gen_params), + KUNIT_CASE(validate_id_aa64dfr0_el1_test), + KUNIT_CASE(validate_id_dfr0_el1_test), + KUNIT_CASE(validate_mvfr1_el1_test), + {} +}; + +static struct kunit_suite kvm_sys_regs_test_suite = { + .name = "kvm-sys-regs-test-suite", + .test_cases = kvm_sys_regs_test_cases, +}; + +kunit_test_suites(&kvm_sys_regs_test_suite); +MODULE_LICENSE("GPL"); From patchwork Wed Nov 17 06:43:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623849 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 A319EC43217 for ; Wed, 17 Nov 2021 06:53:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8D33163236 for ; Wed, 17 Nov 2021 06:53:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233962AbhKQG4i (ORCPT ); Wed, 17 Nov 2021 01:56:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233508AbhKQG4h (ORCPT ); Wed, 17 Nov 2021 01:56:37 -0500 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 3119DC061570 for ; Tue, 16 Nov 2021 22:53:39 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id u12-20020a25f80c000000b005dd97d128f7so2541864ybd.6 for ; Tue, 16 Nov 2021 22:53:39 -0800 (PST) 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=wz9t+E+VXiepJL6MLtAC0LvVnUdPh/IHUgmRsgArlcE=; b=HvmUEQUJKrrfy7KQn+cPJTS8uyt5JY8g+FZ1ZhWzbq0B0GZkYE8v1oNob9IbqThMf5 eIVgxeUWlrp58vNANslC25kMYjxXao1OoVVlwkeRdIQBFhpsxv1TvPOC2f7M5KZhw+37 noAnmBOzEfni+Dz99DJpIx33CHG82FTQtENK+hjXje3ELzg0H/eOgdamlud+8hob8s/n d8TeP3wjd8FQ7MzygsQQiCs3/erA2mIHvazIYJTKNSdQxR9t4VI0XVvGS8E0HirEZClb c4ryR9AUVbcrH8j7FbGB2L7qnbJQcHQVRsWNS94rrM31RTtDfzmSJIvR8mqT25wutC/n BobA== 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=wz9t+E+VXiepJL6MLtAC0LvVnUdPh/IHUgmRsgArlcE=; b=0+1AJR2TEoRT3aAtu1qBWK+xTlgo9yxbXHcUH/Mk4KUqZ+Ly4hQAUh8j4NbA6J84rM xNWvmPSdAPbdlqe3TkvXM1FMB61UFojlyUE+7y3DL2RhyJ8S1xeelMzKgPws6QdADYo0 3or3I7ZuHRHx5axkoNJfB/5cpTGWVhUkS1lBAtyagIV+ZV3MZK5MsEGN94WZK/FGaphH 2GRqiG4SNnZPgwz9FV8TUHA6zd7s0lv3tAGhwi5i/+w9xY8dFlrBV/ICMB8O2WbdFlSF mY1sjcK9b+t4hmG2suVwMjVywpXx0QWGp1wpHlS6cFFp0UcCC1RWyh6TBMzc2k9FF6Dy /xOw== X-Gm-Message-State: AOAM532ts21oJ/X17yrBEtTlV/jKqry51p80srl11UuJTI5cn+J6hQge iQcu7+YGml9dmXUAfpk3CoS6BKB2seY= X-Google-Smtp-Source: ABdhPJyjCsGmjtTxCxe1Vx5kKC6qmnUVUhpi3G5rKbLKiwo+hm36IOcGaCTCDHDDH8Ex13kOFhhfD90EqIo= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a25:d68e:: with SMTP id n136mr15514402ybg.59.1637132018496; Tue, 16 Nov 2021 22:53:38 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:49 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-20-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 19/29] 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 a39fcf318c77..c1e0e1202f30 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 a54579e7ac91..aa4aff2588b8 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1128,7 +1128,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 5a2cb5d9bc4b..0c3f0bf3fbf2 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 17 06:43:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623853 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 48542C43219 for ; Wed, 17 Nov 2021 06:53:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 31B9963236 for ; Wed, 17 Nov 2021 06:53:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233949AbhKQG4j (ORCPT ); Wed, 17 Nov 2021 01:56:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36892 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233957AbhKQG4i (ORCPT ); Wed, 17 Nov 2021 01:56:38 -0500 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 346BCC061570 for ; Tue, 16 Nov 2021 22:53:40 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id u11-20020a17090a4bcb00b001a6e77f7312so853178pjl.5 for ; Tue, 16 Nov 2021 22:53:40 -0800 (PST) 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=bVvTx2BZnkE8y36lnLN4c9tpmfEY262vaHDUdbxg7yo=; b=chhFom6QinoNu6eS6p07QKazNwcXw2TGfQ+sgoSXzF+gknBuTEybuqRv6xwEX6VFfY 1co6CwLMeyDC1nMRrTU0BYtd94bnobsm16nyqYHJ7Af1HNWKh28bWeHGA6TEDPU0Bjxb nAepiDzHTcZYTo92Px+bpbDmsCXkvGTHQfWeXPa0GuGzP/yTDpGYHNMsZL+4q5BWPtJM Ze1RrftZ6XrT4KUpEjVNUkGKxz5XWKxVU/91mkxgyqnBDAiPUJxgBQw7ULIeE87amsqP +tJVS84pe3nU2oQd2CdDCc9y4iBQZliw2b21XSD9jNvZCVgiXE0i+CbHYwplT3f9gKe7 mcDw== 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=bVvTx2BZnkE8y36lnLN4c9tpmfEY262vaHDUdbxg7yo=; b=5ws6dEZmQ1xYCn0h/J2AL8u0D/qc4g13fA7cbOMDwfttW7gZidyDYM/jOKMfi/xImN 1E8wmHGA4hx7Qd+pYXNiNwzkh7lWbsWkXr5dMGgPUQJ4czLrecV0cL8d7ev2yzdUpkJe zP7xWwWgNuIuFyU9QF6VhsaUmDlmZQY5E/dfPYaOf6ICsgH5pbEurNCPGkvgovsgwmzH h/wxbAX3F7TRBe2LVwc8tVMfepwpKqmMv8ArSJa/zyWbysUxO2UXWHd0SwfrCY9boY9L Dx/fNX5QPM3MtQT4DiNHu3fY3Wn7HJ1KHBCwjcBEXbmrkgu4RUNDz4JH+00Q3XAe6xI2 0leQ== X-Gm-Message-State: AOAM531OHAWLNIZZWMz+1J9vgzSmY0FEU61jzVrZvgOI4VRSiavJpK3P YmA56ZeA3IPjdT+nivi/jVzCuAViUIY= X-Google-Smtp-Source: ABdhPJzMYgs7BRw3Qvd8VMWzmCaGHXPCN7+Z05SQBHE9IY6dw1vxa7sU188j1XsJMhABUy7JyUt3ZP21i/o= 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:2296:b0:49f:feb4:6457 with SMTP id f22-20020a056a00229600b0049ffeb46457mr5087645pfe.58.1637132019739; Tue, 16 Nov 2021 22:53:39 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:50 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-21-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 20/29] 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 c1e0e1202f30..e81f21995314 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -333,6 +333,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 aa4aff2588b8..64b104ebee73 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1128,6 +1128,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 17 06:43:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623855 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 C75A9C433F5 for ; Wed, 17 Nov 2021 06:53:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AD85463240 for ; Wed, 17 Nov 2021 06:53:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233968AbhKQG4k (ORCPT ); Wed, 17 Nov 2021 01:56:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36904 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233964AbhKQG4j (ORCPT ); Wed, 17 Nov 2021 01:56:39 -0500 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 D9AF5C061570 for ; Tue, 16 Nov 2021 22:53:41 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id mn13-20020a17090b188d00b001a64f277c1eso2631909pjb.2 for ; Tue, 16 Nov 2021 22:53:41 -0800 (PST) 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=Amc04gsXjzkn+vjiDgw0OgbmKYNLvSS2/kqn0hw3weE=; b=Be2YyTojkLCu9YEXlOJwcvNwijfwGmtrTojbG8RXAybGDqfnHBYiPKUSnvVZlfBEZH Xlk8JuxOCy5zDu6joNjSKNnlj4pcnHBYYjZwI/GTf+l6HScQoc/ZSoZVG9d9Lb6IwAiv Hd1RnT9anrnn17DoPDMNemBeNGbTh8S4c4pHFc5CZ2WFOswIARxDUv4PGNeDaWvAtDI7 MIMCSC7obwyC1XtO1lLqbIob8WlWamA29f44TXMuYIWeNwQTks3Q5vpi/yM5Wn5hwn49 0vCbjLY47br7WG/C1sTsj1FxRv7HllnuskXK5wrYVL2frKNoGOmoLITv9Mi+4Rl9ejPx eThg== 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=Amc04gsXjzkn+vjiDgw0OgbmKYNLvSS2/kqn0hw3weE=; b=4XJTlcaZLaiU3qIRXfZ0b0qA7wy23cAoKnQCQLAtHRFt/8CKRSd/3l5pAwaRidbOdC 4YYNIfdejt+Qm95eR5aasLNCzvDi/IgEDF/0bMQhEB0lcQaR7YsoZvPIpGin8bnG/sLD gJ/VS+Mni/Di2Dfebomejy32JYCxbWtyTT3UipBlNnayy84Fs/3L8pxBJpewnDt+J2h4 164JwrDrxf4erjgbSjWLEoGt4mGKPRuUY/q2VPnLm4CpHZQ7W+mLtK1TsPkdJiyttaYS 8EhzTuvko5LNu2cUpl66mB1SCGvtaBQJ+VNfv9+V3AI9GXgJ5MJmwGWnLgf4Ozg8dG+Z suLA== X-Gm-Message-State: AOAM530DahIZ93zoFmumghK17JwVGcu3dOb90IseoaXJ+mmejkDSAgDa S0xdJDMnlmTKVSPHB43LuHnyJ2CXk5s= X-Google-Smtp-Source: ABdhPJwaOePmyjg4Hc7vZIE16txaFDjohjlCKsgeQ1wSfRlTJ+Jyp/xqcbs1/JJuveMw6sbd0jRvkRvOd20= 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:390c:: with SMTP id y12mr314836pjb.0.1637132021101; Tue, 16 Nov 2021 22:53:41 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:51 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-22-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 21/29] 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 2f96103fc0d2..501de08dacb7 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -376,8 +376,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 @@ -410,11 +440,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); } @@ -952,6 +986,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 = __read_id_reg(vcpu, 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 @@ -1831,6 +1906,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 = __read_id_reg(vcpu, 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) @@ -3457,6 +3568,14 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) return write_demux_regids(uindices); } +void kvm_vcpu_init_traps(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 17 06:43:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reiji Watanabe X-Patchwork-Id: 12623857 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 7897DC433FE for ; Wed, 17 Nov 2021 06:53:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6070C6323A for ; Wed, 17 Nov 2021 06:53:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233492AbhKQG4m (ORCPT ); Wed, 17 Nov 2021 01:56:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230071AbhKQG4l (ORCPT ); Wed, 17 Nov 2021 01:56:41 -0500 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 53EF7C061570 for ; Tue, 16 Nov 2021 22:53:43 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id pg9-20020a17090b1e0900b001a689204b52so2647898pjb.0 for ; Tue, 16 Nov 2021 22:53:43 -0800 (PST) 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=4r4dnGc0QUxfmpMgxENAZwxToTocn/Wh0WdJQeDNk90=; b=KKsm9rkFm/QOI7qFPojRub9O/w6IU6WRes4Tk4KmRqWfD7iq15YY0sFxX0IUah79pB dlkjXriHiEJDCPSb/hJWN5SxXZZFY4RdJwbi88EBN9RJbVLuC0Jp/4B4iiwxznqFUsLT 3M+KV1l0ePdFaQrT2XaX6BZJ+c0FQH3ZeK8eXWM2uCzW+FdlFsTmv2XnXWH/5DadYHQ6 O3jw/JsLgCNgtGJ417Wg8nmGOjtmqhQPBMtjs/Y3PS8X4hlaVJjCPd/64DsFgMX2Qalh Gz006lsabDPmoFPoHlzZzXdrfRgE3po8uf/c5/Q6KF1INwP8BGDf1Zpb6vhkQDK/ltzG gL/A== 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=4r4dnGc0QUxfmpMgxENAZwxToTocn/Wh0WdJQeDNk90=; b=WIU4blUcklmlaaV88LHX8HOdblkeErp7BxdxaqQzW0mWBa3hFR/O5eGRDWfQrGqSoT OKTWXdQ11mL6FX8eDN1NhQ7vfOGNqdH0b1dlkx6Cqml2+k3E1EEljvF3oEDWymtlE0Th qSoOD2bOTXWG86OudxFt7T7eBubyHwoLsH20tH7JTI/OZTOb4DX4SoTN848elWuaXlcH FeHoK79je0TobhtsCYtYUv1dUqHuPufcaH0Z5OleeZd9DwyrRyblKd5pQA5pfjUDcjFg +NiWL4lwnnAY1d6Sgp5S11Owv49xRtTpC3xhm4pUwPqx7PhNclqoXr1nUys5R6DM0QMz ifzA== X-Gm-Message-State: AOAM532qMVpSazIhhdJk2UToTyXb30sGcvpG21P1p8cSIhmqxP8JVIub AOdIwJuPOEfax6qy6Fwv3YpoEmWJQXY= X-Google-Smtp-Source: ABdhPJyGVVmaEL5PQuPlf6iHi8bhoT0WT+vCtCanbdtf7ZVw0zdaOzbC1zXQq2fF70ugDq3mSaxormkPK+I= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90b:3447:: with SMTP id lj7mr7048244pjb.112.1637132022917; Tue, 16 Nov 2021 22:53:42 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:52 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-23-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 22/29] 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 501de08dacb7..42db8cf18fbb 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -405,6 +405,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 */ @@ -871,6 +892,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 = { @@ -1027,6 +1053,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 @@ -2318,14 +2356,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 17 06:43: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: 12623859 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 36615C433F5 for ; Wed, 17 Nov 2021 06:53:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 207CC61423 for ; Wed, 17 Nov 2021 06:53:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233970AbhKQG4q (ORCPT ); Wed, 17 Nov 2021 01:56:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230071AbhKQG4o (ORCPT ); Wed, 17 Nov 2021 01:56:44 -0500 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 8486BC061570 for ; Tue, 16 Nov 2021 22:53:45 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id r23-20020a17090a941700b001a74be6cf80so773368pjo.2 for ; Tue, 16 Nov 2021 22:53:45 -0800 (PST) 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=RcpZ70HWqU0SXh1JgWU046j8p1JVlfrsxLvOnh+ny5w=; b=LbXvb9O/MjigBpj3Q1x1la7lfju5hUWJ9TCDDM/Td5aHN+uf0MArRvDL6IXDAGsAYO 1qkC7lXJQbWXm6LWhlCZdiuD7RJJBvl8caI2psMUC1eT7mAMEjHA2BHA8Canef5mwt+s AHPDTPURjEgHiRebfgGqDADsiynKYh/zcoZ8u2PAU+3i4Cyo9u7uBIvvkDK8+wV7KfOg AOjPWj7Iru5eyBljExW4+88J3f/eMpEMCsWsTXdRmMTBeSdj9C2rZkCK2INb3GMbqBjB UOJvRCAGgqj3yTfI0jOwqB/5K58OA7pNhcqCuiwr4meSLJsuXv1vC+HzzVW8cXmmJGgD +AQg== 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=RcpZ70HWqU0SXh1JgWU046j8p1JVlfrsxLvOnh+ny5w=; b=IQ6gFjWUCUavIgMGNgkkLdrxsNRTHiumhnAPck4MrDYuzu1e+moByLqTMR2kXy8L8O JBJrklYY97PPa/oK9zOxvaUi7jGjxu4hIj/Kb2ku7BEwJobsyXyoVq0aGjbt+Og/lxwu 7Km1ufFux6rSNIfO5Vf3CJvpBA5hIq3ibMmra+a0mBQ8Wk9o9NbXaTZxS65gwdI2f2Ae Q5uvvy/jKyW0A+OofyWmnu5zBA61uaynzL/IE1ss+D7xq67l8jWrkBSHYEqGoXj+Q04Q 3Ti3rvSoCucJjd0vv3iG6YMX7EO9MZVf0zKQX3YtFWJ2CnLAwi3lBy42U7eV5xt50Rds 6slA== X-Gm-Message-State: AOAM532GPAK18/mBhCEjq7vWMXuSIZpzInwUfCjemfl/jeeqzJA0eBbE nT8+z+YK/pT8lryQmUXxobIV0GjqpqM= X-Google-Smtp-Source: ABdhPJw5QD14fDi96csV3HLcCihYEQmTicWAkaNNtkp4LgwsRxcvxf5w6HB4o8EsJXz+BBU2q7qWUTFRJGg= 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:284f:: with SMTP id p15mr314255pjf.1.1637132024716; Tue, 16 Nov 2021 22:53:44 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:53 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-24-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 23/29] 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 42db8cf18fbb..73d992ba6e90 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -426,6 +426,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 */ @@ -904,6 +915,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 17 06:43: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: 12623861 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 0E8D7C433FE for ; Wed, 17 Nov 2021 06:53:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E955A61875 for ; Wed, 17 Nov 2021 06:53:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234003AbhKQG4q (ORCPT ); Wed, 17 Nov 2021 01:56:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36946 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233988AbhKQG4p (ORCPT ); Wed, 17 Nov 2021 01:56:45 -0500 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 566A0C061570 for ; Tue, 16 Nov 2021 22:53:47 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id jx2-20020a17090b46c200b001a62e9db321so848257pjb.7 for ; Tue, 16 Nov 2021 22:53:47 -0800 (PST) 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=QbNVmbb/Oy+N5CWYEueDFqMF+6Qv00nkT2lV81yBcus=; b=rnThbfam0MmqlS4xxWCfnkTZjTwIIjz7OGsfNg2Dc5FUjrEYsTcLphvdf3QszQ1P8e rleC6mNmjL8rGSgDuDk2mhzP8SGwMahAxy9nA+h7AOlzQWfbxzFRrjxv2FpezKRby+K9 fGK+TV7K+cQLxRmufyI3KpJaQs4G8Al8wkjEc76UDtUE0wmLjgvVTLRRUw0vBbR23g47 Gc+6lOK7z3VCYWjyggk8J16KtV+E0A+hk2pessVtreB8IHxMwVAMvH0e1Pg3/TZQwPqE 0+E/K47JxwTWtWGAaiYt1301CwXUMp3SmYnLBzJSPbiOoIxu3b/hJroihzXhExZHOHf4 Euog== 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=QbNVmbb/Oy+N5CWYEueDFqMF+6Qv00nkT2lV81yBcus=; b=de6+XEtHbofQWhmPC/AKeHn17WtJBeC+Sr2YuN2PfS/VvWnpwbUa6OrlT596qQWNsq IN8Ndeo3dym+rhcoZKZV4Z+rsj2qiWj9a9hEnSmCvOTug+XdeRRSppKObcW+uJ6UkNMp GOiOhkukwDhkVNiwiZdXBF63uyub6kdZL9RuKIFZWYBGbN9kvkonH2ydgEP6Sg6lYFhV mOg0UJRzmFxmY+2OQxWdTBiN4CJmaS0CoMvCcGav9F/C7YT3gHDjJzHK/JoZvFwsJx7e 1I1e1nBv1fFzk05XtX74jhqaA1olhad43Ez4vaiJrbdxaXiWH8euL1Opj8JyXUY/EdD6 T8Dw== X-Gm-Message-State: AOAM533H5IRvjrh68CfcJpr1yE1t/0Dy6pjXFQQeiJfnUYG4UU7ZTokg ThXszkTucex4xOhdtRZXdCl1XS09+NI= X-Google-Smtp-Source: ABdhPJzFf9BbNWHGQuNu1097yoIpbbooIyAzQs9+tUoFo73zzIQ3EgtK+MTbaFiYTpdEg+tmDr0Qvl+1lsY= 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:284f:: with SMTP id p15mr314268pjf.1.1637132026636; Tue, 16 Nov 2021 22:53:46 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:54 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-25-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 24/29] 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 73d992ba6e90..cb18d1fe0658 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -437,6 +437,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 */ @@ -952,6 +984,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 17 06:43: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: 12623863 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 52E33C433F5 for ; Wed, 17 Nov 2021 06:53:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3815F615E6 for ; Wed, 17 Nov 2021 06:53:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234010AbhKQG4t (ORCPT ); Wed, 17 Nov 2021 01:56:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233993AbhKQG4q (ORCPT ); Wed, 17 Nov 2021 01:56:46 -0500 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5F44C061746 for ; Tue, 16 Nov 2021 22:53:48 -0800 (PST) Received: by mail-pl1-x649.google.com with SMTP id v23-20020a170902bf9700b001421d86afc4so569289pls.9 for ; Tue, 16 Nov 2021 22:53:48 -0800 (PST) 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=ap+PS7CD+HFBr7r8+vNbRPns4hwGZn9RZNY8Os9x/I8=; b=ME8TBN6HNLGOmfWdS07tu+6rYpz8jFnzNkaM3AZinIB5Y5rSPGGpQSiFoHOMsTPTgR KB+BXxWvxfUtevsqjCwhMzybSqT2HJRuVPaCCd/iP0EHRDDmNTDBaeXD6IeucnltyX5V 8wnPTb44HXZ181eXmc6VngO8oBOrDFP/wOdDuIZ/b2iUw1nXOCxe/qQQDzlTxnRj9lWe PPrXTJyGtiFWiEThG9Z1i55BWOYWpWgTv911tEvlcAKzKXMTlxqzPfA2Mu/keixChqpF HDJwXVj3GrfQzaJ0SeyfC97K4M+g6d/bN1Vn2cnoPn7etEJqpn3cb/dJU0o0svqJNUax y3NA== 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=ap+PS7CD+HFBr7r8+vNbRPns4hwGZn9RZNY8Os9x/I8=; b=Bns02ssL5xUfwQqXXtDci11Eqo2i18iTL31K0k3XmOuCL8PJlKABy38VT0PhmZZFib ap8l5vkwE1hnAb9Laq9ZV6mIz+Zus6MMmH+cnIF9AOmRJI7XrBVpKdQAQbAhRZ6+68/x YYElzP1d220NZmXihDhShAb5UdiVrbUDgX42CAofkm3ZUkW+4AvOd/K4pMLA2PpIn9QE pnuJi+2djHuobIxOLsYk6+TuTa3LFhFB3xJmYlEWLT6Jt5FttRmBdV1If3ORIcLOz7vK wPMWi6hVt8ziI+12dmy3LlqNrsA/A/SCDwgSpvUatCvBH58Vvh/ypuZKWwdGaUda46ab gYUw== X-Gm-Message-State: AOAM532e76CRIIWClhuaR8sxRs3DkMUF+HBYKkmGOVIGhd1I2Fwjm0Gj yQ4dG2+MM5FizszwMaKFGLV5yngi7H8= X-Google-Smtp-Source: ABdhPJx22jUgmf1vQhrGDnEI3IA2ofCSFdssKrHCARSsL9OdUAakMfgccLuH/dwXswlHbXm2xj+dGZ0IezE= X-Received: from reiji-vws-sp.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3d59]) (user=reijiw job=sendgmr) by 2002:a17:90b:3509:: with SMTP id ls9mr6754492pjb.99.1637132028334; Tue, 16 Nov 2021 22:53:48 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:55 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-26-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 25/29] 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 cb18d1fe0658..3d3b29515b8b 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -469,6 +469,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 */ @@ -992,6 +1003,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, @@ -1034,6 +1053,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, @@ -1128,10 +1148,9 @@ static bool trap_loregion(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - u64 val = __read_id_reg(vcpu, 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 17 06:43: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: 12623865 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 98B4CC433F5 for ; Wed, 17 Nov 2021 06:53:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 80CB9615E6 for ; Wed, 17 Nov 2021 06:53:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233996AbhKQG4w (ORCPT ); Wed, 17 Nov 2021 01:56:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36990 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233993AbhKQG4u (ORCPT ); Wed, 17 Nov 2021 01:56:50 -0500 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 651C4C061206 for ; Tue, 16 Nov 2021 22:53:50 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id z5-20020a631905000000b002e79413f1caso718139pgl.8 for ; Tue, 16 Nov 2021 22:53:50 -0800 (PST) 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=l9cL+44fLGdDyYUFjHlYq+dL32isCwZtQcuWO6mBjWA=; b=o36k6i54cI44CkxNoyng06/1cnBbAHYmtiCr8v2I/KDJLlWFA9DKoh2o8QlHJ4ioDR ZBxEhJYYuxUj3CTLSPaVa+LdwzJtLW5vmimI7ZyOL/v2EdkMBv8s7Zb8aNQg1qDNc1Ji 0DxExQLqbrEaTySPkb4iHM10iwaD6drKdifBiW/5Im3Zz2e/K9hPnXG1khJlse+zcZfe e1gO5CpHsd0NA0rBCs8UNOzB5v4100BqKNd+PqC7I11geGCXteo1kcbBCX3QdXqmulGu Uet1f3rbkcNvy1NTGYTYO05MVb+WFisTpVESqHDn9yTzGcCfcX+q2hF+HlQKq8DvKfbW rToA== 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=l9cL+44fLGdDyYUFjHlYq+dL32isCwZtQcuWO6mBjWA=; b=hyTnUANKrk1YEBLzaehGsYmkL7agstakPfgm4t06NZq6n6X+T0r7IoO0RL/AR1HhV6 LSpis4x6cEiubedCjTwdjwpArlZIkMNcGYMAfSxmTxQbXVSmvLoni5o6vEiJc5bOJnFv KpO4gAK6TsBUkcopDNU4uDR5gU3PZ8J52hD/zsppVtT1iaPB/yVmI3ucFyiG5Xlviv2E wwaoWmZnXyF5gf583du2Ww45LmyercPrGcvXXwsighS/sdtb9g9YtjrchF2GYPEUwfhj o3T5EXXkZK3AuwL8olNRFk/qFd5kgq5QMjZmeHfFMW65q7H5mRGfFOQbDpJlacrt3Sax m3jQ== X-Gm-Message-State: AOAM532NgviNuVm4lzQFDKa0yshVVLD5TvPhQaKvs/xu5obPszMYs+Id 0SYxyv18aIx0HDfU2910G6bBHodCuu0= X-Google-Smtp-Source: ABdhPJx9DDeQMUXc6095SOTfgNA0s7/GlZiDRs9vbKaSt1H48YgTnr7zDO2ifTxH2Q2Olse8b10fDPjrRfI= 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:df97:: with SMTP id p23mr6831251pjv.3.1637132029846; Tue, 16 Nov 2021 22:53:49 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:56 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-27-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 26/29] 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 3d3b29515b8b..f1f975ce7b07 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -376,6 +376,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 = __read_id_reg(vcpu, 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, @@ -480,6 +504,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 */ @@ -977,6 +1009,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 17 06:43: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: 12623867 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 BED57C433EF for ; Wed, 17 Nov 2021 06:53:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A8AE461BF4 for ; Wed, 17 Nov 2021 06:53:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233459AbhKQG4x (ORCPT ); Wed, 17 Nov 2021 01:56:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233983AbhKQG4u (ORCPT ); Wed, 17 Nov 2021 01:56:50 -0500 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 5CC22C06120B for ; Tue, 16 Nov 2021 22:53:52 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id p3-20020a170903248300b00143c00a5411so564538plw.12 for ; Tue, 16 Nov 2021 22:53:52 -0800 (PST) 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=cOVvD3SNDbIL6lfyzdxlcaoY7rN6G8I+IyW+oD8ignM=; b=Xlauq9wTt3xE6BYao1bY0HArMFV6nJ6xH/EuP9kpisaxTdt4ScYKFFQdkG9sKoH42R NkptaNYJUssNyX3+a9NogLBRKsc+T4nXMSPu5l6ecIZP9dgrCJ0LRj7ZvOKbho3fYKNy PhVcALbMCYQ5Ueoz0h1Zle1j3NxvJu/jDi42xUt/UJknbA+Lqr2OvLzYcpG7zS4LUpWS nkauUZlcLVqSJnhSegPKecNwi6FsaKPSVXQ2kuwbCvjFz60gmhYejZ728lE6cGAK8Onu SHWWKdpNNpAFDd8jo6+oW+sUESEmaN9xI1ziqCGHwbi6sB/ULtj398r4gUOZBz/AtQOk ALuw== 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=cOVvD3SNDbIL6lfyzdxlcaoY7rN6G8I+IyW+oD8ignM=; b=htQFqSKfBjIxcNJ1u1xUibQhYPeF5WvQdfAOOGsTxtmRBRk8es8AM/jJz2fEOD8SqI Hn6l4/MJ18xx062XyXi/e99zamdsHbQZAtPVHRduThp8Apb/FUsN6r+hfMszNR1Tij9n uHWhaZg6VB3cX32I/efqR/IB1eNZvJgEWLUFZ+v8EjF3kxK/oejQpx21OR4kVbXzYjgq 1CDXKiOVjXrrNutGWFb8nyOFupbaCI5yWq886Sp8bBd/j39HgCtlceTN64+NILs/Cdfa Ln/hz8+IjMBoMrozcDOCgubMczSGa2gNz99bM/EPZ+bC1YDmZ4RQHGQKe6L//WEa6Yib nzPg== X-Gm-Message-State: AOAM530Hpsf3FCm3pw347kRQ9kXlMMv+Zj13uimLhUpiv/jAZuLI2vzs WPGjKRJQQGy3wWDNlP1f+7rvedHqXCs= X-Google-Smtp-Source: ABdhPJxgZUPAeWfxD6o4eFhxbgg1xva8V+KS7wN7lmBeeEQdyhn13ZRClap0+p1FhSsGVbJnsbUOIWe02Cw= 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:390c:: with SMTP id y12mr314910pjb.0.1637132031567; Tue, 16 Nov 2021 22:53:51 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:57 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-28-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 27/29] KVM: arm64: Initialize 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_init_traps() at the first KVM_RUN to initialize trapping of disabled CPU features for the guest. 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 9dc9970a2d46..a53949cd53c6 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -747,6 +747,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_init_traps(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 64b104ebee73..25a41ff92aa5 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -625,6 +625,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) */ if (kvm_vm_is_protected(kvm)) kvm_call_hyp_nvhe(__pkvm_vcpu_init_traps, vcpu); + else + kvm_vcpu_init_traps(vcpu); return ret; } From patchwork Wed Nov 17 06:43: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: 12623869 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 B890DC433FE for ; Wed, 17 Nov 2021 06:53:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A324461875 for ; Wed, 17 Nov 2021 06:53:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230071AbhKQG4y (ORCPT ); Wed, 17 Nov 2021 01:56:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233974AbhKQG4v (ORCPT ); Wed, 17 Nov 2021 01:56:51 -0500 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 D169BC061570 for ; Tue, 16 Nov 2021 22:53:53 -0800 (PST) Received: by mail-pl1-x64a.google.com with SMTP id o8-20020a170902d4c800b001424abc88f3so580313plg.2 for ; Tue, 16 Nov 2021 22:53:53 -0800 (PST) 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=3Vy8zl0uiB6BzrVyosP76h+gx7fVBOmrAidLKwyOmLo=; b=SIFfTVfI7I8A9xtfgW2SGwAAgVjhFtCYzxi+nqRkzYADw/h3e55zX8dv0tcR7U3gTs Ow0HGNvpz/NuJG85fy363/AcS51o/aycC/kCv5uCjNhS+RCTNdAFQi4+DcDeTOnDeDse FVkEWvlwCHnfDvOvPIJ9ghlPfoOQgt8kKi10mbK55MgoCJkbF1IJEjpJu1oblfYzNLKq y4xT6lWYpL+xwM+iKPJwn2wFgMnVAK5Or854NPyaNECj9/og+mfPKEOLl7iIRm4Lmngr PItBcWboqdv21plvaPRpZkKCuZVq0DXHslVP9GpedQEfAciDbpFEfcddLsx2m9IGBW55 wq+w== 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=3Vy8zl0uiB6BzrVyosP76h+gx7fVBOmrAidLKwyOmLo=; b=61ybwpV0X0ifRyH9hqriMfHssOOyRZq7wZ1Z7DtFqPhS+RKpyuvbgpjWKTFlZuflYJ RZpvl8pOxnPSHBfkQj6szC4QvU8vx/B1bdDVqLCz7KxNoDZmtVBxh/3H2PDSIvxQDanK YTsfcf7LBkG3rDwgqzrRcbFekPgjdCm9K8hkp5oxcIkw0Atuo30w46N5mcmGy678QlpO rAuO1tSJgkurZ4nvkLApvn9VmVjityDXWcynZDaPDVhGgaoHTgGcvK/ijblPVUQIP1I0 It6Sd5d+veMrh/VHPUolhr0zUfX4DssIhZ6Ok97dGU0fbiotuUSl8U6YC2vdZ6rLJ6QL 8ffg== X-Gm-Message-State: AOAM533dnovcVjhUSR3DYVRhNPDOtuTzJgBqGqoTKVXPerpTXc/iiXK0 GxDHyp2F7OfjsQ1USqzobTwTtKsAjV0= X-Google-Smtp-Source: ABdhPJyuYg+X9kpMVUPN5OoZNv12tw8vlVgjnQ4xCZ/tC4KYbUa1SUFiMJwvsngrbAH2RAUicLELQrXc63o= 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:ed89:b0:141:f601:d6a with SMTP id e9-20020a170902ed8900b00141f6010d6amr52839367plj.77.1637132033292; Tue, 16 Nov 2021 22:53:53 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:58 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-29-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 28/29] KVM: arm64: Add kunit test for trap initialization 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 KUnit tests for functions that initialize traps. Signed-off-by: Reiji Watanabe --- arch/arm64/kvm/sys_regs_test.c | 238 +++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) diff --git a/arch/arm64/kvm/sys_regs_test.c b/arch/arm64/kvm/sys_regs_test.c index 8d27c7c361fb..f73b207be4ee 100644 --- a/arch/arm64/kvm/sys_regs_test.c +++ b/arch/arm64/kvm/sys_regs_test.c @@ -844,6 +844,241 @@ static void validate_mvfr1_el1_test(struct kunit *test) test_kvm_vcpu_fini(test, vcpu); } +static void feature_trap_activate_test(struct kunit *test) +{ + struct kvm_vcpu *vcpu; + struct feature_config_ctrl config_data, *config = &config_data; + u64 cfg_mask, cfg_val; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + vcpu->arch.hcr_el2 = 0; + config->ftr_reg = SYS_ID_AA64MMFR1_EL1; + config->ftr_shift = 4; + config->ftr_min = 2; + config->ftr_signed = FTR_UNSIGNED; + + /* Test for hcr_el2 */ + config->cfg_reg = VCPU_HCR_EL2; + cfg_mask = 0x30000800000; + cfg_val = 0x30000800000; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.hcr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_mask, cfg_val); + + cfg_mask = 0x30000800000; + cfg_val = 0; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.hcr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_mask, cfg_val); + + /* Test for mdcr_el2 */ + config->cfg_reg = VCPU_MDCR_EL2; + cfg_mask = 0x30000800000; + cfg_val = 0x30000800000; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.mdcr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.mdcr_el2 & cfg_mask, cfg_val); + + cfg_mask = 0x30000800000; + cfg_val = 0x0; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.mdcr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.mdcr_el2 & cfg_mask, cfg_val); + + /* Test for cptr_el2 */ + config->cfg_reg = VCPU_CPTR_EL2; + cfg_mask = 0x30000800000; + cfg_val = 0x30000800000; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.cptr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.cptr_el2 & cfg_mask, cfg_val); + + cfg_mask = 0x30000800000; + cfg_val = 0x0; + config->cfg_mask = cfg_mask; + config->cfg_val = cfg_val; + + vcpu->arch.cptr_el2 = 0; + feature_trap_activate(vcpu, config); + KUNIT_EXPECT_EQ(test, vcpu->arch.cptr_el2 & cfg_mask, cfg_val); + + test_kvm_vcpu_fini(test, vcpu); +} + +static bool test_need_trap_aa64dfr0(struct kvm_vcpu *vcpu) +{ + u64 val; + + val = __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(SYS_ID_AA64DFR0_EL1)); + return ((val & 0xf) == 0); +} + +static void id_reg_features_trap_activate_test(struct kunit *test) +{ + struct kvm_vcpu *vcpu; + u32 id; + u64 cfg_mask0, cfg_val0, cfg_mask1, cfg_val1, cfg_mask2, cfg_val2; + u64 cfg_mask, cfg_val, id_reg_sys_val; + struct id_reg_info id_reg_data; + struct feature_config_ctrl *config, config0, config1, config2; + struct feature_config_ctrl *trap_features[] = { + &config0, &config1, &config2, NULL, + }; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + id_reg_sys_val = 0x7777777777777777; + id = SYS_ID_AA64DFR0_EL1; + id_reg_data.sys_reg = id; + id_reg_data.sys_val = id_reg_sys_val; + id_reg_data.vcpu_limit_val = (u64)-1; + id_reg_data.trap_features = + (const struct feature_config_ctrl *(*)[])trap_features; + + cfg_mask0 = 0x3; + cfg_val0 = 0x3; + config = &config0; + memset(config, 0, sizeof(*config)); + config->ftr_reg = id; + config->ftr_shift = 60; + config->ftr_min = 2; + config->ftr_signed = FTR_UNSIGNED; + config->cfg_reg = VCPU_HCR_EL2; + config->cfg_mask = cfg_mask0; + config->cfg_val = cfg_val0; + + cfg_mask1 = 0x70000040; + cfg_val1 = 0x30000040; + config = &config1; + memset(config, 0, sizeof(*config)); + config->ftr_reg = id; + config->ftr_need_trap = test_need_trap_aa64dfr0; + config->ftr_signed = FTR_UNSIGNED; + config->cfg_reg = VCPU_HCR_EL2; + config->cfg_mask = cfg_mask1; + config->cfg_val = cfg_val1; + + /* Feature with signed ID register field */ + cfg_mask2 = 0x70000000800; + cfg_val2 = 0x30000000800; + config = &config2; + memset(config, 0, sizeof(*config)); + config->ftr_reg = id; + config->ftr_shift = 4; + config->ftr_min = 0; + config->ftr_signed = FTR_SIGNED; + config->cfg_reg = VCPU_HCR_EL2; + config->cfg_mask = cfg_mask2; + config->cfg_val = cfg_val2; + + /* Enable features for config0, 1 and 2 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = id_reg_sys_val; + + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, &id_reg_data); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, 0); + + /* Disable features for config0 only */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x1; + cfg_mask = cfg_mask0; + cfg_val = cfg_val0; + + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, &id_reg_data); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_mask, cfg_val); + + /* Disable features for config0 and config1 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x0; + cfg_mask = (cfg_mask0 | cfg_mask1); + cfg_val = (cfg_val0 | cfg_val1); + + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, &id_reg_data); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_mask, cfg_val); + + /* Disable features for config0, 1, and 2 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0xf0; + cfg_mask = (cfg_mask0 | cfg_mask1 | cfg_mask2); + cfg_val = (cfg_val0 | cfg_val1 | cfg_val2); + + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, &id_reg_data); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_mask, cfg_val); + + /* Test with id_reg_info == NULL */ + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, NULL); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, 0); + + /* Test with id_reg_data.trap_features = NULL */ + id_reg_data.trap_features = NULL; + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0xf0; + + vcpu->arch.hcr_el2 = 0; + id_reg_features_trap_activate(vcpu, &id_reg_data); + KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, 0); + + test_kvm_vcpu_fini(test, vcpu); +} + +static void vcpu_need_trap_ptrauth_test(struct kunit *test) +{ + struct kvm_vcpu *vcpu; + u32 id = SYS_ID_AA64ISAR1_EL1; + + vcpu = test_kvm_vcpu_init(test); + KUNIT_EXPECT_TRUE(test, vcpu); + if (!vcpu) + return; + + if (system_has_full_ptr_auth()) { + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x0; + KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu)); + + /* GPI = 1, API = 1 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x10000100; + KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu)); + + /* GPI = 1, APA = 1 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x10000010; + KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu)); + + /* GPA = 1, API = 1 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x01000100; + KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu)); + + /* GPA = 1, APA = 1 */ + __vcpu_sys_reg(vcpu, IDREG_SYS_IDX(id)) = 0x01000010; + KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu)); + } else { + KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu)); + } + + test_kvm_vcpu_fini(test, vcpu); +} + static struct kunit_case kvm_sys_regs_test_cases[] = { KUNIT_CASE_PARAM(arm64_check_feature_one_test, feature_one_gen_params), KUNIT_CASE_PARAM(arm64_check_features_test, features_gen_params), @@ -859,6 +1094,9 @@ static struct kunit_case kvm_sys_regs_test_cases[] = { KUNIT_CASE(validate_id_aa64dfr0_el1_test), KUNIT_CASE(validate_id_dfr0_el1_test), KUNIT_CASE(validate_mvfr1_el1_test), + KUNIT_CASE(vcpu_need_trap_ptrauth_test), + KUNIT_CASE(feature_trap_activate_test), + KUNIT_CASE(id_reg_features_trap_activate_test), {} }; From patchwork Wed Nov 17 06:43: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: 12623871 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 7FBBCC433EF for ; Wed, 17 Nov 2021 06:53:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 66EAF615E6 for ; Wed, 17 Nov 2021 06:53:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234002AbhKQG4z (ORCPT ); Wed, 17 Nov 2021 01:56:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234000AbhKQG4x (ORCPT ); Wed, 17 Nov 2021 01:56:53 -0500 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 645C5C061570 for ; Tue, 16 Nov 2021 22:53:55 -0800 (PST) Received: by mail-pl1-x649.google.com with SMTP id z3-20020a170903018300b0014224dca4a1so594910plg.0 for ; Tue, 16 Nov 2021 22:53:55 -0800 (PST) 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=qbc2GaKXdn7Q+y6eTZ1QNmA9LJajLyyG1yFIjawKfKI=; b=IN40Na6X/WrOiwYWLVNVskrKV/IC49mZn/cey2wt15jI95iQklBFqKS1AVhxfUc2iD AbjXqmWp8x4xnLrZ1EjSmBqtZZv+EVMTjqNqQXgyWsIfaWJh3s/6AxgKNHVrg4ac0GKS LOmoNZsfa5bvi0jClMkRkqGUT/E421cgbhRh1iv8+4ZqFIoPxnLEfZ9IOSX5wQ3BUQk7 6ix6fLzRHn+gl3p3vPsj6uIBSfvJK2EBiv49v4tOtgzapHdsDD5aI6FGomZDPeZ6qmuq dqH8gA3O4R4LHQeGd3pslHEIzGRJzhajo8w4WzPK4Nb8V1ARflnHzQvExJb9jvwFxXij G2Eg== 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=qbc2GaKXdn7Q+y6eTZ1QNmA9LJajLyyG1yFIjawKfKI=; b=oG5brOLSen52WUKgAxtYTaF8eQocVEz0tzgMPUNwUbdXz/jomsAqMvQ5+Skl2CJWQR KqNEJcUIoSYhUKF4m4qlJmYFOWg+IBA7Oh0mI9ex+6F+Ecjwtn4intF6W/Qpxo7hcuSq z+Z7a8QAaBBh308NHY1fs8zOXvVw06EekDJXrfYmKbKBocE5oH6j8A5VZD58VxKn+44M 6z2dc4lEak5yMAUTVkzdryQ9eDLezl38cda4js2L//7SNck4/UR86TMNU/Pj4Y6jtV9+ BKO/BIUHkssrPazjInc6piLGD5Zn5y73XbaBm10e5ZakBCxEHhb2bJUccDCnfzlR+Urc W8pA== X-Gm-Message-State: AOAM5327byBC8kXmu6DxR3xsjx2a+zmJJ7+NidAcBg6tAOdb9KedLcx4 dbdnROUcgVfALgmqy7SxhjpsEE94Uek= X-Google-Smtp-Source: ABdhPJyG9g+GX3Rb9X/2WPY53/Z+oM2PsXLviG/iM4X6CWgqxf/HzxFpWoq5SXdCbGWfVuTvpLY7aCM6PnU= 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:684b:b0:143:84c4:6561 with SMTP id f11-20020a170902684b00b0014384c46561mr52432178pln.33.1637132034898; Tue, 16 Nov 2021 22:53:54 -0800 (PST) Date: Tue, 16 Nov 2021 22:43:59 -0800 In-Reply-To: <20211117064359.2362060-1-reijiw@google.com> Message-Id: <20211117064359.2362060-30-reijiw@google.com> Mime-Version: 1.0 References: <20211117064359.2362060-1-reijiw@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [RFC PATCH v3 29/29] 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_CONFIGURABLE 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 | 1128 +++++++++++++++++ 4 files changed, 1131 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 d4a830139683..5daf1400f0cf 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 c4e34717826a..fee6ba13019c 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -92,6 +92,7 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_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..50d60d120e2e --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/id_reg_test.c @@ -0,0 +1,1128 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "vgic.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 GICD_BASE_GPA 0x8000000ULL +#define GICR_BASE_GPA 0x80A0000ULL + +void test_vgic_init(struct kvm_vm *vm, uint32_t vcpu) +{ + /* We jsut need to configure gic v3 (we don't use it though) */ + vgic_v3_setup(vm, 1, GICD_BASE_GPA, GICR_BASE_GPA); +} + +#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 = "GIC", + .sreg = ID_REG_INFO(ID_AA64PFR0), + .shift = ID_AA64PFR0_GIC_SHIFT, + .min = 1, + .caps = {KVM_CAP_IRQCHIP}, + .ncaps = 1, + .init_feature = test_vgic_init, + }, + { + .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 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 bool feature_caps_are_available(struct feature_test_info *finfo) +{ + return ((finfo->ncaps > 0) && + caps_are_supported(finfo->caps, finfo->ncaps)); +} + +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 if the feature is available */ + if ((GET_ID_FIELD(sreg->org_val, shift, is_sign) >= min) || + feature_caps_are_available(finfo)) { + 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); + if (finfo->init_feature) + /* Run any required extra process to use the feature */ + finfo->init_feature(vm, vcpu); + + /* Check if the ID register value indicates the feature */ + 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; + + 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]); +} + +void run_test(void) +{ + set_id_regs_test(); + test_feature_all(); + test_feature_ptrauth(); + test_feature_frac_all(); +} + +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_CONFIGURABLE) <= 0) { + print_skip("KVM_CAP_ARM_ID_REG_CONFIGURABLE is not supported\n"); + exit(KSFT_SKIP); + } + + init_id_reg_info(); + run_test(); + return 0; +}