From patchwork Thu Dec 1 11:38:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jintack Lim X-Patchwork-Id: 9455867 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9BC1660515 for ; Thu, 1 Dec 2016 11:39:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 910E028249 for ; Thu, 1 Dec 2016 11:39:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 845D7284C6; Thu, 1 Dec 2016 11:39:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B583028249 for ; Thu, 1 Dec 2016 11:39:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754405AbcLALjl (ORCPT ); Thu, 1 Dec 2016 06:39:41 -0500 Received: from outprodmail02.cc.columbia.edu ([128.59.72.51]:39037 "EHLO outprodmail02.cc.columbia.edu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750906AbcLALjk (ORCPT ); Thu, 1 Dec 2016 06:39:40 -0500 Received: from hazelnut (hazelnut.cc.columbia.edu [128.59.213.250]) by outprodmail02.cc.columbia.edu (8.14.4/8.14.4) with ESMTP id uB1Bc5Hh039216 for ; Thu, 1 Dec 2016 06:39:39 -0500 Received: from hazelnut (localhost.localdomain [127.0.0.1]) by hazelnut (Postfix) with ESMTP id BFB3B6D for ; Thu, 1 Dec 2016 06:39:39 -0500 (EST) Received: from sendprodmail04.cc.columbia.edu (sendprodmail04.cc.columbia.edu [128.59.72.16]) by hazelnut (Postfix) with ESMTP id 7F8B37E for ; Thu, 1 Dec 2016 06:39:39 -0500 (EST) Received: from mail-qt0-f199.google.com (mail-qt0-f199.google.com [209.85.216.199]) by sendprodmail04.cc.columbia.edu (8.14.4/8.14.4) with ESMTP id uB1BddEr000511 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NOT) for ; Thu, 1 Dec 2016 06:39:39 -0500 Received: by mail-qt0-f199.google.com with SMTP id d45so149474394qta.2 for ; Thu, 01 Dec 2016 03:39:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=JPoI62+h+NavplAOGUEhxZvABgEgkPyo1D4fcSJzt24=; b=ZWiNxVv67smFj8MG3YCAvbd6n4h17GdLsCC5AnxvN1o6r/tLP2GrwqsTLq6OJQuuTc vcNmsRRWRgqCodAdyyrnrSL6eBMladrgROv+sGxUjetbQjibC4YNkiu3+l0z8XBx6I8/ 6/e9BQCgPTDckLQE1oro/aVvvBI+KRMfs2fI10Ue45I2QISb75aOaRWXJiS2BG/P9cnp A8ZR1Ypl15aC/YFss0zzygWOb7D/hcMI0+pEJe92vLtr6JknXx4GrKCVfXXbve/ZpKke qEs6MjBUyH4aRXakcM97JJconXJ/FPJd8qrwN5ndza922C40U/k0DinL9Q22DV8RmbKY 4FUg== X-Gm-Message-State: AKaTC03JyjUh6LowGztWCItyicBl9V8KvDy6yhfTusthCSLQ2j3GCc501M62h470Xkavc72eKU6BLSMfjDlEyb12TK5g9doaJVJjEcNhomZ5mNVEhyqEgwLf05E8D0FzYHSEYvw0OmZ3oIQ= X-Received: by 10.55.91.193 with SMTP id p184mr32291322qkb.301.1480592379043; Thu, 01 Dec 2016 03:39:39 -0800 (PST) X-Received: by 10.55.91.193 with SMTP id p184mr32291307qkb.301.1480592378763; Thu, 01 Dec 2016 03:39:38 -0800 (PST) Received: from jintack.cs.columbia.edu ([2001:18d8:ffff:16:21a:4aff:feaa:f900]) by smtp.gmail.com with ESMTPSA id 1sm35742576qtb.49.2016.12.01.03.39.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 01 Dec 2016 03:39:38 -0800 (PST) From: Jintack Lim To: kvmarm@lists.cs.columbia.edu Cc: marc.zyngier@arm.com, christoffer.dall@linaro.org, pbonzini@redhat.com, rkrcmar@redhat.com, linux@armlinux.org.uk, andre.przywara@arm.com, kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jintack Lim Subject: [PATCH v2] KVM: arm/arm64: Access CNTHCTL_EL2 bit fields correctly Date: Thu, 1 Dec 2016 06:38:30 -0500 Message-Id: <1480592310-26079-1-git-send-email-jintack@cs.columbia.edu> X-Mailer: git-send-email 1.9.1 X-No-Spam-Score: Local X-Scanned-By: MIMEDefang 2.78 on 128.59.72.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current KVM world switch code is unintentionally setting wrong bits to CNTHCTL_EL2 when E2H == 1, which may allow guest OS to access physical timer. Bit positions of CNTHCTL_EL2 are changing depending on HCR_EL2.E2H bit. EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is not set, but they are 11th and 10th bits respectively when E2H is set. In fact, on VHE we only need to set those bits once, not for every world switch. This is because the host kernel runs in EL2 with HCR_EL2.TGE == 1, which makes those bits have no effect for the host kernel execution. So we just set those bits once for guests, and that's it. Signed-off-by: Jintack Lim --- v2: Skip configuring cnthctl_el2 in world switch path on VHE system. This patch is based on linux-next. --- arch/arm/kvm/arm.c | 1 + include/kvm/arm_arch_timer.h | 1 + virt/kvm/arm/arch_timer.c | 23 ++++++++++++++++++++++ virt/kvm/arm/hyp/timer-sr.c | 45 ++++++++++++++++++++++++++++++++------------ 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 8f92efa..38c0645 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -1286,6 +1286,7 @@ static void teardown_hyp_mode(void) static int init_vhe_mode(void) { + on_each_cpu(kvm_timer_init_vhe, NULL, 1); kvm_info("VHE mode initialized successfully\n"); return 0; } diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index dda39d8..5853399 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h @@ -76,4 +76,5 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); +void kvm_timer_init_vhe(void *dummy); #endif diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 17b8fa5..7a0d85d7 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -507,3 +508,25 @@ void kvm_timer_init(struct kvm *kvm) { kvm->arch.timer.cntvoff = kvm_phys_timer_read(); } + +/* + * On VHE system, we only need to configure trap on physical timer and counter + * accesses in EL0 and EL1 once, not for every world switch. + * The host kernel runs at EL2 with HCR_EL2.TGE == 1, + * and this makes those bits have no effect for the host kernel execution. + */ +void kvm_timer_init_vhe(void *dummy) +{ + /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ + u32 cnthctl_shift = 10; + u64 val; + + /* + * Disallow physical timer access for the guest. + * Physical counter access is allowed. + */ + val = read_sysreg(cnthctl_el2); + val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift); + val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); + write_sysreg(val, cnthctl_el2); +} diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c index 798866a..f7fc957 100644 --- a/virt/kvm/arm/hyp/timer-sr.c +++ b/virt/kvm/arm/hyp/timer-sr.c @@ -21,6 +21,18 @@ #include +#ifdef CONFIG_ARM64 +static inline bool has_vhe(void) +{ + if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) + return true; + + return false; +} +#else +#define has_vhe() false +#endif + /* vcpu is already in the HYP VA space */ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) { @@ -35,10 +47,16 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) /* Disable the virtual timer */ write_sysreg_el0(0, cntv_ctl); - /* Allow physical timer/counter access for the host */ - val = read_sysreg(cnthctl_el2); - val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; - write_sysreg(val, cnthctl_el2); + /* + * We don't need to do this for VHE since the host kernel runs in EL2 + * with HCR_EL2.TGE ==1, which makes those bits have no impact. + */ + if (!has_vhe()) { + /* Allow physical timer/counter access for the host */ + val = read_sysreg(cnthctl_el2); + val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; + write_sysreg(val, cnthctl_el2); + } /* Clear cntvoff for the host */ write_sysreg(0, cntvoff_el2); @@ -50,14 +68,17 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; u64 val; - /* - * Disallow physical timer access for the guest - * Physical counter access is allowed - */ - val = read_sysreg(cnthctl_el2); - val &= ~CNTHCTL_EL1PCEN; - val |= CNTHCTL_EL1PCTEN; - write_sysreg(val, cnthctl_el2); + /* Those bits are already configured at boot on VHE-system */ + if (!has_vhe()) { + /* + * Disallow physical timer access for the guest + * Physical counter access is allowed + */ + val = read_sysreg(cnthctl_el2); + val &= ~CNTHCTL_EL1PCEN; + val |= CNTHCTL_EL1PCTEN; + write_sysreg(val, cnthctl_el2); + } if (timer->enabled) { write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);