From patchwork Tue Oct 17 14:14:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dongjiu Geng X-Patchwork-Id: 10012113 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 17EC0601E7 for ; Tue, 17 Oct 2017 13:51:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E307288CB for ; Tue, 17 Oct 2017 13:51:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 02FC6288E8; Tue, 17 Oct 2017 13:51:22 +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=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D336C288CB for ; Tue, 17 Oct 2017 13:51:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xnc9tKB06czsSX8VMsKwGUEcy/dSioJXksaQagiQcIs=; b=t1c3CPBFsracbC l2cRybEeZYtY2+MFYVVIv+ERhp3CFdQeX8i5lR043Tad0kyzbQc0OA34ypu+k6veif1ygsMu10RV/ 01T4Sexf9/HUpXPAa7A0jChkZv5Avvyu/6FklsgDMkyQmR47Sad7qtUVaMBQwHb1RZTBjreCHE7It oQZf46b0Yv82mNNhf44sq83R7y1dsV/SQr3qDFoWc7dSqtFUYK5sWP5VW6paReVQoPL/J230V8+O8 neKGgMx3a2gFgg52qGob6/E+lHPqxwikZIlWCNW3AcIWKKkk6kUTI9i21UbIslWJSfo4o2BADaa/N IrFMlmn1zaOhKcms0GMQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1e4SHA-0005nf-U6; Tue, 17 Oct 2017 13:51:20 +0000 Received: from szxga05-in.huawei.com ([45.249.212.191]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1e4SFf-0002oJ-TR for linux-arm-kernel@lists.infradead.org; Tue, 17 Oct 2017 13:50:09 +0000 Received: from 172.30.72.59 (EHLO DGGEMS401-HUB.china.huawei.com) ([172.30.72.59]) by dggrg05-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id DJH70338; Tue, 17 Oct 2017 21:49:03 +0800 (CST) Received: from linux.huawei.com (10.67.187.203) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.301.0; Tue, 17 Oct 2017 21:48:48 +0800 From: Dongjiu Geng To: , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v7 1/4] arm64: kvm: route synchronous external abort exceptions to EL2 Date: Tue, 17 Oct 2017 22:14:46 +0800 Message-ID: <1508249689-10350-2-git-send-email-gengdongjiu@huawei.com> X-Mailer: git-send-email 1.7.7 In-Reply-To: <1508249689-10350-1-git-send-email-gengdongjiu@huawei.com> References: <1508249689-10350-1-git-send-email-gengdongjiu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.187.203] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020203.59E60A4F.0131, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 6ee9113daca47ba61c184db28d3b0f46 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171017_064948_944914_3A0A13BB X-CRM114-Status: GOOD ( 14.61 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP ARMv8.2 adds a new bit HCR_EL2.TEA which controls to route synchronous external aborts to EL2, and adds a trap control bit HCR_EL2.TERR which controls to trap all Non-secure EL1&0 error record accesses to EL2. This patch enables the two bits for the guest OS. when an synchronous abort is generated in the guest OS, it will trap to EL3 firmware, EL3 firmware will check the HCR_EL2.TEA value to decide to jump to hypervisor or host OS. Enabling HCR_EL2.TERR makes error record access from guest trap to EL2. Add some minimal emulation for RAS-Error-Record registers. In the emulation, ERRIDR_EL1 and ERRSELR_EL1 are zero. Then, the others ERX* registers are RAZ/WI. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++++++ arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/asm/sysreg.h | 10 +++++++++ arch/arm64/kvm/sys_regs.c | 40 ++++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..1188272 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA (UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H (UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index fe39e68..47983db 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d686300..af55b3bc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -105,6 +105,8 @@ enum vcpu_sysreg { TTBR1_EL1, /* Translation Table Base Register 1 */ TCR_EL1, /* Translation Control Register */ ESR_EL1, /* Exception Syndrome Register */ + ERRIDR_EL1, /* Error Record ID Register */ + ERRSELR_EL1, /* Error Record Select Register */ AFSR0_EL1, /* Auxiliary Fault Status Register 0 */ AFSR1_EL1, /* Auxiliary Fault Status Register 1 */ FAR_EL1, /* Fault Address Register */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 35b786b..bd11ca0 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -169,6 +169,16 @@ #define SYS_AFSR0_EL1 sys_reg(3, 0, 5, 1, 0) #define SYS_AFSR1_EL1 sys_reg(3, 0, 5, 1, 1) #define SYS_ESR_EL1 sys_reg(3, 0, 5, 2, 0) + +#define SYS_ERRIDR_EL1 sys_reg(3, 0, 5, 3, 0) +#define SYS_ERRSELR_EL1 sys_reg(3, 0, 5, 3, 1) +#define SYS_ERXFR_EL1 sys_reg(3, 0, 5, 4, 0) +#define SYS_ERXCTLR_EL1 sys_reg(3, 0, 5, 4, 1) +#define SYS_ERXSTATUS_EL1 sys_reg(3, 0, 5, 4, 2) +#define SYS_ERXADDR_EL1 sys_reg(3, 0, 5, 4, 3) +#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0) +#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1) + #define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0) #define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2e070d3..a74617b 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -775,6 +775,36 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return true; } +static bool access_error_reg(struct kvm_vcpu *vcpu, struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + /* accessing ERRIDR_EL1 */ + if (r->CRm == 3 && r->Op2 == 0) { + if (p->is_write) + vcpu_sys_reg(vcpu, ERRIDR_EL1) = 0; + + return trap_raz_wi(vcpu, p, r); + } + + /* accessing ERRSELR_EL1 */ + if (r->CRm == 3 && r->Op2 == 1) { + if (p->is_write) + vcpu_sys_reg(vcpu, ERRSELR_EL1) = 0; + + return trap_raz_wi(vcpu, p, r); + } + + /* + * If ERRSELR_EL1.SEL is greater than or equal to ERRIDR_EL1.NUM, + * the ERX* registers are RAZ/WI. + */ + if ((vcpu_sys_reg(vcpu, ERRSELR_EL1) & 0xff) >= + (vcpu_sys_reg(vcpu, ERRIDR_EL1) && 0xff)) + return trap_raz_wi(vcpu, p, r); + + return true; +} + static bool access_pmswinc(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { @@ -953,6 +983,16 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_AFSR0_EL1), access_vm_reg, reset_unknown, AFSR0_EL1 }, { 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), access_error_reg, reset_val, ERRIDR_EL1, 0 }, + { SYS_DESC(SYS_ERRSELR_EL1), access_error_reg, reset_val, ERRSELR_EL1, 0 }, + { SYS_DESC(SYS_ERXFR_EL1), access_error_reg }, + { SYS_DESC(SYS_ERXCTLR_EL1), access_error_reg }, + { SYS_DESC(SYS_ERXSTATUS_EL1), access_error_reg }, + { SYS_DESC(SYS_ERXADDR_EL1), access_error_reg }, + { SYS_DESC(SYS_ERXMISC0_EL1), access_error_reg }, + { SYS_DESC(SYS_ERXMISC1_EL1), access_error_reg }, + { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },