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: 12692826 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 40024C433EF for ; Wed, 17 Nov 2021 06:48:01 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F349363212 for ; Wed, 17 Nov 2021 06:48:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org F349363212 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=bBbQpHH3zjADEvMKMucNYI4CxlXNfsbKaUokseJ2ZqQ=; b=o9CZrcQVQtnIaYw56mvkauSMOK K0xnmopJZDAJXH1lxisi5toHnEYr9hQ4Xzr4E9T6Yty7Hy4hbSZ3F4Z6ou4tPjWxgfKfJBFPXm3W8 yDuqQoX26C3iBZZ9sdJ4xwHxWb/PSTgSIQ7jvZSMMBZjLAxcgJcv6vGG7i8kJnL8FZ4oqFFis83Xm JkLzayPie37M0tQ/4fdOqmSHH2Ufxo8UdjvPu+pI4ew+jkpVe2xnCZBwKgNFIWA8DGOV1VyeX0kOp FfU98SjoiC0pb9b8nQJYROj72kg+bVIQ9KAfR0GLatVykdINT6kBE9kRZKzHlADvitsHEJOzmFHet ZrHzJaZQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEiQ-003XBB-0X; Wed, 17 Nov 2021 06:46:42 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEiL-003X9m-IX for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:46:39 +0000 Received: by mail-pf1-x44a.google.com with SMTP id w7-20020aa78587000000b004a28bb92381so1081100pfn.22 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=REyRh/a1Nu7ROp8KfSb0ImcotRBgICI0daT0jbgOTrraoBjnqzSvTx70zl7rUFLn6S OOS2k20ZbiEpoS89VUcZI5Z479zk56TL96iKCQ/w9H3BESReFKZokVTAW5onqlpMGyrW wFEsIy/t+LSPK3lFIVdlWtNqP7B6p+ptV/YeC0GzOn9+qdLFVn39xEBIcKmCHheYVdq5 UGMJVbNLNXdDq3NIiCUWzD0L+oFvMdNBUtEvx1DqLJe0qqhMdegnCnorXO+xKvkObwAE 1ZU7OcwZ+ctAg2td1xfkEjTaIlvKHkBe1uZRAq2C8h7ppVN1aevXJH3OinZrJHN1eJTn Gd2g== X-Gm-Message-State: AOAM533tnnQTVzUL5hfr2eC+MWPPqH+u+2UX8GmXrwheQiXYvZve8ClT VYxQ6xGGBbr76nxgoh0aYuLB+LqUogw= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_224637_657065_3E3C4B35 X-CRM114-Status: GOOD ( 10.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692827 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 2AC0CC433F5 for ; Wed, 17 Nov 2021 06:50:19 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ECAD761BF5 for ; Wed, 17 Nov 2021 06:50:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org ECAD761BF5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=3kVmjw32PE5GKxVi1iQskK2ybfjZVsQPNv9Wa8VGwB8=; b=Sx0p/qszbzeOiRKuKzsGmtZXWb JdkKxk9EZfqIL2yPgI+u04bONBCZKmmjKlXDHWtBnZPG/2xdyb+VQh1MC4SkYMT4W5KRlkTanbgzl HaXja1pEuSusB9uYMdDkylGqGzLWcn3JZ2xXtgdsRdum3aQxIkBr9f5ejUvPuVnYql3ILQ7490jYt IFu2yrLJMnY+BvFCma8RN6NAVhn00VhvHHrU+6KkOi7sQVR4BKcTwurHq7IvACgGZFr4YklxGcEjk IhEzA6xo0XJruRA0GVqLsnYZZZfrI6Bv2bhBA3a+ZVX2b+uxsjKKphe1JDmiv1e8cvxGGL5lgDulV MifbWP4w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEkg-003Xwi-Hi; Wed, 17 Nov 2021 06:49:02 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEkd-003Xvb-4d for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:49:00 +0000 Received: by mail-pj1-x104a.google.com with SMTP id pg9-20020a17090b1e0900b001a689204b52so2641443pjb.0 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=XF2/RIF/aG50QC4c4EMcrN8zPhNmwhMlRB6jPK5hr5hORvL5/CDgL0XuLsuJHUHndN 094nSfKVkLWFTHfG2ip9Gk7fTaAFLCsv63eBFn5PAnvEOM+ItsaD5wXyL2WcsZZI3lTh lMvH6IYlgVLpPOPSR7aVyvgDPk2jW/2xIqc0UEizZtWfA2MkW1+NOaWXSMMWatTitdfF bsrWFDOW342srMpmL2OcF2F2naUcsdndsfwJWQnSU8nJHb3YkUk6+rBVF7jFa0j3IbP2 mtVjp59BLfsPx9XBkq0208ejomhulptgeGYOvMpZpfNBBxRZfErldMXJuFSSMOml9TCR DSEQ== X-Gm-Message-State: AOAM532nmFOBzR2Qykcb/kI0iOuO8iOABbFLLZcW3qcUe5ERJ82gfZrc H5P3e7evBfDu8Rr+xgFSKoQhb2pUS2s= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_224859_221961_ECA8CD92 X-CRM114-Status: GOOD ( 17.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692828 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 5069AC433F5 for ; Wed, 17 Nov 2021 06:51:15 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1288761BF5 for ; Wed, 17 Nov 2021 06:51:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1288761BF5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=kHkgBBAULHl1azvZGTjMHyc16H5WbQsgiwWhv/4Mq/o=; b=i9DAqhhz1cnrRL8KwHqQTSv9dU ZcDgBPYSoS++R2u8tzMzBpDuqV6wMma5J6cqGvM26gXupmipIQibGmJiWOXCJviE1DhMOmSiJ6S2a Vj8WwvBuU8lr7fyQontbukv/rOZKwePkY84mQ5kuxCPSrQJBXXImwfxEoOjU+0DFbKzggUch4XeEx oFqcZBT2KKZkcBkUJQWhY3a2p4f3w0jOrbqNo7d5l/0LBKdt3zHZ/zI0aNGe20g+coTIb01uSxfrw +n+W5AMlXVEpamfAlilE7aVoFLQZPV3an6MEq2KtAQWoU+4S2qp85D7qo+zdUNkDkZ+YYI+Hh0jpd aqPIv5cQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElO-003Y8M-Il; Wed, 17 Nov 2021 06:49:46 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElK-003Y7H-U4 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:49:44 +0000 Received: by mail-pj1-x104a.google.com with SMTP id jx2-20020a17090b46c200b001a62e9db321so842608pjb.7 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=5yLATRblA6fgpoRHEzmhDBFYaY4tOnzyXHr8aSZvfrXHjCVHf4YE1MuDvRu2cglPpD pDPAyAIj4n3k0jcRvTfz53MkrCGPw/6DOxOM+lm6k9+PDumP4pn2OSMj/BryH3tMBGBf N9/ovuOtqkWxNC3pJ136b52TDYXnp/ORZ9a8dou8EMQPKMzS29NBKpjYQg7vcQfkDizH 6pXfeuyV31uRUQAfRJa876ZqSMQjnPRTy0xMucdimvto6ayorqQayADagbyoGdScEQ+5 LwR5luGVR76Y8jzrYLS/fNCqT/dVukscPMqddAoChtNGhbj2JEEvwr7CsPleTzFIRcsa zUeQ== X-Gm-Message-State: AOAM531ewk1AzfMz0mI9bMLeywdoJZr0LX9wpbYRfiOayjT/SQnL2ojV D+fnBfdlCveO/0Z3NWFPGzpJCJDSfjU= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_224943_011947_FB3DE283 X-CRM114-Status: GOOD ( 34.46 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692829 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 1AC39C433EF for ; Wed, 17 Nov 2021 06:51:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D397F61BF5 for ; Wed, 17 Nov 2021 06:51:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D397F61BF5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=eCT2VWwKH/3GxAU6AUEiEOq+F5Z7OWhSbjm6iDprZmk=; b=rN2ZBsOqPeNBKwuMloX6k+Aqkd Tqu5mCj/l2MuXTSzg/P6JAsDxm428mDIEftERsroHXJ5WLqp0qmKSlGk3Acz3z3BhBxuxNZ63Rcwq 0zCzPOupizRQ+NFRkNM3CTE4h4JHi5gtB9ZwgktAqzskfI6aD4tDp+zg/ibWVdSMFw4tnqnqgvDD1 //OSUfT1iOsSp5M0PAWRP9Vjnk2BHqb7V7nM4HZMTS6ApBZzyEfAO5e2aQRa3N/SeuKlYE0dMJlCU N/aJevnkUUtleqLphX31nKi3MWYaKNyhAuGCEAhXQgtGQi4pR30kE8GzfCMH+S4+VCRXF2D25ITZv czO692Vg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElg-003YDl-Cf; Wed, 17 Nov 2021 06:50:04 +0000 Received: from mail-pg1-x549.google.com ([2607:f8b0:4864:20::549]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElY-003YB7-FX for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:50:01 +0000 Received: by mail-pg1-x549.google.com with SMTP id n22-20020a6563d6000000b0029261ffde9bso692980pgv.22 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=ZYD2d3A/xflpn+EKn4NXdXOwW5UCUsPC96iz+zUrTQ1y0y7UM6EX+JkW8jmoR5Fr8n yLoizi+zvqYzSxW3gm2iSgYiVOxKixCzZktja+Tq6mdueVF4trMH4/O5PaEnQaSt5sXn x12zfIDmfsirYjYoslDsB+7oq1isDs2PyT8mOPb/Ey3rWjgpQS6VzDOvefFw2T/9JHES m+HnEeXXo3/zXa+io+1SWPbELflMV8zOsaAdzmsjYg4cW51UX5byLN/Y/kfhXPK6Si63 UaxyIHMHAO6L0gPq7IXbZc+pjR3fw5SG3tbtUp1uZVenfKGSKM4Gx9T3InmswyLcsat7 TzRw== X-Gm-Message-State: AOAM532a371SufXipRoNu8KM1/PKsrmmqS8t+IlUGeKORqamHwKdSJFu GU9u0kXr1vPIcmV6F0xstVBFyiAbRvY= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_224956_580737_9B143FA3 X-CRM114-Status: GOOD ( 24.04 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692830 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 A15BAC433EF for ; Wed, 17 Nov 2021 06:51:45 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 65C3461BF5 for ; Wed, 17 Nov 2021 06:51:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 65C3461BF5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=BKZiWj+PpDDomHDZaBcu1s3ff62tiLr1DKTwj58XoK0=; b=NCcRLrDcE2cvgUBAv63KaUbokU Y5QnudvFEylc+KyfPJtVkWD49rANJjiftgDdH+WNjSMDqoDCHAOuz4YV0kyjMMnuM6+0XF0jGOg2N 20OBF3WzAsmWKhcfU7t17x182UNE2RvwGKVVoI+g1kTVbRmOYtCkdTlkE2KawIKMEWRyB5NUCRCo2 jItqMMQGeQ8/TVd0jDPb8/pwybLfgMz1dpvg7asCYK+s/kcTpDagBtVlcv390VoUVRnD+fcW9IqC5 otuf65keEz+Wzp79HNBTW17sFjvDA3rki8tKQM8kvCqdrekJPz0mYBtr/czYJ+2INaG7NZgcE0lgG gvZ0Zw0A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElv-003YHs-7h; Wed, 17 Nov 2021 06:50:19 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnElk-003YEi-HH for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:50:10 +0000 Received: by mail-pl1-x64a.google.com with SMTP id i3-20020a170902c94300b0014287dc7dcbso553136pla.16 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=yqHL5bkUNlShkhCIdSwN7B9ebtVttlcMyblRK5NERpBi3lOlHK3gkTBTP2EFUL0uYq baVG3EbxoZSkydJbmd0QkJ/KNYxS8INVzhPdfyP7EjQwsOch4sWA0Z5afpyjrffMNQPj FnqUWBftlilkW5vliL99SGgQN1CFA/nNZX4cDa267bKS0rxU1fxlnqEH1fmKoCJIZF0E eLXjA/s8NfQKAGoFb0E5ZbYc+0SqxSpi+XlW0kEFWuGC5xTmqNGbP47l6UiZUXmDSkiy pK9kurKebfHpqkX6W5IFfdUarIRZUjd/1ON60bFAQkqV4sAeYnN/4eqvp+4ZK0cwFRN2 R+tA== X-Gm-Message-State: AOAM530iLFFgUpH+IVObQ/2IOtWIFBANNXRN9ETaS0FjHj5TrTgP+qKe rOz97HvelWoe7wv3qy8DjYr9bu0vjy4= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225008_609966_9008CC4C X-CRM114-Status: GOOD ( 18.11 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692831 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 17DD8C433EF for ; Wed, 17 Nov 2021 06:52:02 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D42276321B for ; Wed, 17 Nov 2021 06:52:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D42276321B Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=4v4OQYiHWa3XNICtNCdt1DBTLZswW1aVEfHeexccfjE=; b=CBjVQ0De9TQ11i1dbGR36HyCju X9+y0FaIceAFa5zi8vPIX3Yo9QftqZj+Dl6ezJlIDgAzubAAXUffDKobBZDH8ROJ0zc391JYMW6wp LgyIm18VI3cXeIn7D6sBx2lVKuRks6qHJnA70LCHEFvTEk2aIGOezQaZ22soIQDB2GnnQ7o1XVPrG jMBiOiLIygGBlK5N+TZxUsQzkrB0Ibgzt0s215eLBlNV8wNTKPndZk+X9lDvj51f11soOExHpjDyv oZxgMz8r5T9cks/ZwxSRp5kK8lfl9KxPuRo9p1CPCs1PxYrTYKBMfDpYAOfNzNubjys0rsxol4al8 pye+5gDw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEmF-003YQa-9L; Wed, 17 Nov 2021 06:50:39 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEm1-003YLF-O3 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:50:27 +0000 Received: by mail-pl1-x64a.google.com with SMTP id p16-20020a170902e75000b0014271728fd6so550354plf.18 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=qOR2AM95pcrVdYVU3NgMGirdryRduCa9FhSSMSdgy48dOPbaZbl8skzu/Cb2qZ0S0q KiFFaYT5tyCy84k+Tj8LUoW1Oui/0140ozYd9WLil4TFbArhCYXanGbkAh7UBjjYIoGY RZGe0h36bgSB/kl5c261czNzSRmpDokRarA/2V3oIUnfp2KF3rKC1FP2sdWEHrXTqw4R x3CkkMHUQ70cq0xkdKLzRwntfey/LnnK6ozEW/vxr7HEWvWOTxqVJKysBFSoN3tS4Ejx 5u/qs41Oc39dbvsSjlqeZaUadGO9G1G9dj0Q4847sDPmMaO088QCodHeN24Dd+xB+a5+ Vl0Q== X-Gm-Message-State: AOAM530twvB5m5CHURQECc4MNNJ0lk4fcMT4eKHDQCnHlqUdJsy8fdSs Surk6fdrdnh4hj1aJoUns/A80ubkQcM= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225025_829286_1946C847 X-CRM114-Status: GOOD ( 13.64 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692832 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 B56C2C433F5 for ; Wed, 17 Nov 2021 06:54:28 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7486061BF5 for ; Wed, 17 Nov 2021 06:54:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7486061BF5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=bcGHZe+D5zV5q7J4ACx3fAAVuRPuJO0hRwV8wFNtAxE=; b=JtaLP33Ykzg0d1BZjCoPKrQrmq P/0kigqOq1Raw/kvAIT5AmhA8eHSFweEfY2IEk+p2A7P6jk1ZJ3dMEISP6rxaEYFKpJ2TcMsa+NTw KSAy6cZoWtX+X0XP8osOPCIQuQnUrxe1rrNJ3To6MigYYR7N755zrSjKJEMgeApZIRz0Ve7RsUl7A LVlrBjcErSf9or01q2cnAA5nlsOPgwfJ5e9qf4Q648qqyuLSBZgvZn2paVplufpTi3tzo+gGm3PrW BUWAfCVq1YQB6cGcvIheT5v9b9KEyOpU/3JdyAwWhHc8Eljkk2xXC3EtU+tBYi2RkchLlXIle9OYf t3vp0hkg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEoI-003ZUY-Ua; Wed, 17 Nov 2021 06:52:47 +0000 Received: from mail-pl1-x649.google.com ([2607:f8b0:4864:20::649]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEoD-003ZRh-Nt for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:52:43 +0000 Received: by mail-pl1-x649.google.com with SMTP id l14-20020a170903120e00b00143cc292bc3so579729plh.1 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=v1Lu0R1PX7od59wEpjT6oF7mRSYWFcb4coYESApIJUw2EMiLtq03gO9cWFb+7dT66Q kaH/JdW3u7qF8qnz0i2gDr3Rt2TfvlaHuz7tYgDurjbrQJbStZ8SaZHpKh2ylfiKtTjP G4LCImRClbpPg0Nw7fmjPbVsDlumQYtm7LYy5psFzxOq9gre6pkm02Yhk4Eej3AQSKRP R2RWochzT+QIYTJEDuCDIwD91uoKrD6wNr3rhnS9joewYs57etEOqvIh1G+Bx3oy7hr3 1LDOo68kvKmZdgpis/FFSJhQzRrxTdS28oMjUojkSx0149hcyrACjVj5du0dLX77kXZs SyEg== X-Gm-Message-State: AOAM530Qi/lUMGSAYxZkJULcCsHU+nYhJiRKjpeP+CdwAYxwIO5le1lY 9l6aZnKIMa6N/fvN4Sz/T1BJAIPezZM= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225241_818618_9D96650D X-CRM114-Status: GOOD ( 17.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692833 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 E9BE2C433EF for ; Wed, 17 Nov 2021 06:55:03 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A326561BE5 for ; Wed, 17 Nov 2021 06:55:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org A326561BE5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=XmMOHcBUjqacX9Zqaay+VccsAEAJrqa6oRDW7I5+ykw=; b=ecEiiXe24l3dz372CfBTSlRHNT aQqQ6I/EeOFGVEcMTG0/+phKpFWlIeVKwAgcD1gjtKJzZe1VR88pqRd3QuljPM0sJQBT5Ii5J+YUv hsurh0OqNJKPyJAWHobrsC/ayfJYHsA3B1tV/NqTqk6520IPIeoOyKxO3LbQPkyjkNXvHGE+5jH7t lGg/C7VtJxXBNcDRapASBcy2LWq41fp7GDJmc5SOTcLCDDlELAqCqGy+IqmF8CzM7kFB7emR05Vus GLc0r2QbYGXoTwIUP+VZmxlLiVARS+0kMcrhrLwWuAKG4/h2PuwlZYfGnPdwlY94QzaFSrqpix0yo T+Ss2cHA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEom-003ZgS-T1; Wed, 17 Nov 2021 06:53:17 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEoN-003ZWr-T6 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:52:53 +0000 Received: by mail-pl1-x64a.google.com with SMTP id v18-20020a170902e8d200b00141df2da949so568067plg.10 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=s77kzWQMrNH+SYP/Q1tAVz1WXNGF+z5YCXoXJXbrVffP1s9HXz5ZFFeU3dAQpxegCK urd1Lym3Du++nicvpU8pOQYvsZvUYmTLyySVFeyI+pSQZ8u1uo/2pVuaxRAFEiJ8XKq3 KbDyNZ4zeDWuzsioHMheAjlZ+7h7KFT+VzJQWUkg80fVpaS46GKoo87eKCHMQYkdBYHa RXOf2D07TuS/NM8mHfopiP6a1bV3jeBEc6OdJsEcOEuOH3+WQo7iRkoCOaWEcgy32zhM 1N8V0oPPGExGMEfW6jn387vocON+hGxzdufev9JqX3dbyaBFzJsz2owrAddnEhXI79el 22qw== X-Gm-Message-State: AOAM5311EiBS1wa1N7FzxNKEHf81lwWsCnZlk/q1M5CGAshVGRPxN4VL p8G6v3VirnLNL7d7H6kNv4aSS9qmaNM= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225251_985339_7777CD72 X-CRM114-Status: GOOD ( 18.95 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692834 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 470A3C4332F for ; Wed, 17 Nov 2021 06:55:40 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E4BB61BF4 for ; Wed, 17 Nov 2021 06:55:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0E4BB61BF4 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Wb5EdYOAwX5Fl0hcSsDR6fTpRdYiGCaGMeCNlv5/3so=; b=QGP0DM5OFz1MkW+l0Go1Nvv4YS H7fm3Oe/csn9dWeLRjhPUXYL9C4ucBPc+7dXBFnembIPbymI8ssZs+g/Ap6H4DPf6xqzyz602HCMH JKHuVOlFbAyLKFQjpB0jQoW5dTJSOr2a5xN1vRUhjmzunOWgUHM6IHJgTt+srrQes3l3RSHTsfgB/ MY2dTWFxRYDpERhbBC89xCefEqNRicZKrnEMrsUexaUnfVQ6WRhWb/uAiBdkeJNCWcHLF+/ix6gwy L73uFVj4GNbANwvpdOq8WL/so4egeQrYZuXqbqRiSnQ4UHr4Y3qyvoz1IWx0wi6KhLCdP3Vd5/Usn Pq6pKBFw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpZ-003a7O-H0; Wed, 17 Nov 2021 06:54:06 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEoX-003Zaq-Ta for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:03 +0000 Received: by mail-pl1-x64a.google.com with SMTP id x18-20020a170902ec9200b00143c6409dbcso574863plg.5 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=yLXT+BkWzmOImAO/ALTH6aPhMrEAVoQOewEP17vlfJpeI3WW8fUDa6WLur1jLjlKli eV80wwYnpL6iFNG423T4Rf46hlr70iNZs4jodJUnM7oIOK/fWkU9gnAmbf9E0aZRCEUK 8PdEP6tVPE7jLhNNgE3zRiLyx3SjXCIZjdTZNtZ7T3wYgAzYodyGxh8lZwImFk6UImVK wgmrHfi+03vz7J7sSx8UsAoRomwaHvyPeu9E3oSfII/vlQbT4KtzREKcL7hjQu8/QVXy q8bAv7LTHj984nVATaUlWrS0pu5G0MLIn5xyWWDUbY23macuxoJHTWWhXZD9IUwxmkyB 5l2w== X-Gm-Message-State: AOAM5325G7JCSHI3CPzqPSTANxgP+ij/cX1WpnSv30oIgwnGl7pmfRCc jIe25xl16SorhN9nPnJhxMmLf/jsPQo= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225301_998033_DAD420DD X-CRM114-Status: GOOD ( 12.94 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692835 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 68672C4332F for ; Wed, 17 Nov 2021 06:56:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3740E61265 for ; Wed, 17 Nov 2021 06:56:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 3740E61265 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=puZEE0sJg0xT4Of/KHzNcjjBbzerNHYGP65DHwAI9CY=; b=YnABpeAx6OiZlVBF7rzCgATF2m wlyZsfU0w9sJlbzbUGFrue/GP4xRzYt5Lkpr52AuHKOSesfmvAjBjU6JDePkxHZVV5lLpSNR1yoYT 0BCsIq3LsU7s7ixjYyGnXKDu/5GmpPy9xuB31698pKsPAbx8tiQ0ArzBPIM6+sgTvXEZ1evEvzWa4 BbM6s+M5wsQ0noI2H6scAeDCPOaWA6+oKdO0QFfPjhVl4igARowilyeT1r8lD2zBA1Tbg02CyHqYJ hQbz4QBxINsTN/4LtUaGOSfiuoFY8LXXaWOdsrUr38GkpA4CQ55cgoKUMs08H+udwh/u2o5DkDOR6 1cpHGWSg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEqG-003aLo-3e; Wed, 17 Nov 2021 06:54:48 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEod-003Zdt-Rn for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:09 +0000 Received: by mail-pf1-x44a.google.com with SMTP id x25-20020aa79199000000b0044caf0d1ba8so1141624pfa.1 for ; Tue, 16 Nov 2021 22:53: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=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=RqBLbN5mtBr7Zk1JkIGDeqHuCkpYrJhEIfLG/7H/LtqjiptmzyEHnXmDLpZ97dQBfB 5lPS88ysDEzBv/uoUKA2hC9v1hrPea9iSVdLDvfNAE11F3tmOUkgHh/ms7OuR1cPTUky vuLACzNx8gzgADyrkZimna0y3aKlitxDSN6ufgNz2CP6JGdFY6Xvu6Ik8zgJxu9ZlaKl qtPGRx+HT79WfXtKhBg+/qsOr91Jc8LpHWDBoF2XUliz1GVfHpRj8sKyD96y47QKoS0D OsEeZdJRCfKdQbcTE5JqaJjxO/Mh9DAc9fdv/S7dlEPEWBwvrA1lSH+JnSJAHrIlakpw S94A== X-Gm-Message-State: AOAM530KXxoFn8TU504JXsb+REG2lJ+CHgVx3Kc9GxYukj1ICzFsGiSu 9IAgWjTWN1CZoMLGA0gw/HFjsVBkNVA= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225307_948963_4E460B68 X-CRM114-Status: GOOD ( 19.09 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692836 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 A5DBBC433F5 for ; Wed, 17 Nov 2021 06:57:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7549D61265 for ; Wed, 17 Nov 2021 06:57:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7549D61265 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=768oZw6xuZnvXFHlZqdYiw1OiBluipunWPpum4V8uiE=; b=pCYfMoX0lgAKnuhIvP1YKfa5bL k7HPwKd3wnx3G0NBuQwAb19E5jFSm/vfJTKYgnkxFdTed9453L4BQJozRJGPeoOAJ2wtlsWEAeuHs PMoXqgEaGVf7eUdGRTb98cA2PcLBHv0groPBl6/W3/i08TWsutj9upqpEixvTCPMdBVpeYhTSIct1 uoOmEZE49TsDKFp3HnLJp0W4C44lwlWOL14D/frLy36lhYvUrfco+2fJWCOWlQHjNFsoCMgOqGhVA +Di99uKA3CSkHU4uxefViWkryaM3AlmHPKB1ZZYXKc6l2eb0mshHGXbzXjr6oFAcwCE4cjhZGQ7sA c1SZsQ9Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEqs-003abw-G7; Wed, 17 Nov 2021 06:55:27 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEom-003Zhe-30 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:17 +0000 Received: by mail-pj1-x104a.google.com with SMTP id x6-20020a17090a6c0600b001a724a5696cso847198pjj.6 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=Uu9AYKPgPzHorkWzgScOhzIEcuFA7TOS32/3PnvyLWkaGqU9ytp1KOR8tQPy3qDsKf vSceEX77eDnDpWbQGs1k8iD2ySd0Er+j34b21ZmwCX8yuHOgIFr4cKGqdQs6zffDKHih SESaxC0FR7bmhh/yHp1M1yIDIT4YvX2y3rhIHTm4nADlVZNYlJ4XZvOXV7onDlUTUrjg ar/hyGhai6uHUauOcdR9JKSvULP1YH+kxJK/SqA0DtHMA3Hw5ErOc5sazwAopdwzW5+I b5j67eUSYkQvHVkSYA0qhLEw8QJpGfVGp6bidOXaQ1R+JSzgeGBdrF3jhQlNJ6cECy7T jWvQ== X-Gm-Message-State: AOAM533sz0bLka7cg+4vjSgaMXegVev8B0zztyZGPeEi8l47WyYMmjiB VsZTp3U0mrcQ+rLefSfKgLLD8XasBWM= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225316_197716_42D8EE5D X-CRM114-Status: GOOD ( 16.57 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692837 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 AC5DEC433F5 for ; Wed, 17 Nov 2021 06:58:05 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7065861265 for ; Wed, 17 Nov 2021 06:58:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7065861265 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=w5/ot1lEtnexDlaX2pNsajulUD8l+dJTfUgzAkodW60=; b=NYryurbvG7k2RuGOo2yfYLqNkC pZtUY2GCEBW7KmZtjhaGft3ejIoLIn0SOznbIyFl+r3ExE3t3WmVeu5vOB5pDgFMsfr43ZDbLRx89 pnTA6WAr2CeQplvLNrz6bD5KIIWLsPHoQT2xQ0hBSigpaof8EZTLD61sfPi88DESwT/EVuhzvOxjU AYvak2alrQ24h3Iy+FEKdF8CWwKnpSUBtj0/2Um4JQK6K3RKcm2hmnfaTLk/ggG7b/MGWDkab88OL egGF5ZNrHabxXbFgAlS1BN1XojfKuoZWsszDwYWqhgFvfDaFH4fENgh4SnI+kFlu1W8tVomySnLDk 5tZCHlkQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnErc-003av2-Ik; Wed, 17 Nov 2021 06:56:13 +0000 Received: from mail-pl1-x649.google.com ([2607:f8b0:4864:20::649]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEot-003ZlU-6I for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:24 +0000 Received: by mail-pl1-x649.google.com with SMTP id v23-20020a170902bf9700b001421d86afc4so568705pls.9 for ; Tue, 16 Nov 2021 22:53:22 -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=HR8Md9gpZLOg651LdeynDqGrj4UH2ATeXlwaZ0AEkZ9IHhVNUvbXuqtvC2Zg0F9Ehq UYTFYFdARkzK7KhMfQ3fStEkxVjGhqsfhtsb0nWaFQay++OyNy8Jdn6AEXoNU0F0aHL5 P+2JLFafoRzXubMNaR+GvSsZMNvj7tbuNdFIyrSo6Ds1YZEh24rUhDqh4QeD3S/9CBKi eYC93a5KTAGN5Fiv+kPA4PRYM8Z3xc+QKVn4pnxlFNhzDRHMSI50Avzvo45e1hPRynQK 5UT6UdJpRXUj5I9Mb1MsfWmyJ932Wmw8gg21nZf+rp+QxZnDsNk1nVZ8519JTweN99vt 5vPQ== X-Gm-Message-State: AOAM532DgsQlGdISc6kvH5rR4WFyvsHfZvFDOwlXUaucib9ZEjIwrHAq JcFhZ0CuNN6obsi4/t7tftRf1xBpGhk= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225323_277397_99CE14C3 X-CRM114-Status: GOOD ( 10.98 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692838 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 6B77DC433EF for ; Wed, 17 Nov 2021 06:58:53 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 27F0660D42 for ; Wed, 17 Nov 2021 06:58:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 27F0660D42 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=SaqEJdjAQtrzdPtMVCT49/JZqLF427/AVhZtBsBrfjU=; b=BIcbnrc+e31iiWgrnZq6MbNeK1 U43kaPHBdFU6IMrVmQ261yMf4NajGYRu+I0pmMBt4YoGF6z1tpEe7iTKCdswOWDlg1rTGzDcEKRrz n+YRCd0pumBc+RmTL6Hfw1mndkfpdGDanrV2VComR2Pd0P2TgBmvOGKcNJm5lDrR2J+LK9vUZgkXX PJJMqk/fiTgUu9hI5A6t7TM+B/So0wDK8sitYuZ30P7+/satCXeR7rjOmI50AIkqS0Ck4kfEmECYc 5ktK4bPmXZVxcq6lxHAfvAVsE+Bt1ZBycFN3MiUj2xtIRbrW3vISSaBr8RgWN0DTmiIp1sHXYlN0V dzC6l4Pw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEsS-003bFq-3x; Wed, 17 Nov 2021 06:57:04 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp0-003Zp8-87 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:31 +0000 Received: by mail-pj1-x104a.google.com with SMTP id p8-20020a17090a748800b001a6cceee8afso767661pjk.4 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=x61qQld/coDV5j3Uxil/5r6tC2r6E/rENLMdf2S+CNX44TlSnNzCY8542gBG5EUPp6 poTcctlA0gi40I9A9N0wGPZPm+J2ct15R1/bUPPR1PO6Ih6o4TOWArDYxlxrQe6AErIg CyQVELisOvA1jaSQiPTZsWUcZLZXT0oqxl+wKm4eCr80rsisaG9q5H28phAv6zuECoTB mRkR98pSeA42+JWps3HXrp5WYd2oWqDQO1GZwiEve91ATF/cz0dwPkhxw322aqSs/4q1 NZrI5dj6x+123ZZ3wcfagkMvhmRH54zOT+reYzFNaMcr3VmGbZG9IUFItMrZio4EZ+D6 Zcrw== X-Gm-Message-State: AOAM531AMuoFtAUqHqVAZHtAA7piyJiVtKLHPn/KDknYVrqNjMMgXuu7 hjd5JjfXAualg5NJbk8aK0bZ2F3eZeQ= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225330_346562_20FE56A8 X-CRM114-Status: GOOD ( 10.87 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692839 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 14D49C433F5 for ; Wed, 17 Nov 2021 06:59:38 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D8FE661BF8 for ; Wed, 17 Nov 2021 06:59:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D8FE661BF8 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=TpUYECVCI3ikhcpnUI5N488pm6xo7Nl6kt4QHiCtS20=; b=zU5LTWTbk798suV1q8TcFFYxsl AIpYedvlQNZxzQMHY1GtYD0QYRJpk20En71M0GTyIn7uJU9Os2P4j7kXCeiELFg4+wn/RiO0Ngbqb rPlFwZGEQ6Pcyt5h6PfNbYXvB2VTRBeEod8+Cqplg+YRZOT0FwRaRF2TDBCJNbwxpF90kl7ZOcB3W KRmQLptO7FHc5j9gkXVas7xC+eI4VxDKkc+YVGzeAB177Ex93xoQ1uhmIalG2tpugGJVA0eugujw/ fbanHWcF42uLUVhGcMgOjWJWs1wbYHjZnRmqbvNuzvqxtM+P50ahIgQLDxPgW9xg+ZkXzPEYgm6tR VVumZfZg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEtE-003bYp-9o; Wed, 17 Nov 2021 06:57:53 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp2-003Zq9-3P for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:33 +0000 Received: by mail-pj1-x104a.google.com with SMTP id g14-20020a17090a578e00b001a79264411cso772849pji.3 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=BtM1envHIalD25fVp3C0xnFr+bkbmyZ1wl3Q0hcjNNpdHssy6bVIBMsmoNgOWVvzDj pp2tuvX5IfmyneV4VQOGLVCp75Rjp2ZUFZwTnROZbDoUc+gzcS2d4VUX/A61qa0Wy1Fx aLWX4DkSfTx0DJVi16zRZe5C9RribQE2wxBzO2jX98JSBuA60/M+hMViaIR0rs83fN0O Ezg71TFjlD+6/KuZ6Fs4VMaCtgc5qdlcruRwNspf89VerJj+aGKm7M90OWBk/hEb3hF+ rxRb/JoIgFbhPPcwptKBeG7MprPmo+jEwLjTN/5e1q2ZyIzvtApUs/g007auOgsVTLtU /TnQ== X-Gm-Message-State: AOAM530Fws19/nDF73IHn+zxqrFt8DndUABSaNoe1tGT/t5WbjQD9Gay wK105EaWhmxu9FI+VX6ry4jG8Z6M9Is= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225332_171397_3670D0DF X-CRM114-Status: GOOD ( 17.87 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692840 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 54341C433EF for ; Wed, 17 Nov 2021 07:00:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1B6D961BE6 for ; Wed, 17 Nov 2021 07:00:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 1B6D961BE6 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=UT3CvBXqHsH67hCh6y0WtunErTnkPz4yorlkiWhFujo=; b=NzmtRk8zYW3MEH/KxHSiaHi3KB YJl6lr/rNmT7Hx6HlnnLha2UynEcGS1eXQNBFQnEz3wQ0DygScOL9N+kCbGhFrrhOLwmNrU1xU8RZ gS7WzZ+YSmTtsUFGZ7/gNikJnBOE4juglIbavYG/S2F2uPfECAEuJTA2S8Kr0Z+/vopcQZC4GEozK Xd/IdsK3pyeIeifuhk7ykrFRUrQ0yIrkFaASMlFMyiLAnQXbIdD77VjnlokyIRKyMzu0Pu/x1YL54 pXeFCPSRgU1Gpat3+dA85V+hh0O8ZnIFeGI+3zWEGW+2mdI5p0l/CHiojF30fX6Ud1DFjB6nIiWvC vgbc1FlQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEuA-003bvm-DN; Wed, 17 Nov 2021 06:58:51 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp3-003Zr8-Mr for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:35 +0000 Received: by mail-pf1-x44a.google.com with SMTP id y68-20020a626447000000b004a2b2d0c39eso1107019pfb.14 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=u1NhA3NVwOx13+Bo6gNn0GJMwiPFsyzID+4YfdjlttqtqciibmRxh255PDXu0ozl1T N6KzfpSl2KpcUb8rnckS+TOr3WzM+G8pI9eT536cPiAyjyf7KgpCw3Pax3cRvh5NXZQx hwplxL5jBkGu9nzOVU1OtX6Io+Rjeap4M27CTKRxqrneZuVo27xRxLmAgS05J/oRLbJS U4ntT/ZzQ9U95u8URynlrR61odVRBBl/K3hZFl7Gw128Ep5qaccuhjm2KircKgISj+S+ G+Z/ZVeTJlfpKLmJVnDDxj3p4uPSaO/L+8jOwArP8O/6Enps8ERhxmWGndATgVuWeIys xc0Q== X-Gm-Message-State: AOAM531UVffNo4GSRhlNfHQUJzV9rhYbua8ur8N28T+Edpw3sjIwQvrB 9OoM1B2khGXyTCuC/laPSwvUgVayVXA= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225333_799886_5DAF48A1 X-CRM114-Status: GOOD ( 11.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692841 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 A4557C433F5 for ; Wed, 17 Nov 2021 07:01:54 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7254461BE5 for ; Wed, 17 Nov 2021 07:01:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7254461BE5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=O1J6p5HZazX/xX0BE5gXLC38TxwZOXs25ERCYQyUNdI=; b=LBpGWYd1E7O0AJzr8iTaUvDS9G ld6tPem50r2T5O8GkZ10LJb7NrPQu06aEKFYH00cnrZoxSN8miBmQSmSMEiJk4mCb98DdiV7KMV0m xzZtum6L8rPhRsTuWsxGKnba6kpTk8PzgzgAxMIwtlTOKCXkomgBgP+eV2Le/Ij1Gk3bWeebM4+ye l53ZMB0wZM5MIIXvRWreK2Gqo8wshJ8g1wioUM7hY+QmINlCNxkJCO5XFBPUqYhOg32Mv9f8zMq5G PEB1UEgA6bJtTjrQ0v15+hPfGqF3I0FdecFyv1eCIMqwhHUbf4d6mFeupeacgngzJaG61C9J8sabi 9wsp58Cg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEvA-003cIv-6E; Wed, 17 Nov 2021 06:59:53 +0000 Received: from mail-pf1-x449.google.com ([2607:f8b0:4864:20::449]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp5-003ZsG-BP for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:37 +0000 Received: by mail-pf1-x449.google.com with SMTP id g142-20020a625294000000b004946d789d14so1139398pfb.3 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=8GTW+ZmahVLH/FDZub0XrklvSf2cCYSka1Yjp+ZDl4HmW3jOgY/nfw3lpGqW6Tpj8W 2KeqgYIBN3KE2Ae6b999FdbO4TZfZnWnUY9EsDnoIJTLr9NHwzYSOELOgkjqgk9r/xaY A5eAcBswmSs2eTdZFfhSiGuyFuONjjXi/huW/8kUHO3N3yU3BrDlKTLtZG4TBLxGff7t /eOn0DYYHNJEDH59Rf+uASSMZMOlm/rIfJowFJ85qlvzzj8x//Gnkb5r3BzLh192JRrd dR7c1nPrFzxd1Zyh2SE2b/BEHAjYIS41qDK9iGL3mxTtWR9njjYI91IfIdQx5Zs3UpiI y4QQ== X-Gm-Message-State: AOAM5336Dl3JC5x4ODni+BkIXZd/s5VbFA3pfJY2wcD52MFrkMjaOgY8 WKKaswz4u1fkRQ0s71neS/mvjsQYHiA= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225335_457358_BA3CA550 X-CRM114-Status: GOOD ( 22.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692842 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 AFFD0C433EF for ; Wed, 17 Nov 2021 07:02:41 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7997F61BE5 for ; Wed, 17 Nov 2021 07:02:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7997F61BE5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=0ZWnK5wgmOJToEiLVV3564TxjbUi3b4cAcn3M52UklQ=; b=mv20b+Uq234LM5WAgOBJ43ahW7 hhA3rHs48x3kKF7eJaPS5AOmilovv25Or7n8OEudyoLOAfS1YXs/+icKc09pB5bcxryuLDslnRZVv zC7yKLyK2x2Kf9Sgml6bBhUq3PeKyIdpo38GsoQ2u/tg73s4t5HTcAtkd2MAzzmoYe5VuXN0grcPn Kl9BCKBwwIxf53Gv5dSVRJlRWNygIB+1vwrtPsuZ+zRL0/IDlxkt6LGwvmU5eT/9CL9vpIfh8SUm6 gWQuDASYVIEB1lwQ3SFP8JRn8q2XKaY5JBdqFb68p94mVhy5J2OacWy0omQHuRLtHusxbTqZlfAhr B3d20B9w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEw1-003ccC-Mg; Wed, 17 Nov 2021 07:00:46 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp6-003Zsw-Oz for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:38 +0000 Received: by mail-pf1-x44a.google.com with SMTP id 184-20020a6217c1000000b0049f9aad0040so1090555pfx.21 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=uIdji4IcjflbZMKv9hqBxhVaT6p7qMH9T25aaX2YWqeMN7148TP9zIvmtN+hFWtHnK /c9kimFrL0M/aTXgrdOWwgBDsjW15f9Es/Mo3qNeDylVAcQFmgzK5soykWbOhQ/HMtGJ XhsVnhxbwCNTai1j3ZPZRYFbeFTZIvbvmjcFm/wQny1WB5JHgZ765lWAuYraFAFzBKQx Wz1YJTwTSwgTgJw4Y11/uUs++HTon6VyJvQe0vNTOIwymSTJ5mGg9MV0iyverTWiwgR1 5XSnTXpz2Mz3sE8e8lc+ye3bvO4iZAnbCsla/4ZVD/r1vDN3BX4MlGM76ZTZG1Ilp+DC Gv9Q== X-Gm-Message-State: AOAM532Wa6zVzbq0GQj9G08x4VJBlkWbcpWagpseoKYi4okEvR5SDi83 nQxTaoOO5ALSTNuJFD72oAyrWqv07/8= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225336_858701_FE11B52D X-CRM114-Status: GOOD ( 10.50 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692843 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 84BEFC433F5 for ; Wed, 17 Nov 2021 07:03:45 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4690761BE6 for ; Wed, 17 Nov 2021 07:03:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 4690761BE6 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ADenlVvgxgehwc/5sVSqtkaE/vTaoHD1svL6vrHYVA0=; b=Umg5n25H1ltZZqlkLfqp+KdtKW cstGyNc1pffb2vqL7ldIA9gNun/yuhwIgizg0hSPLUQglFuX5AuF5aC8VFeTq6Iv7U9ijrN2JRJe4 Kt3qnap8nQuvl8TknBGi5uj1yz59AG7BMeREi20kf9S07QxNUiiqJMvJgmLHxZURagXRUzwLIok1S dKaNkyjjgrF1WvHylQUCmKhxuVX6QJuQAga8ZwPX7UFb7WG7o2z3GOZGvJTl8X4QlCPk1S6vf+iZc GZhjdJ0D8k1b9YJQsv9GrfxrDw8IDJoX/WKnvwvJ4yOvMc1Z/LUKC0ZDAWDqCWQQsbN83z3gPDoQA kuI+5kNw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEwz-003cyI-Np; Wed, 17 Nov 2021 07:01:46 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEp8-003Ztt-C7 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:42 +0000 Received: by mail-pj1-x104a.google.com with SMTP id n6-20020a17090a670600b001a9647fd1aaso2633278pjj.1 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=el7fER6C171quLs/mijNlR7/N8BpngaHm794Hqm+GX0CwZnQ5Qlyxe+2L9rgJYxHS/ nm/HdZ3tAvD012B1fOmN5kbrqgd5v/4hddEIx2kzSjE2foJNKo0OaaPrPzAU5jlv73zp LjiPy1hts8gjJ6lB5utvrsYJFt7Oz/9GrZbXPB/Xp52Roz6KyPKt0/azdA9rLnpvGtIO wzFVaahmxPOC3QnQFIiz7dhavK/hfvlN528Qqt1V4W0N6Vn3UNRxd3F9iC1tHe7Kyq6A xsxQWiadpG4b3CKXKVVNwELcnKEglb5fDr2qK6m1OWJzsu4LfaZqvaBoud1ex15gFMM4 iL1A== X-Gm-Message-State: AOAM532ptuH4pcBWbNWTml5SYYNQOlL6FqUEhSTdHe+8oHZdY4LSC2qX sTH2Mif2a+z1C5mJ8hstQs5vIOd2Als= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225338_506551_B49A0681 X-CRM114-Status: GOOD ( 19.32 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692844 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 0F261C433EF for ; Wed, 17 Nov 2021 07:04:53 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CB1F961546 for ; Wed, 17 Nov 2021 07:04:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org CB1F961546 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ICwNs+zYwrril+mLZO1Es34Yy321YF9go6g4PxYkrbA=; b=rE9hFVP/3pIS3PvR4Bw98OA2Sp FgXnQLsq0UUx2uOBNQNLNhcJZCHY5GISeDjRToX/HHI3reqtCCsBy9PEGFjI0MBoHDwOAig1vL+TD wuaIXFFgTMtWMWzxuP03a0gTYJfNmrlXIOZNPbp0hN6DNMr2w9Cb922NHHs5IXtHEfqkzO0k2yDfO fJXCBiYEor0nYw1uOesIRGdodHwkp+++gVgd6PhAGY49FFkNgdC5aIMUKINL1thUtAunD0PkTct1o 9q4NHjy1ebG9iwHTanRpsdK63i+W1sLI+RP2Klw3ppHpvs2GJylaA/k9ACvfIkQ5Tus++0LpvbsWf Y+Oj77EQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEy6-003dLV-Cm; Wed, 17 Nov 2021 07:02:54 +0000 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpA-003Zuu-VA for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:42 +0000 Received: by mail-yb1-xb49.google.com with SMTP id v133-20020a25c58b000000b005c20153475dso2489310ybe.17 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=CQ2ZytC6VYWfKx6JmEOiKaD9iuh0Rl/LOaJ4g7rlzjgWjDcqde9jN4EpXhZkkY5BsH jX/LuDuv/TQfYUqr7kvlQcGUQpX22WZZeFBpXLOrp78Q4dPa3ufc5zv7XXAkexvAFsB1 3sSuo8BBw6LEM58DLALO27D4YztzT8lQ/9BLS9dE+MMaUAew04IgNWLlRS5u9TMi/Pxj k0iSmPyOAgZYCUlBEWt34xbAdpjR/yDqHcZVYA0G7m15/nC+Xu+lWxF3XhDPxZMjyqx8 lgSgtxOuy3eftv23NgsPeCURiHbqu1+cC6BOAjA2F9yt2l1+cVhQz0mB5TMazITaE5Zq ekEA== X-Gm-Message-State: AOAM5319Ie8hEmNItHcwyRlFIF58MxpKOK3vAOxYNV6FsaB4b26vYPY8 ZnNbSUqqCAZAIZqA4Z6iToH63jmVAjw= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225341_070978_CBC6CA2F X-CRM114-Status: GOOD ( 16.55 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692845 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 1F06CC433F5 for ; Wed, 17 Nov 2021 07:05:50 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DABF461546 for ; Wed, 17 Nov 2021 07:05:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org DABF461546 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=FEY8bBoiltktGmkIN7+2gityvvRyIoamBFbiRx2msFY=; b=qWQnh+Y4Cpl/3Ar46VOQ+D0EdL fUe6NoOs8/CPdkpQ2CEGNRpHvZ5FpyDMPL5UOxZmboPxDkSd5cEBfyDVey40QWI7u9Ap3RHA0mdN5 jfGOYbfskrK5ed8P9wpWsMj0NYWIkLAAhFmWZsiCH/zmYXgvtAVjruIvs8dSZMowNNVR0a9MoqaVa /vIiUqgRqLurX6nXYhgptn9Da8w081hkPPXT4n8TY/JtroVCcBDFLf4rMvtqdFmD70GTkw9ycSdVN 1sy9FDdeokP2PPaq3rynTbYShnET2Ek9VRxPWzPBr85G/R6pfiJWoFAkLA2cRMiuyiEQJxGBl4Op8 CaFGpLzA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEz3-003dfk-H6; Wed, 17 Nov 2021 07:03:54 +0000 Received: from mail-pj1-x1049.google.com ([2607:f8b0:4864:20::1049]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpB-003ZvR-VV for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:43 +0000 Received: by mail-pj1-x1049.google.com with SMTP id gf12-20020a17090ac7cc00b001a968c11642so855279pjb.4 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=VbOe5CkhuxxQ/BxL3hKq1F7//WLW1ROnSnT+QPKqlAvnxuE0PvDtDPdeWCukVSgVXy C1McXFU08jDJnwHHaJkDQqCAuAokKxJEB2gGEdQigDVMuqi+HUdstuHLiCUkocw/xzwu k7tn4B7nleVy4dS2wsrSxmRhrg4MpO9pq8gYT4Lf+Ta2ZZPl59IsnPhwaVpmgxp4fqAg H45g/qmsOKU9xmj7ek1FsU7PDHHMc6ePS0b0wpea2SXWSQoB8Ry+F6WBqTaOeaH5Xdn8 R3bEJvn1K5Jy65aHu/QoH+mw3s2i570lM4bXIhgubFs2XlA5SrrDuIn8AHlSD2z9QwRs fJjg== X-Gm-Message-State: AOAM530/YWzyNlVL6GXFgEqkDQDMNQnReLpdfcQFRaCjDVgP/ASnqcBP koFeJ20PGXYXlRoCuzIIhyEQcEjZLH4= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225342_066090_276865F7 X-CRM114-Status: GOOD ( 15.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692846 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 F3D50C433EF for ; Wed, 17 Nov 2021 07:06:51 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C320261BE5 for ; Wed, 17 Nov 2021 07:06:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C320261BE5 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=5apKkNt249rUH2Wp81zKTdEgr/IIrQGNqJtqochQODM=; b=FORgyn+WlyZhX/i+pL+r2jRUPH BIlzg2LmyJTbPNpsP2OV48nAUUnZmK0kUbfCNMj854iUCC/V7nFIBHYZp02MbX+ch3ILdADoR6pnQ qbFD4R84ijA8rJ7Dt81/MTC/pJJ36UVMXN34bhGEZvUWeXAqo2rd4hrpUKPjBVL8qwcgtc1jG5zHy 4aq8hKiOaFdXV1cBZpeL2U4vO2bgfu2+qbFVhe7ETR4nlxya1l4KZYFtMKuj5aWvX5YOMvuivAcVr A+h2/LX0jmwd9XOpeN0nh4e6fU5wrOAq3ibc/G270wYB1Lbm5gyIQS3kVIdeNfQ3Q02y8OpdaWM7A aZuyeKKQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEzv-003dy1-Ih; Wed, 17 Nov 2021 07:04:49 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpD-003ZwC-0z for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:44 +0000 Received: by mail-pf1-x44a.google.com with SMTP id e12-20020aa7980c000000b0049fa3fc29d0so1118032pfl.10 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=n85yh2hbS2h44hhDn2qo4mRl43Hc42fMMdDm41f2KYDiZrULcygU4w5WwsndxSemxO +rw1hIbJT7X7giGKQA6ERgATd6q7FBI4J7N6jWv7NlZF2N87SedguDfro+cxxK+fJ+06 GIMe5JCXDKZLeQ74of4Wup4UbDpUPG+VE5Zm4Ofsr8IlM+eTQ8RwqQysU6a41lBFpMxs TE2ve4ULIyA/DwMo8vrrfrh/7iWGrfxk3ZmHjZEOUNmtz/TsqQ9VrJnYziqfkXSTQtI0 K8QuTyPA+eR+06M1J45oiRqHs7+v3wjm5NZvSGd94AJ2p18rTdftKfs8E2ZWbI4i5PHB dhDg== X-Gm-Message-State: AOAM533pWS3QU35E7NvtXIkLdeLVxDGLGhH29Q7aQIh6OnPhiNlKwtgt UK/+CFKRbMes60MlpaRYdYpHua4k1oI= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225343_140996_59D4503E X-CRM114-Status: GOOD ( 25.76 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692847 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 335DCC433EF for ; Wed, 17 Nov 2021 07:08:39 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EEEC761546 for ; Wed, 17 Nov 2021 07:08:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org EEEC761546 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=ZZogvzCVzvrKEn1c5HK2eFCxoeqzNQDR7+fJeSzxT/4=; b=Wtl73qPhSEPpCYzAz0tJ5OCv/2 mRZcW3Vvmv3KL0Ghk5nhNSFk6zJuv98RtDb1InwcDC0q3o0ZofA8PfZ99NyM/1RPwicnnDOUmPhwD kOdVwOvbLG8DVjksFpLBdcOm4rEspWUOHltKxfzdR0aMbRNZGpbG5UChdAhcPWAk60eHpRkkcOXn0 aTJAcvCoSU+/oGv/8sNH5SG5cudGoUGizDBkVP3tZYU8GD697vz6Gx/hwrk2Kky+zhN22etw2pMzW 8JpVW2K4c0sTFUe+layx+N0IH4d2i/dODqog7fWhmDjMCwZCMoMurN4EUOtjph0CqUl1yamjLJ5Z/ /2szqJww==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF1Y-003eV2-Sa; Wed, 17 Nov 2021 07:06:30 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpE-003ZxL-R4 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:46 +0000 Received: by mail-pf1-x44a.google.com with SMTP id x25-20020aa79199000000b0044caf0d1ba8so1142298pfa.1 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=QxWAl/x9UwMBu/RBXKiV/1FW0MHyR5zr8ClzIRC7ZtCtvKvqhRPRt1aNXucSTzaCs9 lZUIYfdPA3XilZoAWXhGkNqXOTGNCxBfaIQzWQgg1FJUDe58VNn1QzEPYUYYeiAx9h8a NE1bbWUrtUnPcAXGydFrMmI8/dQ9dsqeJVIP2rqNM2SHGSUQN3zCBRyfu/k44Zt7q8kP OyrhIzDQOC1v3FD1R0YXxaIz3UIW7RwfQAmt2PvwjBz68ockWJuILwm2hrfQCxYDi3PS jjASNReRcSOzoGpHbpDImTj65Mk2wVUsxoQ/mMdx7TU5y4ZIx+7BR0zs4C7/ttATf4Iw asoA== X-Gm-Message-State: AOAM532jyhspvD6Q1zGVCdbYcntIj3vmdR7op6r78XWTmtGfB4ncwdvb s3r+8KJC3ckOYY+vxdNsTU1QMOBw5Mg= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225344_924239_3F482458 X-CRM114-Status: GOOD ( 18.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692848 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 ED09FC433EF for ; Wed, 17 Nov 2021 07:09:46 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B344961BF8 for ; Wed, 17 Nov 2021 07:09:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org B344961BF8 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=pmFpq880N+VYka1pUBPyVN1jFWp0yQrJeHbBdC1ZAss=; b=MB8G/xL0wZ2H8QNGyTlX4ZQG6h XtSXg1kdWsea/cRdqR0Wczs0RYdUeDEr9W+7tf/m6+8adzyjEeg1Ltsb2F3oKwAH1ZlC1XlCCOO7p Qcx76uLVRGdvjLSI7JV2gNAdMeiG9Sss3hOBkoVu9vbFoZ+Ff3J//pPdHtqHQTLjH0Igkl5gZthlP E+BXpl0qTKAjhsGaSVV488f6yFHieG7Bjn20P4ZgL9RnPLFEa8SIsAIr0sKomrehvrFaLCOOntMif Cw9UKFXz6rptk26us8DqnZ+/7UTD2GhCcvIesjOwZDvDu2bXrNQg934XCX0ROlr4JejQKXMYD1mIC tBWNQ4zw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF2y-003f2T-V4; Wed, 17 Nov 2021 07:07:58 +0000 Received: from mail-pj1-x1049.google.com ([2607:f8b0:4864:20::1049]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpG-003Zyc-Gk for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:47 +0000 Received: by mail-pj1-x1049.google.com with SMTP id x6-20020a17090a6c0600b001a724a5696cso847941pjj.6 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=RNrARoWVV4mG88QXFtwNyKQgYhr70xfrrWY43jFFMTiiBOPtHfqjMlXSPDPJY3TpI3 r0D1zzxRfKbcmBL7XLO7IRffXIWzduqTSDLJS5JlSD1PI415TeuUcAiUMlVqYcbgG/Le 05rOUOswH3iiUGQTAfMDgeVHQ2NcacaipDO/N1B+WcmqTMv5P84JN1G+t7gCL4WpB7qa R3/+5eVMrL7ao4pJm23CRgRjZ8uau10/qHzyu27eF41t9cm7m1gAgVHqCuTmKypw6y7f IyKA5SFlBnfv8OAVtWK3Aecw6Hlvh58821PD38tDYYbR5jppPOsTFiQ5NajlRrKoXjXj DGdw== X-Gm-Message-State: AOAM533eZXZLTS0f/WBTHGQDxI/6kcOZPh+BksGLvHsdPqPDLmSUpD8i ZRUWrK4rDRE1BmOpu5CRX4+eQPK1ToA= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225346_592655_A72068F8 X-CRM114-Status: GOOD ( 11.94 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692849 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 6D8F1C433EF for ; Wed, 17 Nov 2021 07:10:58 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2C22061BF8 for ; Wed, 17 Nov 2021 07:10:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 2C22061BF8 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=yYUY+Y3XqkM96UhgsnZy6w+/VSMi1ha8UkT8MtYJeOU=; b=T5xTpwG9qndEG/eWy70aFsOjYz kepLj+A9QRduECfnxo7xm7vDOkfKrr01pDAHsh19lKK8vdGaHDsBW+d2PxeZ26uwu2SKXNyiLjc8o UXepDjaNPxxIfA3YzId3aoW/3ybC8VluiJaLO9MF0R6zaDPosteMpLqnYRg43uadkxuJ+bbYicoGS YVsFtWAGthNxXwd1j8D/oK35pmuRN63yfJukRJrd1fHuIZCjJojKoxHnW/Cj2p+bAefDtdnAoYQbY uE4TOfBoCrPvUSguYq2qPOHfQ0RlDhoTTgWyZ8pl7RSpl/5m47qSaHThOH69yi2hI8EIZg6kK6K5/ 1rWr9vMg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF4A-003fUq-9F; Wed, 17 Nov 2021 07:09:10 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpI-003Zzw-4F for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:49 +0000 Received: by mail-pj1-x104a.google.com with SMTP id d3-20020a17090a6a4300b001a70e45f34cso886246pjm.0 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=GbArjEEtyc0BvvONSmcVsWbxhIpCCMZm9WVUqRQ83qvl6C0rsVSbt4VS10arIdOUr6 OpBY/M7GW4y81Gp1RhGm3P1xKqrufTSjfrQMSfCckloG8x+cBiWYG57M989HFX/f//tF 49j37EFdaBAERc9/iaPPUNmTVtKRz03lXRkeydS3TU7GYXGr0Ez6FAk77m+dkoUiw8zb hRAYorBZhWVviPJex59s5mpV08sTqg5+CW3weT8IQQpzKmB6eSbmJv3gFIYSfQL5wVun rQByErXf+ke9ktmKCQM4pSAd+m6lLyOXegLIcBjGucYlWOebkvqJCUfLVi5DEGGHoL4B jNqg== X-Gm-Message-State: AOAM530on66/0Q5UQVUJRzhf04HS9j3iIfwuzc+LAnQ/iafXFhdXWSJS x1WoZyjJbhUTm2TTRhyJ2Ow+LI/+O6U= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225348_211198_2B928676 X-CRM114-Status: GOOD ( 11.26 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692850 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 BD867C433F5 for ; Wed, 17 Nov 2021 07:11:52 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7E31161BF8 for ; Wed, 17 Nov 2021 07:11:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 7E31161BF8 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=rHXWqL8R5aVjPknqr5dRLmn4xWIutwVhFB8ZzPeVvfg=; b=n56VbY/vEzR7wiw9As/U2yuhu/ pTAL5zm8MrsV7nMdnn2/sgzE3pRSsCDLGJas+CdUZDKLl9SEVtISRdGNmefKqo/ejh6H0lop3yUA3 5VNJafy1ogtqYlZ+01OY8cG1ctyoTSJK3BFAY4mxIp6PvTJSdSlFbnBU6lWSj3HI8COINmQwK1tDm PI9qLQSqK+dAVUYax6tIHvIrjnsC00F9S8B7SPU6W+s6X2U214pOm3R6uOozUjArkKFuPie6SgugS 7lc+2mrEjeV7+xf+0hBhA1sX4KCDE5z8SsqCJf49+Bwh4bjnjmHAZmIu/DvyatJ7m8l1hOjEQx0of G4ifjYfQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF52-003fo8-0M; Wed, 17 Nov 2021 07:10:06 +0000 Received: from mail-pj1-x1049.google.com ([2607:f8b0:4864:20::1049]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpJ-003a0m-Ns for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:51 +0000 Received: by mail-pj1-x1049.google.com with SMTP id x18-20020a17090a789200b001a7317f995cso2623907pjk.4 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=yDooJhCPmNczJg5S/p6KMkPWeFgB744BnRHAIDfBs9Ays/NCKCmLv6+sj0bIu7bqse uJN+CP8aMOGeS9rGibjE8RUUTYMDaciCO+1WuFGke2zXeknrHtYVLcHb1oOtgWxjIWR+ zOeIfHmu/Bavheix5KVXRaBhisiAW8BHRD5folFcOYpbMQ4d+vzPPP20YxOovOh29P0E QJxy7HhhV9U3quwfP9eHa3KdNoi9II6p0uZlMascpZH3thWeLXJsle/+Veaz/UroUZ5t P5hItxIaA0DP1YJrVged27/EbYSHey3WlRReG3jF37KFMidmJ0v3KLF0wGf7q+5aklIh Ec0w== X-Gm-Message-State: AOAM531yQNm+nquI0F8mYis2j1ay5f+p0y/S2yDyAfKqOWEUDML3BIwk XUV32wnvgDw3w9W/OPMh+LLrigePBxQ= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225349_841434_B4DCA17F X-CRM114-Status: GOOD ( 14.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692851 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 8A77DC433F5 for ; Wed, 17 Nov 2021 07:12:40 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 51776613A1 for ; Wed, 17 Nov 2021 07:12:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 51776613A1 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=6XvNmVgkOEYDOqrGwaQJ1Qwvz60g+1JTdz+tBg5+/Ak=; b=ovKlLdcq8HDQVT4k4u4a6j2SAU z91mSFbt9QpFXr6xQdrA8W7MPC+V1870w3TtZJBXFGlZbTaoxAihObup8Ihq0FUX1cB6/EaiSanPF WOK/tfUPCLWA8WIfXPXV2dADDcQ31oEThz/wGTAKihBM45JuVL2unvBur57LnERQXJ8o/p89NQ4Hw S1kFO1Cl+BvOVdJCykwfs1rUCXqmfhDJH3yMXqgAG9tCWP86rN+vaIzluTDxZRfIaoJ+8Sc6Ae+oN JYUPIPJhTzaJAzLLwK81u0SMaWd/lPcLuFiUbmyje327Z603sXSoxk+/lFHkFRVL8+qVILeGI2j1W pHiSCrCQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF5s-003g5J-Gu; Wed, 17 Nov 2021 07:10:57 +0000 Received: from mail-pg1-x549.google.com ([2607:f8b0:4864:20::549]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpL-003a1j-94 for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:52 +0000 Received: by mail-pg1-x549.google.com with SMTP id s8-20020a63af48000000b002e6c10ac245so693332pgo.21 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=nCj1ezmkREDHCdpANFi/yiwdPRDQ5wh2yT3XTPIINCGjMKuBym8JqMM63uGqrYdlJw v5dBNfFPeOveJeLlFiJiEEe7+xrqXlsMOjVt1bJC9qUUPVbaDshfyqW0Ub2l9/zCJXg7 urWZ6lwuh8mPkFCDiqe+kxEqd1QooGAUYnOTHefarLr4SD41j+Qm2oJAxAgmQ+JpGM8E laWUeNtNYBIgBHjB1+1HyqkZ8/4so59v1prbc43fx7BbxQFrqryVk5RhGYtonk+Kdl8d lRTEW+/iOzWd2YL5OaTevA8piwmYoCan/Jpg7NpQrxEVS4N7AdGNQxdlITLjCxQwPnYs pAGA== X-Gm-Message-State: AOAM533qR/bnnPHW1oue5zEbGERfDGUI93a8GimxbX6k8k76u1C2JX9z ZbbqLlSNqtUIKqse+i004gX8tBvSk38= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225351_385112_3E04EF01 X-CRM114-Status: GOOD ( 15.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692852 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 0DA48C433EF for ; Wed, 17 Nov 2021 07:13:43 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C591A613A1 for ; Wed, 17 Nov 2021 07:13:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C591A613A1 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=PU38kVxFUHpnahsEEIPRdFvx2R4eVS0I9a+JGfVLPMk=; b=mP29TRM/RZmIWiUjFRc8W5/rhI SHZl//TFA5Gb7RBAsSErND4GVMG94keYvk+GJWCq+dQ2xm3Wa520BcCSovs5HCWZ5eZ2ctiReSt/V XrJhu71X60BRL86krCJsahLy1KTwxUxJAM4M17PKfO7CJDXihow6Dhkd9Rs6m7G324xh2G365XDJi S0F2ZzGcmADx/0ek4/GGMtdXRiYAYdEc0HoCdpRTQJgcP88Gs/1ejy71Vu7Yi08JjggXuN+q37AE6 9glumYHvdCbvjXNb1t1DACTxzU+9MZLQVTrGCKKKBBrszD/5J+AYPQmSu2YVPAN+4TKaHhYS2nOuQ 2pGUGOfg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF6k-003gOU-Oi; Wed, 17 Nov 2021 07:11:53 +0000 Received: from mail-pl1-x649.google.com ([2607:f8b0:4864:20::649]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpN-003a2y-AF for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:54 +0000 Received: by mail-pl1-x649.google.com with SMTP id 4-20020a170902c20400b0014381f710d5so566000pll.11 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=6E81U0cMC++pLLfFqQnK+b5muuPYYPuRwoArB7RBL6t/GotbIMomwfKq3ylnf6NjWU 1Ttn1Rc0kKs5u6Jf0hhXnW0/BfhyCUx1fjdCHn0wffGfmjrwlFrVF8qMbVlcXV2wu2ry s+Yu4RZxQFPGx2UPhIDcnHTny7TONWM/0WvMa8mD8AhVmj0Dgi6ySfEMScwKw7UuuXXh VaO4J56HezynWNWKWb2obxfueSdEoljYLBOHVIswiT9+fh4g7vgGJ0U+ogr1iBdResnH hfVlXYxxG05EPE0eUpA2u39MRFBQkYRqx8VDqy0gDpguW4lp3UNrr6V32zk8faM2pOTx 6iiQ== X-Gm-Message-State: AOAM533eA3VprXY+rRLPl9OZLFvlrC++IaPIvs/+OH9jFcyex59X2XM7 fRok2qpe6dKgCB+2Cdp7ju/4LmCwWQE= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225353_403222_0905BFB1 X-CRM114-Status: GOOD ( 10.45 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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: 12692853 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 4A55DC433EF for ; Wed, 17 Nov 2021 07:14:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0F85461A53 for ; Wed, 17 Nov 2021 07:14:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0F85461A53 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=vj6lpbYqrB3we9/rtYs1xDXSoac4hiVJOZNnWX9c0CE=; b=mDJv4W0ND8VpKZ7F67HXOWZIkL gpyjx1bCi+2cjvGxhvcIT7S4eK1ySC4pbjs8UQhmYKa6oFRdon9LzQ9bEq5TZdKD58ybpLRh/9vNU J6YtW5gFDTfyFg2UDkop0YL8+yaGqjM5HRW9ThSvG166JeVddZtFUFkG9MBEW8CfkEhOIGbJlMg6d TB3El6hYYCB325QD9E6MiPv4w5lcNnmV54C4rQvhSl3pyHEV3JCq6q2LgRX0fE/BRK0zyil8uH/+X qRTcqmXqAUOjHMNSUUHiUCcO8L6LAN7AxeIOOrIeaFcG2A4QQuOZWY1Q85HfLdAzh4aaEggZHSacA jMHlnBiw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF7S-003geC-SW; Wed, 17 Nov 2021 07:12:35 +0000 Received: from mail-pf1-x449.google.com ([2607:f8b0:4864:20::449]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpO-003a3s-NC for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:53:56 +0000 Received: by mail-pf1-x449.google.com with SMTP id y68-20020a627d47000000b004a2f6a1551cso1084757pfc.23 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=NzCD/YcmYuv+jdQaY2TnKzCRgQ8aVvaFV5x4uU/Vllmw2i20AMbm9rZA1NeMgBjlh9 zqzliR7Y8XZodR93bpZJV314UoR/4nxYRDLVOQPC1tmuyQFzDE2xFZqjIMne33ii3XRW N7BGvjiQ5NLkXDnv7hpEIUPaYJRLwAuE+W1Ax7dJxVMVk+07Z9Qhrq1y27STWufR+BN8 Gc6ow6bU7DPcWFrzOndSMENaPVa4z2e/yjtPb7raSErPtb1Luu5WjgfrMo/0KskWb3yE q3eEBra9fEJsPgy5SXfWK01k7woScGppW1PKbNwIbOwkubbFnED/ElCdG12OTirxmG4A r6Gw== X-Gm-Message-State: AOAM533vzMr9EPuaCUdxts/1f0EfuEkv3WZ6Ip6zpddrOrHPC3J7aYct fuDfWAnXDLHMkUJxUFpJtlN0G3+usis= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225354_825370_CDFB9907 X-CRM114-Status: GOOD ( 14.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add 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: 12692854 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 40C3AC433EF for ; Wed, 17 Nov 2021 07:15:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DFF9261BF8 for ; Wed, 17 Nov 2021 07:15:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org DFF9261BF8 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=py3rVl/HyYBHFsYoYz9tPPwluJ3ijbfrSi3evoxU1Bc=; b=MF/GnlhWY7lNQzXU4n2/AT3rF4 ZjfHxvy+GTvMlSaiHxCqK0CFl2rAVOyUgQ3Cbpf5mwe9ThxvjedJI0INTBLxDr8Hvjb8Fjzc3x2k3 IO7v4gQDp/ZSTcU09hnUw/dOI6MiLHLzLB7MMPwp6LQRNk2u4rlV/s4tLdP3rAaSIDiDIHAN64WSQ 1XG4lEW5K8KNk1KcFJMZKRXcA9s8tVB9LBFOjtYILLu12R2UMoHOLIkgCETiL+IAv+yTTnFwhRUJG mNVF21r2AXHTvNpphSLqtesLsdzYqdHqqnbAwQNElrDNwrQ8SfyVeXYZ+0sKuV+vtkmuw0iUghift TX6MtBLQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnF8I-003gvG-CC; Wed, 17 Nov 2021 07:13:27 +0000 Received: from mail-pl1-x649.google.com ([2607:f8b0:4864:20::649]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mnEpQ-003a4V-LY for linux-arm-kernel@lists.infradead.org; Wed, 17 Nov 2021 06:54:00 +0000 Received: by mail-pl1-x649.google.com with SMTP id p16-20020a170902e75000b0014271728fd6so554816plf.18 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=ml+Ys0bAfFj+ii0bD1A+jhMDDKfpk0as0gN9JMjyup/Dj+2rTCKQLly6hM0cHr8UvM gRZVbaS8Te0QxaDhGtCnEbqJLGYJfuhIlcFOI/VwKTEK3+cZyINv/zMUsvfxlSloJ9vb Wmf8bVXogNWnK2uBJN23WQ6eIvm1+Pph+0H1MRo3JgJYlqpwpCm76wsSgE1shQc34hVN 4oTIOppuHjTlJ3GvRxRWUdTc9XzneY3pGOyLdNtTjZzRjWm2DdyMn1WeWduX3u3wdym4 oecMQUyVZsJtPkUKnVIO2VI923Fw3DPXYDHyuFSZQAUhBOgkEupBHo8GPBv3bKLzbJ0l TdeQ== X-Gm-Message-State: AOAM5314J2kX3e43swYLBU2lY56CQQ/EM5259DiGIA5qkjsTAVF1X9nx 7l1nPzG+4Ozg0r+GBbNw93AGv8nrxp8= 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 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_225356_820630_D337FA9D X-CRM114-Status: GOOD ( 21.33 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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; +}