From mboxrd@z Thu Jan 1 00:00:00 1970 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55B08C433FE for ; Fri, 11 Mar 2022 04:49:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346479AbiCKEuD (ORCPT ); Thu, 10 Mar 2022 23:50:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346472AbiCKEtr (ORCPT ); Thu, 10 Mar 2022 23:49:47 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4E5E1AAFC9 for ; Thu, 10 Mar 2022 20:48:35 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id f21-20020a633815000000b0038105768c61so933130pga.21 for ; Thu, 10 Mar 2022 20:48: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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=kxXwwKf76XJVgOlrOSM6DlfVqX/r3m6LuNum/WvCEBqF/qgCmnns+PpZ8/o1y+g5G/ Kbg7RIzj8TfV2IM1veJH+op06M5dxHq0f+2obySLhGc7P1v4e3CM7YEyyaDkYRCNSaGi 3+3SoFIcPnUZEePvQcDX8xI6VQRkzZFCBP3HBnxusnXLd/G+F1Aw6hmn5kA2WJ4axU2j HcAulUblFsyadSuQYww+KZFE94Mr4Qs60zf37KZMZnXwYP53R4ZBJAUBMEBRSw6xjZgy GqbLJiTK/yAFQuzzk2KLg4iIn6jvN1ffGHq9Qs4rH284leJGJ1SfOb68WDW2kpB2PxTJ A5mg== 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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=Vcc6N1yeMcTEGMYeBESHzgEKHWnk71rD9P+jjwyHxdGRv5Zc+KDqgNEuUe0yY/0+HV n3kO/ntr8lCWKqOr1CuyCMPQL3uotNBZB3RLW6BSQskCa340fgtEsmOMgnloHnrPR31g BozaGLs4r4zzHg86LdKvjWIT9/2Ta751mMXTEX2tN9W7eBnbeQrdaRbgj7QWfthlIpCb wJDPBjqsswOvOcmQkyDucPQi5UK80PQCWlNp1FVKjI+NEeivEJEVM0OfTzMv+KyiW5Le cc8DBppFK+o9JX2eO09wedANnTOXtGZ3S3PdVgTgBQAYPgdlUfvBUylV5izBPgVDcvta Obww== X-Gm-Message-State: AOAM531/Bw03bwhIF5UXuHpqkWkXNWvTZx+Zhj9eaFWmYU8ZkwC6XVyN bU5tFPMeFdJ3/8PM6Uj+8atAQ9YdPLI= X-Google-Smtp-Source: ABdhPJxPyEOxxqDIYNwgjAeeZrHfimY7GNc7Ltn9lvGWCQ9Lw0fZekJQj1mHokO+KyKBt5e/7m5MR2Yd05I= 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:cf12:b0:14f:e0c2:1515 with SMTP id i18-20020a170902cf1200b0014fe0c21515mr8814824plg.4.1646974115128; Thu, 10 Mar 2022 20:48:35 -0800 (PST) Date: Thu, 10 Mar 2022 20:47:48 -0800 In-Reply-To: <20220311044811.1980336-1-reijiw@google.com> Message-Id: <20220311044811.1980336-3-reijiw@google.com> Mime-Version: 1.0 References: <20220311044811.1980336-1-reijiw@google.com> X-Mailer: git-send-email 2.35.1.723.g4982287a31-goog Subject: [PATCH v6 02/25] KVM: arm64: Save ID registers' sanitized value per 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 , Fuad Tabba , Peng Liang , Peter Shier , Ricardo Koller , Oliver Upton , Jing Zhang , Raghavendra Rao Anata , Reiji Watanabe Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce id_regs[] in kvm_arch as a storage of guest's ID registers, and save ID registers' sanitized value in the array at KVM_CREATE_VM. Use the saved ones when ID registers are read by the guest or userspace (via KVM_GET_ONE_REG). Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 12 ++++++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/sys_regs.c | 65 ++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2869259e10c0..c041e5afe3d2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -101,6 +101,13 @@ struct kvm_s2_mmu { struct kvm_arch_memory_slot { }; +/* + * (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)) + struct kvm_arch { struct kvm_s2_mmu mmu; @@ -137,6 +144,9 @@ struct kvm_arch { /* Memory Tagging Extension enabled for the guest */ bool mte_enabled; bool ran_once; + + /* ID registers for the guest. */ + u64 id_regs[KVM_ARM_ID_REG_MAX_NUM]; }; struct kvm_vcpu_fault_info { @@ -736,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); +void set_default_id_regs(struct kvm *kvm); + /* 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 4783dbf66df2..91110d996ed6 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus = kvm_arm_default_max_vcpus(); set_default_spectre(kvm); + set_default_id_regs(kvm); return ret; out_free_stage2_pgd: diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 4dc2fba316ff..d2b3ad32ab5a 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_with_encoding(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_with_encoding(vcpu, SYS_ID_AA64MMFR1_EL1); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { @@ -1059,17 +1061,16 @@ 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 bool is_id_reg(u32 id) { - u32 id = reg_to_encoding(r); - u64 val; - - if (raz) - return 0; + return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 && + sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 0 && + sys_reg_CRm(id) < 8); +} - val = read_sanitised_ftr_reg(id); +static u64 read_id_reg_with_encoding(const struct kvm_vcpu *vcpu, u32 id) +{ + u64 val = vcpu->kvm->arch.id_regs[IDREG_IDX(id)]; switch (id) { case SYS_ID_AA64PFR0_EL1: @@ -1119,6 +1120,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_with_encoding(vcpu, id); +} + static unsigned int id_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -1223,9 +1232,8 @@ 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. + * For now, these registers are immutable for userspace, so for set_id_reg() + * 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, @@ -1837,8 +1845,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_with_encoding(vcpu, SYS_ID_AA64DFR0_EL1); + u64 pfr = read_id_reg_with_encoding(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) | @@ -2850,3 +2858,30 @@ void kvm_sys_reg_table_init(void) /* Clear all higher bits. */ cache_levels &= (1 << (i*3))-1; } + +/* + * Set the guest's ID registers that are defined in sys_reg_descs[] + * with ID_SANITISED() to the host's sanitized value. + */ +void set_default_id_regs(struct kvm *kvm) +{ + int i; + u32 id; + const struct sys_reg_desc *rd; + u64 val; + + for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) { + rd = &sys_reg_descs[i]; + if (rd->access != access_id_reg) + /* Not ID register, or hidden/reserved ID register */ + continue; + + id = reg_to_encoding(rd); + if (WARN_ON_ONCE(!is_id_reg(id))) + /* Shouldn't happen */ + continue; + + val = read_sanitised_ftr_reg(id); + kvm->arch.id_regs[IDREG_IDX(id)] = val; + } +} -- 2.35.1.723.g4982287a31-goog From mboxrd@z Thu Jan 1 00:00:00 1970 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 mm01.cs.columbia.edu (mm01.cs.columbia.edu [128.59.11.253]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20909C433EF for ; Fri, 11 Mar 2022 04:48:41 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mm01.cs.columbia.edu (Postfix) with ESMTP id BAB0949ED9; Thu, 10 Mar 2022 23:48:40 -0500 (EST) X-Virus-Scanned: at lists.cs.columbia.edu Authentication-Results: mm01.cs.columbia.edu (amavisd-new); dkim=softfail (fail, message has been altered) header.i=@google.com Received: from mm01.cs.columbia.edu ([127.0.0.1]) by localhost (mm01.cs.columbia.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IGDt+GZwmeo0; Thu, 10 Mar 2022 23:48:39 -0500 (EST) Received: from mm01.cs.columbia.edu (localhost [127.0.0.1]) by mm01.cs.columbia.edu (Postfix) with ESMTP id CA61749EBB; Thu, 10 Mar 2022 23:48:38 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mm01.cs.columbia.edu (Postfix) with ESMTP id 72F9F40CF5 for ; Thu, 10 Mar 2022 23:48:37 -0500 (EST) X-Virus-Scanned: at lists.cs.columbia.edu Received: from mm01.cs.columbia.edu ([127.0.0.1]) by localhost (mm01.cs.columbia.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KrlYMXp5BTkH for ; Thu, 10 Mar 2022 23:48:36 -0500 (EST) Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) by mm01.cs.columbia.edu (Postfix) with ESMTPS id 1CDCE40C95 for ; Thu, 10 Mar 2022 23:48:36 -0500 (EST) Received: by mail-pg1-f201.google.com with SMTP id b18-20020a63d812000000b0037e1aa59c0bso4132847pgh.12 for ; Thu, 10 Mar 2022 20:48:36 -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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=kxXwwKf76XJVgOlrOSM6DlfVqX/r3m6LuNum/WvCEBqF/qgCmnns+PpZ8/o1y+g5G/ Kbg7RIzj8TfV2IM1veJH+op06M5dxHq0f+2obySLhGc7P1v4e3CM7YEyyaDkYRCNSaGi 3+3SoFIcPnUZEePvQcDX8xI6VQRkzZFCBP3HBnxusnXLd/G+F1Aw6hmn5kA2WJ4axU2j HcAulUblFsyadSuQYww+KZFE94Mr4Qs60zf37KZMZnXwYP53R4ZBJAUBMEBRSw6xjZgy GqbLJiTK/yAFQuzzk2KLg4iIn6jvN1ffGHq9Qs4rH284leJGJ1SfOb68WDW2kpB2PxTJ A5mg== 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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=8LZ2m0drvD6bELiFNfiCi+J0QyLwsJM9YGPF4MgI4nOfMJdO54DLqVHgdXiwmgjlY8 y2PnSDJE/Tc1o8E1Owx+ZtgasKtZyAbdFNm+q+Sycn3w871OoteiEmN9RSJedPbgLj+S MgB1KTrmFbOEy3jSMKWBupJ68uoUKykm6fuNpDFVtizfJfUjvMZl/kxWILzEilnMt1rM QFj21eYaALGbXdH3iNS/MSy8aQv4xv/UQU1q1SWPPj1UMCNU+09036QN4c25xC7SVK1u L2YV3nnAj6de4ebtJ7FWZtLsxZMwRIeC5shHmj1b36R7hm4wGGiDuBsRMDzxsLgq8cPO p88Q== X-Gm-Message-State: AOAM533oLs+LHbIBoIcUHAiiqogbCLrAc7IMRGVItwNje0u7ySd7CYtQ auEmTvntfxecw8vPcseAtDgX9jyVEZc= X-Google-Smtp-Source: ABdhPJxPyEOxxqDIYNwgjAeeZrHfimY7GNc7Ltn9lvGWCQ9Lw0fZekJQj1mHokO+KyKBt5e/7m5MR2Yd05I= 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:cf12:b0:14f:e0c2:1515 with SMTP id i18-20020a170902cf1200b0014fe0c21515mr8814824plg.4.1646974115128; Thu, 10 Mar 2022 20:48:35 -0800 (PST) Date: Thu, 10 Mar 2022 20:47:48 -0800 In-Reply-To: <20220311044811.1980336-1-reijiw@google.com> Message-Id: <20220311044811.1980336-3-reijiw@google.com> Mime-Version: 1.0 References: <20220311044811.1980336-1-reijiw@google.com> X-Mailer: git-send-email 2.35.1.723.g4982287a31-goog Subject: [PATCH v6 02/25] KVM: arm64: Save ID registers' sanitized value per guest From: Reiji Watanabe To: Marc Zyngier , kvmarm@lists.cs.columbia.edu Cc: kvm@vger.kernel.org, Will Deacon , Peter Shier , Paolo Bonzini , linux-arm-kernel@lists.infradead.org X-BeenThere: kvmarm@lists.cs.columbia.edu X-Mailman-Version: 2.1.14 Precedence: list List-Id: Where KVM/ARM decisions are made List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: kvmarm-bounces@lists.cs.columbia.edu Sender: kvmarm-bounces@lists.cs.columbia.edu Introduce id_regs[] in kvm_arch as a storage of guest's ID registers, and save ID registers' sanitized value in the array at KVM_CREATE_VM. Use the saved ones when ID registers are read by the guest or userspace (via KVM_GET_ONE_REG). Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 12 ++++++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/sys_regs.c | 65 ++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2869259e10c0..c041e5afe3d2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -101,6 +101,13 @@ struct kvm_s2_mmu { struct kvm_arch_memory_slot { }; +/* + * (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)) + struct kvm_arch { struct kvm_s2_mmu mmu; @@ -137,6 +144,9 @@ struct kvm_arch { /* Memory Tagging Extension enabled for the guest */ bool mte_enabled; bool ran_once; + + /* ID registers for the guest. */ + u64 id_regs[KVM_ARM_ID_REG_MAX_NUM]; }; struct kvm_vcpu_fault_info { @@ -736,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); +void set_default_id_regs(struct kvm *kvm); + /* 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 4783dbf66df2..91110d996ed6 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus = kvm_arm_default_max_vcpus(); set_default_spectre(kvm); + set_default_id_regs(kvm); return ret; out_free_stage2_pgd: diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 4dc2fba316ff..d2b3ad32ab5a 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_with_encoding(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_with_encoding(vcpu, SYS_ID_AA64MMFR1_EL1); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { @@ -1059,17 +1061,16 @@ 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 bool is_id_reg(u32 id) { - u32 id = reg_to_encoding(r); - u64 val; - - if (raz) - return 0; + return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 && + sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 0 && + sys_reg_CRm(id) < 8); +} - val = read_sanitised_ftr_reg(id); +static u64 read_id_reg_with_encoding(const struct kvm_vcpu *vcpu, u32 id) +{ + u64 val = vcpu->kvm->arch.id_regs[IDREG_IDX(id)]; switch (id) { case SYS_ID_AA64PFR0_EL1: @@ -1119,6 +1120,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_with_encoding(vcpu, id); +} + static unsigned int id_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -1223,9 +1232,8 @@ 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. + * For now, these registers are immutable for userspace, so for set_id_reg() + * 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, @@ -1837,8 +1845,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_with_encoding(vcpu, SYS_ID_AA64DFR0_EL1); + u64 pfr = read_id_reg_with_encoding(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) | @@ -2850,3 +2858,30 @@ void kvm_sys_reg_table_init(void) /* Clear all higher bits. */ cache_levels &= (1 << (i*3))-1; } + +/* + * Set the guest's ID registers that are defined in sys_reg_descs[] + * with ID_SANITISED() to the host's sanitized value. + */ +void set_default_id_regs(struct kvm *kvm) +{ + int i; + u32 id; + const struct sys_reg_desc *rd; + u64 val; + + for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) { + rd = &sys_reg_descs[i]; + if (rd->access != access_id_reg) + /* Not ID register, or hidden/reserved ID register */ + continue; + + id = reg_to_encoding(rd); + if (WARN_ON_ONCE(!is_id_reg(id))) + /* Shouldn't happen */ + continue; + + val = read_sanitised_ftr_reg(id); + kvm->arch.id_regs[IDREG_IDX(id)] = val; + } +} -- 2.35.1.723.g4982287a31-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm From mboxrd@z Thu Jan 1 00:00:00 1970 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 00E8EC433EF for ; Fri, 11 Mar 2022 04:50:50 +0000 (UTC) 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=P6lt3Ql1pEfz68+wQ95uwbIi7iskD02ZLP3jA9Ql96I=; b=w1UHP7vPDWwRfUy89omsj4qmYk az9YHYaiJisWDSu3KKTsRaHyj5nTwP6NWzDP1QhQQAtnnBJqBy4fOxzs1GDqv8K4Y8pBui14MMgPC Q7cNMU5Jpr07ZViegGPpa9IF/Qsx+H6Oj69FPxCe+3pHdMzDjaiGF1LgqDkDcEuga+C+ihJ+9wOIp qwQP79gw2VpWQMNnIGPDWX+LPOdihhdVrXmmdfu7Y2n9q2Uam/LAUJa7BN06BgpNzG3sAdx99IG+v G74so+UhX1o74gV3HuhUnIbYR9A/8HSU4UNgyYvPdl1TPx4tXttheY2jND3Xk/buiKCV9Zby1wgRm SRm9I/GQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nSXCm-00EzbA-Tt; Fri, 11 Mar 2022 04:48:45 +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 1nSXCg-00EzW6-Li for linux-arm-kernel@lists.infradead.org; Fri, 11 Mar 2022 04:48:40 +0000 Received: by mail-pj1-x104a.google.com with SMTP id w3-20020a17090ac98300b001b8b914e91aso4542352pjt.0 for ; Thu, 10 Mar 2022 20:48: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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=kxXwwKf76XJVgOlrOSM6DlfVqX/r3m6LuNum/WvCEBqF/qgCmnns+PpZ8/o1y+g5G/ Kbg7RIzj8TfV2IM1veJH+op06M5dxHq0f+2obySLhGc7P1v4e3CM7YEyyaDkYRCNSaGi 3+3SoFIcPnUZEePvQcDX8xI6VQRkzZFCBP3HBnxusnXLd/G+F1Aw6hmn5kA2WJ4axU2j HcAulUblFsyadSuQYww+KZFE94Mr4Qs60zf37KZMZnXwYP53R4ZBJAUBMEBRSw6xjZgy GqbLJiTK/yAFQuzzk2KLg4iIn6jvN1ffGHq9Qs4rH284leJGJ1SfOb68WDW2kpB2PxTJ A5mg== 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=qTyrhuTFJ7wTiM9tvbSBgyvkTis1ZeMrxQeZx92tj2A=; b=iFIPEi9BMkc0ILuD0Nv1M4nCClWgMDa6oDpDwpRERqyl/AgxxUuZsGYEG1zwmB37xj 8gxijeK19vRbLJ5xBPYoH7GZb8hvGXP3TBU6G8x0+IHVRZbQTw7c4k0Pt0HBnJitpBWc pcB+nMVOE9Ies4YC6XBbJX4QRriqlGlSUSL53ohXwT2WBF5d33zVWcN+dPTDDxmMKBhP TLmmZnpF9EIV8jhr78R44J/4m4k+Il4a+9IFIr+MO2jNDDJD83eW7JAlZVHCTFTkfhhR iwzWEPYa3npmP7Od/HU7glmRm8L3TULscYD3Ju34nu5aUywho+hWVha+hPbZPjoEHL8v ERZg== X-Gm-Message-State: AOAM532uxbVj67mdcNkrix9fAEj2gReT+wMDlSz2takGxD6tEkC4NIYC gnS2Bpfgl5MiCAynMdDLbUqoTBvifFw= X-Google-Smtp-Source: ABdhPJxPyEOxxqDIYNwgjAeeZrHfimY7GNc7Ltn9lvGWCQ9Lw0fZekJQj1mHokO+KyKBt5e/7m5MR2Yd05I= 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:cf12:b0:14f:e0c2:1515 with SMTP id i18-20020a170902cf1200b0014fe0c21515mr8814824plg.4.1646974115128; Thu, 10 Mar 2022 20:48:35 -0800 (PST) Date: Thu, 10 Mar 2022 20:47:48 -0800 In-Reply-To: <20220311044811.1980336-1-reijiw@google.com> Message-Id: <20220311044811.1980336-3-reijiw@google.com> Mime-Version: 1.0 References: <20220311044811.1980336-1-reijiw@google.com> X-Mailer: git-send-email 2.35.1.723.g4982287a31-goog Subject: [PATCH v6 02/25] KVM: arm64: Save ID registers' sanitized value per 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 , Fuad Tabba , 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-20220310_204838_752415_5AC9B84F X-CRM114-Status: GOOD ( 21.88 ) 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: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Introduce id_regs[] in kvm_arch as a storage of guest's ID registers, and save ID registers' sanitized value in the array at KVM_CREATE_VM. Use the saved ones when ID registers are read by the guest or userspace (via KVM_GET_ONE_REG). Signed-off-by: Reiji Watanabe --- arch/arm64/include/asm/kvm_host.h | 12 ++++++ arch/arm64/kvm/arm.c | 1 + arch/arm64/kvm/sys_regs.c | 65 ++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2869259e10c0..c041e5afe3d2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -101,6 +101,13 @@ struct kvm_s2_mmu { struct kvm_arch_memory_slot { }; +/* + * (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)) + struct kvm_arch { struct kvm_s2_mmu mmu; @@ -137,6 +144,9 @@ struct kvm_arch { /* Memory Tagging Extension enabled for the guest */ bool mte_enabled; bool ran_once; + + /* ID registers for the guest. */ + u64 id_regs[KVM_ARM_ID_REG_MAX_NUM]; }; struct kvm_vcpu_fault_info { @@ -736,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); +void set_default_id_regs(struct kvm *kvm); + /* 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 4783dbf66df2..91110d996ed6 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.max_vcpus = kvm_arm_default_max_vcpus(); set_default_spectre(kvm); + set_default_id_regs(kvm); return ret; out_free_stage2_pgd: diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 4dc2fba316ff..d2b3ad32ab5a 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_with_encoding(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_with_encoding(vcpu, SYS_ID_AA64MMFR1_EL1); u32 sr = reg_to_encoding(r); if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) { @@ -1059,17 +1061,16 @@ 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 bool is_id_reg(u32 id) { - u32 id = reg_to_encoding(r); - u64 val; - - if (raz) - return 0; + return (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 && + sys_reg_CRn(id) == 0 && sys_reg_CRm(id) >= 0 && + sys_reg_CRm(id) < 8); +} - val = read_sanitised_ftr_reg(id); +static u64 read_id_reg_with_encoding(const struct kvm_vcpu *vcpu, u32 id) +{ + u64 val = vcpu->kvm->arch.id_regs[IDREG_IDX(id)]; switch (id) { case SYS_ID_AA64PFR0_EL1: @@ -1119,6 +1120,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_with_encoding(vcpu, id); +} + static unsigned int id_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -1223,9 +1232,8 @@ 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. + * For now, these registers are immutable for userspace, so for set_id_reg() + * 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, @@ -1837,8 +1845,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_with_encoding(vcpu, SYS_ID_AA64DFR0_EL1); + u64 pfr = read_id_reg_with_encoding(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) | @@ -2850,3 +2858,30 @@ void kvm_sys_reg_table_init(void) /* Clear all higher bits. */ cache_levels &= (1 << (i*3))-1; } + +/* + * Set the guest's ID registers that are defined in sys_reg_descs[] + * with ID_SANITISED() to the host's sanitized value. + */ +void set_default_id_regs(struct kvm *kvm) +{ + int i; + u32 id; + const struct sys_reg_desc *rd; + u64 val; + + for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) { + rd = &sys_reg_descs[i]; + if (rd->access != access_id_reg) + /* Not ID register, or hidden/reserved ID register */ + continue; + + id = reg_to_encoding(rd); + if (WARN_ON_ONCE(!is_id_reg(id))) + /* Shouldn't happen */ + continue; + + val = read_sanitised_ftr_reg(id); + kvm->arch.id_regs[IDREG_IDX(id)] = val; + } +} -- 2.35.1.723.g4982287a31-goog _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel