From patchwork Tue Jul 18 16:58:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jintack Lim X-Patchwork-Id: 108157 Delivered-To: patch@linaro.org Received: by 10.182.45.195 with SMTP id p3csp6152049obm; Tue, 18 Jul 2017 10:02:51 -0700 (PDT) X-Received: by 10.84.210.140 with SMTP id a12mr2710247pli.281.1500397371554; Tue, 18 Jul 2017 10:02:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500397371; cv=none; d=google.com; s=arc-20160816; b=LXuHUhQOCsVSLw5OzjzW047cUDfGu6iL63JblRu5FcJ4e2RTKNUOASISLLIkjoCa6u Wo6yleZDtCbP1YWWXjefOfngd8tCfA0hofrRvmVEjHncqn8jAeTqvx5CJYzwHAoze7uT rVs/s7is6rRSqcb0SpFR76vmU9LM3aeyfCfbTSxnVim+6UoNZhBXcXDayCnsxNiQcs1d vifoqGczGT9DVHU48H/efebodgg2vkLjHJWD1dU16ef/vMmQANKyc0U3saXGa1yt2LCI vcpIu0bhwvdetfZe21z5K5HWCRoceiPHX9JQy2h3oyXjOiYhtacD9apdw9NkdsiGOVvB 4MDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=RTOCeD9C0Q0Zk3vCwtWb/h9OY7AIslrucChSVac3rQY=; b=hDMUi4e1jfpmT7mZKcXCl70XqcG6UbeEuI4pIQmAuKuoHu2ZXMBLjbdpjKbMbs4dlX lICoI4HjSjtpCOsbMPJ6yHrwVvya5h5RRGcM38IKOtXCEdg19yTUzUa0KY2GuZFqFGXO cXYVJrBM9RAUu0D78K1NjapFXPyTw5wxz9RlAx8W0oZW//ESqDjHdtP287o04clXZjad /VSfYG8Vpf+uUvTQPvycWcriA+E8tNg5b5paTHZpOCDRm+S9YXtT3xrYGlZb1vAbSpoR LwrqdTuyXhfEByoi11o6txrt9SwaQa0LBYFJOcppznADQnJ8RMiZRl4d9YDUDvuVOGTU lTzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=cBu/xqGO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r7si2083799pli.606.2017.07.18.10.02.51; Tue, 18 Jul 2017 10:02:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.b=cBu/xqGO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752646AbdGRRCt (ORCPT + 25 others); Tue, 18 Jul 2017 13:02:49 -0400 Received: from mail-it0-f44.google.com ([209.85.214.44]:34101 "EHLO mail-it0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752466AbdGRRAd (ORCPT ); Tue, 18 Jul 2017 13:00:33 -0400 Received: by mail-it0-f44.google.com with SMTP id v205so2303563itf.1 for ; Tue, 18 Jul 2017 10:00:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RTOCeD9C0Q0Zk3vCwtWb/h9OY7AIslrucChSVac3rQY=; b=cBu/xqGOwuCorSPPnbKYQdY3aKQ64m8vQIajN5Jb0HUhz0TLaslBIeOw6N6vAbnV/5 UHDRf/tL8QvgI29VmC8nUoOPJljEhv7FDXgVMnUS4OC3S/hI5xCmFBfi+7dxjnh/VnFA 4s5IYeMK5MuwjLLzSWbbyd/3H7Da+mIYWlMRc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RTOCeD9C0Q0Zk3vCwtWb/h9OY7AIslrucChSVac3rQY=; b=QP+joqN0yMUW3Y37GjTFK6IJhdPEH5yCTLSmBGEK5mbAkkMG75mV/3PnK6CKRsd8aR Y/tyrX67c6neRUtjgsCviMOtezi7JuzegYx/mBwyqRpYG77AWyUf4VjB1mJMN2j4Fjg1 CFs/KrGp9JLDA+IQqVrzZGEuTpLrzYzUc3zIwIUCne42I78wZvSSn+0ZKVQ1P+B//JyT eTxwiG6H3qkGe8QnJAW1La2FaMq6QM4jq743vpUV2pnVPCYRriSGeE5Mw3uWlSNRZjRX Vic2GkJnLp8kF858fC5x9ILfIOgcD7oafBZIR3t05luh1rCFV2yvEaNrP6EQ6fnhTc1F rMSA== X-Gm-Message-State: AIVw110ApjBmQKZmKGPJBKnOtpQMIos+fnOrQsekUIxRX8qgUwVyeoJ8 2wbepF351rLXUrca X-Received: by 10.36.218.133 with SMTP id z127mr3714018itg.74.1500397232050; Tue, 18 Jul 2017 10:00:32 -0700 (PDT) Received: from node.jintackl-qv26972.kvmarm-pg0.wisc.cloudlab.us (c220g1-030822.wisc.cloudlab.us. [128.104.222.82]) by smtp.gmail.com with ESMTPSA id j96sm1413075ioo.49.2017.07.18.10.00.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 18 Jul 2017 10:00:31 -0700 (PDT) From: Jintack Lim To: kvmarm@lists.cs.columbia.edu, christoffer.dall@linaro.org, marc.zyngier@arm.com Cc: corbet@lwn.net, pbonzini@redhat.com, rkrcmar@redhat.com, linux@armlinux.org.uk, catalin.marinas@arm.com, will.deacon@arm.com, akpm@linux-foundation.org, mchehab@kernel.org, cov@codeaurora.org, daniel.lezcano@linaro.org, david.daney@cavium.com, mark.rutland@arm.com, suzuki.poulose@arm.com, stefan@hello-penguin.com, andy.gross@linaro.org, wcohen@redhat.com, ard.biesheuvel@linaro.org, shankerd@codeaurora.org, vladimir.murzin@arm.com, james.morse@arm.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jintack Lim Subject: [RFC PATCH v2 32/38] KVM: arm64: Trap and emulate CPTR_EL2 accesses via CPACR_EL1 from the virtual EL2 with VHE Date: Tue, 18 Jul 2017 11:58:58 -0500 Message-Id: <1500397144-16232-33-git-send-email-jintack.lim@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1500397144-16232-1-git-send-email-jintack.lim@linaro.org> References: <1500397144-16232-1-git-send-email-jintack.lim@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org While the EL1 virtual memory control registers can be accessed in the virtual EL2 with VHE without trap to manuplate the virtual EL2 states, we can't do that for CPTR_EL2 for an unfortunate reason. This is because the top bit of CPTR_EL2, which is TCPAC, will be ignored if it is accessed via CPACR_EL1 in the virtual EL2 without trap since the top bot of cpacr_el1 is RES0. Therefore we need to trap CPACR_EL1 accesses from the virtual EL2 to emulate this bit correctly. Set CPTR_EL2.TCPAC bit to trap CPACR_EL1 accesses and handle them in the existing handler considering that they could be meant to access CPTR_EL2 instead in the virtual EL2 with VHE. Note that CPTR_EL2 format depends on HCR_EL2.E2H bit. We always keep it in v8.0 format for the convenience. Otherwise, we need to check E2H bit and use different bit masks in the entry.S, and we also check E2H bit in all places we access virtual CPTR_EL2. The downside of using v8.0 format is to convert the format when copying states between CPTR_EL2 and CPACR_EL1 to support the virtual EL2 with VHE. The decision is subject to change depending on the future discussion. Signed-off-by: Jintack Lim --- arch/arm64/include/asm/kvm_emulate.h | 2 ++ arch/arm64/kvm/context.c | 29 ++++++++++++++++++++++++++--- arch/arm64/kvm/hyp/switch.c | 2 ++ arch/arm64/kvm/sys_regs.c | 18 +++++++++++++++++- 4 files changed, 47 insertions(+), 4 deletions(-) -- 1.9.1 diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 68aafbd..4776bfc 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -59,6 +59,8 @@ enum exception_type { void kvm_arm_setup_shadow_state(struct kvm_vcpu *vcpu); void kvm_arm_restore_shadow_state(struct kvm_vcpu *vcpu); void kvm_arm_init_cpu_context(kvm_cpu_context_t *cpu_ctxt); +u64 cptr_to_cpacr(u64 cptr_el2); +u64 cpacr_to_cptr(u64 cpacr_el1); static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) { diff --git a/arch/arm64/kvm/context.c b/arch/arm64/kvm/context.c index 9947bc8..a7811e1 100644 --- a/arch/arm64/kvm/context.c +++ b/arch/arm64/kvm/context.c @@ -66,7 +66,7 @@ static inline u64 tcr_el2_ips_to_tcr_el1_ps(u64 tcr_el2) << TCR_IPS_SHIFT; } -static inline u64 cptr_to_cpacr(u64 cptr_el2) +u64 cptr_to_cpacr(u64 cptr_el2) { u64 cpacr_el1 = 0; @@ -78,6 +78,21 @@ static inline u64 cptr_to_cpacr(u64 cptr_el2) return cpacr_el1; } +u64 cpacr_to_cptr(u64 cpacr_el1) +{ + u64 cptr_el2; + + cptr_el2 = CPTR_EL2_DEFAULT; + if (!(cpacr_el1 & CPACR_EL1_FPEN)) + cptr_el2 |= CPTR_EL2_TFP; + if (cpacr_el1 & CPACR_EL1_TTA) + cptr_el2 |= CPTR_EL2_TTA; + if (cpacr_el1 & CPTR_EL2_TCPAC) + cptr_el2 |= CPTR_EL2_TCPAC; + + return cptr_el2; +} + static void sync_shadow_el1_sysregs(struct kvm_vcpu *vcpu) { u64 *s_sys_regs = vcpu->arch.ctxt.shadow_sys_regs; @@ -93,8 +108,12 @@ static void sync_shadow_el1_sysregs(struct kvm_vcpu *vcpu) for (i = 0; i < ARRAY_SIZE(vhe_map); i++) { const struct el1_el2_map *map = &vhe_map[i]; + u64 *el2_reg = &vcpu_sys_reg(vcpu, map->el2); - vcpu_sys_reg(vcpu, map->el2) = s_sys_regs[map->el1]; + /* We do trap-and-emulate CPACR_EL1 accesses. So, don't sync */ + if (map->el2 == CPTR_EL2) + continue; + *el2_reg = s_sys_regs[map->el1]; } } @@ -138,8 +157,12 @@ static void flush_shadow_el1_sysregs_vhe(struct kvm_vcpu *vcpu) */ for (i = 0; i < ARRAY_SIZE(vhe_map); i++) { const struct el1_el2_map *map = &vhe_map[i]; + u64 *el1_reg = &s_sys_regs[map->el1]; - s_sys_regs[map->el1] = vcpu_sys_reg(vcpu, map->el2); + if (map->el2 == CPTR_EL2) + *el1_reg = cptr_to_cpacr(vcpu_sys_reg(vcpu, map->el2)); + else + *el1_reg = vcpu_sys_reg(vcpu, map->el2); } } diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index fffd0c7..50c90f2 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -50,6 +50,8 @@ static void __hyp_text __activate_traps_vhe(struct kvm_vcpu *vcpu) val = read_sysreg(cpacr_el1); val |= CPACR_EL1_TTA; val &= ~CPACR_EL1_FPEN; + if (is_hyp_ctxt(vcpu)) + val |= CPTR_EL2_TCPAC; write_sysreg(val, cpacr_el1); write_sysreg(__kvm_hyp_vector, vbar_el1); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2aa922c..79980be 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -972,7 +972,23 @@ static bool access_cpacr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { - access_rw(p, &vcpu_sys_reg(vcpu, r->reg)); + u64 reg = sys_reg(p->Op0, p->Op1, p->CRn, p->CRm, p->Op2); + + /* + * When the virtual HCR_EL2.E2H == 1, an access to CPACR_EL1 + * in the virtual EL2 is to access CPTR_EL2. + */ + if (vcpu_el2_e2h_is_set(vcpu) && (reg == SYS_CPACR_EL1)) { + u64 *sysreg = &vcpu_sys_reg(vcpu, CPTR_EL2); + + /* We keep the value in ARMv8.0 CPTR_EL2 format. */ + if (!p->is_write) + p->regval = cptr_to_cpacr(*sysreg); + else + *sysreg = cpacr_to_cptr(p->regval); + } else /* CPACR_EL1 access with E2H == 0 or CPACR_EL12 access */ + access_rw(p, &vcpu_sys_reg(vcpu, r->reg)); + return true; }