From patchwork Tue Oct 3 03:11:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jintack Lim X-Patchwork-Id: 9981531 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 85F22602B8 for ; Tue, 3 Oct 2017 03:16:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78B082887F for ; Tue, 3 Oct 2017 03:16:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D76628882; Tue, 3 Oct 2017 03:16:25 +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.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_HI,RCVD_IN_SORBS_SPAM autolearn=unavailable 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 A9B882887F for ; Tue, 3 Oct 2017 03:16:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751840AbdJCDQK (ORCPT ); Mon, 2 Oct 2017 23:16:10 -0400 Received: from mail-it0-f47.google.com ([209.85.214.47]:50823 "EHLO mail-it0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751894AbdJCDMB (ORCPT ); Mon, 2 Oct 2017 23:12:01 -0400 Received: by mail-it0-f47.google.com with SMTP id y138so10005748itc.5 for ; Mon, 02 Oct 2017 20:12:01 -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=9i2WruQyyjnDqIxjHGFDBHeRvu6kqt7bRb8vlRJ9+LE=; b=bD3UogmOUupo5kk4LGa3fWHTB9vB2pXsal59760y+eBdEORJSuHa9eRoGkSALEaGsg bdCXASNKxQqIKS3qbR+1n+BpRb9tFp7Ua5u4XMzbQQ8iwajVOuzqOnFJrsiHqkFRwhOw UdTR5MnmHur0yeplMq8IA6EoBdz9nC6w62A4I= 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=9i2WruQyyjnDqIxjHGFDBHeRvu6kqt7bRb8vlRJ9+LE=; b=mwW4O5/jdquL8BedEyA/KV8F5Oty7qpxAduh0MB72p9XgCpCQhqggpqnIp1i5zriIR AmU9bL5cf5cEYRJzOppY+TlJxzU4ckZAo7joZDTy+dXM6njSvkeQrZp5j9cYsIHpjWgm 2mZjMew/QBzUQrs5iR7Ip2H2NFaKHSszdeZeMd3+WH/tLHVIROBWJ6HPuwcKykP0yb0L uq2SQD29VtnMC4z6N4I+roJMU77lMhAScjTsnXUiV8M3AbnudFHw+Q/QUhZ0i7T1i/jl WrgwdR7pVN/EpeuwfwtmNnOvQTJwCQOACmLwbIlBoox2pzGuFPzfUuvTXyOgPCe/Hzjy T8Dw== X-Gm-Message-State: AMCzsaW8v8ZMcIIEew/TUsN9zsWsAvUvf+Drn3GealUZOMHlYlCjzVh6 8h6V9FWplmSHBcYb2DmpthZn+w== X-Google-Smtp-Source: AOwi7QA5Hwz+ppAhnZZczBWAMg1E57MizxFDvWGSjLH+Iehu+YSF7cQ1H+CbweLiWS21SaWMaIDEeQ== X-Received: by 10.36.237.79 with SMTP id r76mr9971346ith.140.1507000320823; Mon, 02 Oct 2017 20:12:00 -0700 (PDT) Received: from node.jintackl-qv28633.kvmarm-pg0.wisc.cloudlab.us (c220g1-031126.wisc.cloudlab.us. [128.104.222.76]) by smtp.gmail.com with ESMTPSA id h84sm5367193iod.72.2017.10.02.20.11.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Oct 2017 20:12:00 -0700 (PDT) From: Jintack Lim To: christoffer.dall@linaro.org, marc.zyngier@arm.com, kvmarm@lists.cs.columbia.edu Cc: jintack@cs.columbia.edu, pbonzini@redhat.com, rkrcmar@redhat.com, catalin.marinas@arm.com, will.deacon@arm.com, linux@armlinux.org.uk, mark.rutland@arm.com, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Jintack Lim Subject: [RFC PATCH v2 20/31] KVM: arm64: Implement AT instruction handling Date: Mon, 2 Oct 2017 22:11:02 -0500 Message-Id: <1507000273-3735-18-git-send-email-jintack.lim@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1507000273-3735-1-git-send-email-jintack.lim@linaro.org> References: <1507000273-3735-1-git-send-email-jintack.lim@linaro.org> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement AT instruction handling logic in EL2. This will be used to emulate AT instructions executed in the virtual EL2. AT instruction emulation works by loading the proper processor context, which depends on the trapped instruction and the virtual HCR_EL2, to the EL1 virtual memory control registers and executing AT instructions. Note that ctxt->hw_sys_regs is expected to have the proper processor context before calling the handling function(__kvm_at_insn) implemented in this patch. Signed-off-by: Jintack Lim --- arch/arm64/include/asm/kvm_asm.h | 3 + arch/arm64/kvm/hyp/Makefile | 1 + arch/arm64/kvm/hyp/at.c | 131 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 arch/arm64/kvm/hyp/at.c diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index e492749..4bded9d 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -56,6 +56,9 @@ extern void __kvm_tlb_flush_vmid(u64 vttbr); extern void __kvm_tlb_flush_local_vmid(u64 vttbr); +extern void __kvm_at_insn(struct kvm_vcpu *vcpu, unsigned long vaddr, + bool el2_regime, int sys_encoding); + extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); extern u64 __vgic_v3_get_ich_vtr_el2(void); diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 14c4e3b..1b03adb 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += entry.o obj-$(CONFIG_KVM_ARM_HOST) += switch.o obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o obj-$(CONFIG_KVM_ARM_HOST) += tlb.o +obj-$(CONFIG_KVM_ARM_HOST) += at.o obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o diff --git a/arch/arm64/kvm/hyp/at.c b/arch/arm64/kvm/hyp/at.c new file mode 100644 index 0000000..d491d94 --- /dev/null +++ b/arch/arm64/kvm/hyp/at.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2017 - Linaro Ltd + * Author: Jintack Lim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +static void __hyp_text __save_vmregs(struct kvm_cpu_context *ctxt) +{ + u64 *sys_regs = kern_hyp_va(ctxt->hw_sys_regs); + + sys_regs[TTBR0_EL1] = read_sysreg_el1(ttbr0); + sys_regs[TTBR1_EL1] = read_sysreg_el1(ttbr1); + sys_regs[TCR_EL1] = read_sysreg_el1(tcr); + sys_regs[SCTLR_EL1] = read_sysreg_el1(sctlr); +} + +static void __hyp_text __restore_vmregs(struct kvm_cpu_context *ctxt) +{ + u64 *sys_regs = kern_hyp_va(ctxt->hw_sys_regs); + + write_sysreg_el1(sys_regs[TTBR0_EL1], ttbr0); + write_sysreg_el1(sys_regs[TTBR1_EL1], ttbr1); + write_sysreg_el1(sys_regs[TCR_EL1], tcr); + write_sysreg_el1(sys_regs[SCTLR_EL1], sctlr); +} + +void __hyp_text __at_switch_to_guest_nvhe(struct kvm_vcpu *vcpu, + bool el2_regime) +{ + struct kvm_cpu_context *host_ctxt; + struct kvm_cpu_context *guest_ctxt; + u64 val; + + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); + guest_ctxt = &vcpu->arch.ctxt; + + __save_vmregs(host_ctxt); + __restore_vmregs(guest_ctxt); + + val = read_sysreg(hcr_el2); + if (el2_regime) + val |= (HCR_NV | HCR_NV1); + write_sysreg(val, hcr_el2); +} + +void __hyp_text __at_switch_to_guest_vhe(struct kvm_vcpu *vcpu, bool el2_regime) +{ + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; + u64 val; + + __restore_vmregs(guest_ctxt); + + val = read_sysreg(hcr_el2); + val &= ~HCR_TGE; + if (el2_regime) + val |= (HCR_NV | HCR_NV1); + write_sysreg(val, hcr_el2); +} + +/* + * Switching to guest. + * + * 1. [nvhe] Save host vm regs + * 2. [both] Restore guest vm regs + * 3. [both] Set HCR_EL2.NV/NV1 bit if necessary + * 4. [vhe] Clear HCR_EL2.TGE + */ +static hyp_alternate_select(__at_switch_to_guest, + __at_switch_to_guest_nvhe, __at_switch_to_guest_vhe, + ARM64_HAS_VIRT_HOST_EXTN); + +void __hyp_text __kvm_at_insn(struct kvm_vcpu *vcpu, unsigned long vaddr, + bool el2_regime, int sys_encoding) +{ + struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt; + struct kvm_cpu_context *host_ctxt; + + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); + + __at_switch_to_guest()(vcpu, el2_regime); + + switch (sys_encoding) { + case AT_S1E1R: + case AT_S1E2R: + asm volatile("at s1e1r, %0" : : "r" (vaddr)); + break; + case AT_S1E1W: + case AT_S1E2W: + asm volatile("at s1e1w, %0" : : "r" (vaddr)); + break; + case AT_S1E0R: + asm volatile("at s1e0r, %0" : : "r" (vaddr)); + break; + case AT_S1E0W: + asm volatile("at s1e0w, %0" : : "r" (vaddr)); + break; + case AT_S1E1RP: + asm volatile("at s1e1rp, %0" : : "r" (vaddr)); + break; + case AT_S1E1WP: + asm volatile("at s1e1wp, %0" : : "r" (vaddr)); + break; + default: + break; + } + + /* Save the translation result to the virtual machine's context */ + ctxt->sys_regs[PAR_EL1] = read_sysreg(par_el1); + + /* Switch to the host */ + if (has_vhe()) { + write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2); + } else { + /* We don't save guest vm regs; we didn't make any changes */ + __restore_vmregs(host_ctxt); + write_sysreg(HCR_RW, hcr_el2); + } +}