From patchwork Thu Jan 11 04:43:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolin Chen X-Patchwork-Id: 10156931 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 37772601A1 for ; Thu, 11 Jan 2018 04:43:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 26D89286AA for ; Thu, 11 Jan 2018 04:43:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 18C6B286B2; Thu, 11 Jan 2018 04:43:58 +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_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, 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 757C8286AA for ; Thu, 11 Jan 2018 04:43:57 +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:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=tNRJe0b6S9EHCEQPtGSMZ39dgpvitaXz4cONQ/ZxyQk=; b=jVV gBVz/sLo5nKXWkMfTUi6wkDzxOSC6S3teTklLCv1uhp7NWqDYVJ/CbYijxzZ7RJGSfT8lPKFQ5aY7 5hFr5xkx7tWM5YxlYnD+IymSg23TkYmjsrMbLlffK1ytf+wu6r5PiuewPtVoJlMbzy3o7rXXkLfbS NTfPNt9FPzscDg+4oRNG82MiIwwYHeFGMoIHTq2NKOVWzMUd2OpUVPbxKV4/TxxbxIg/5RWE7HHUD rVdRLbHebqq1OhS26yqHLdKAjVSJGEEZqojJ0DQRmUW3ibN/A008LUMHtji2sPgPne/tZ2Jbs6e0A W6IDehJREPjP9bDwR8kNwfihOiXJRDQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eZUiX-0006rt-6g; Thu, 11 Jan 2018 04:43:53 +0000 Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eZUiS-0006qP-Ot for linux-arm-kernel@lists.infradead.org; Thu, 11 Jan 2018 04:43:50 +0000 Received: by mail-pf0-x241.google.com with SMTP id j3so537339pfh.8 for ; Wed, 10 Jan 2018 20:43:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=4VGR28p1UsIqIg61YYMG3bf8u/mycQBdGj/HI7kQmH8=; b=hoBJ56FggZpWI3kn6B/HjnbreliDE/capWDlHi0bnhWUfJfffzbZERMSosaVcNvYKs MDS5KZKjb82wLPeK5XYcxku/MOVjQNo71x1gqzqwf++3Tt58wIlPc4FLUiJlICoTlzvx hRW230M41TH7ydbtTpL0hn/a/fcClxJZvAXTnCABSXPfo7kWQ0qjWgXdGbP1cgzJeeAJ 7OyMX3/OYB/tZHqBi/HwmnWkowY+y33EVANlyZcC2fr3k1vxX8/uyQrGxCSs4TugyFCS 5gX7UJcuXIndRvJ6SlDgyOWrMVVvT9yAK4LwWGlxy/CNK82rPiHMdDlnNv7YJcFoRLiF GcKQ== 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; bh=4VGR28p1UsIqIg61YYMG3bf8u/mycQBdGj/HI7kQmH8=; b=BBERF+Y9TPjAcDD1zU0zpps4MmRUR7oT3QjHMqIiT17DJ8av92Z9jCKH8blHUfEYj8 FBfdb3B174DHH1UlrKV6kWwUi0KyEKEVGcAQSDMjhdg1Y3TWbi4dclcVR80HXuCKXdW+ wBk9RYZzFCgc6KHMQw2UTgHOgrU3JusdXRGMZJXoyZtyl8d0c9FCdRbUYvcSWzZjCtCq Sj58f/IpjW788h4uDprchggNWFe1+dGZ9mBrIfdHgYM9AmO1LnhbRBnnxmnGpXN0N2jn NAtUGW1N2WmiQZapRdiFkjT+NZt39GxGE84Hw3rgXrPV60MZ6lDuTK/2m5WbcgdUBDvs +Swg== X-Gm-Message-State: AKGB3mIXlmzq58myAyNHrdv6GV7h1KpEL3Tcb7BTXRMZFMxk6s+U/hpn P5vRg7J0gDMAAJ5ke+g8AYo= X-Google-Smtp-Source: ACJfBosNKfe7uLadHFnIPS9EDvAKCBdxFOfDm33YbnGig3VNMuKG90noM0GBpAm1xDmA0ff6MXylvg== X-Received: by 10.84.217.217 with SMTP id d25mr13241999plj.312.1515645816129; Wed, 10 Jan 2018 20:43:36 -0800 (PST) Received: from Asurada-Nvidia.nvidia.com (thunderhill.nvidia.com. [216.228.112.22]) by smtp.gmail.com with ESMTPSA id s189sm33377470pgc.5.2018.01.10.20.43.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 10 Jan 2018 20:43:35 -0800 (PST) From: Nicolin Chen To: marc.zyngier@arm.com, mark.rutland@arm.com Subject: [PATCH RFC v1] arm64: Handle traps from accessing CNTVCT/CNTFRQ for CONFIG_COMPAT Date: Wed, 10 Jan 2018 20:43:36 -0800 Message-Id: <1515645816-14063-1-git-send-email-nicoleotsuka@gmail.com> X-Mailer: git-send-email 2.1.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180110_204348_813300_CB29187F X-CRM114-Status: GOOD ( 18.73 ) 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: , Cc: cdall@linaro.org, ard.biesheuvel@linaro.org, linux-kernel@vger.kernel.org, xiexiuqi@huawei.com, julien.thierry@arm.com, catalin.marinas@arm.com, tbaicar@codeaurora.org, will.deacon@arm.com, oleg@redhat.com, mingo@kernel.org, james.morse@arm.com, robin.murphy@arm.com, Dave.Martin@arm.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 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 CONFIG_COMPAT allows ARM64 machine to run 32-bit instructions. Since the ARCH_TIMER_USR_VCT_ACCESS_EN might be disabled if a timer workaround is detected, accessing cntvct via mrrc will also trigger a trap. So this patch adds support to handle this situation. Tested with a user program generated by 32-bit compiler: int main() { unsigned long long cval; asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); return 0; } Signed-off-by: Nicolin Chen --- [ I also added cntfrq here for safety as theoretically it could trigger the trap as well. However, my another test case (with mrc insturction) doesn't seem to trigger a trap. So I would drop it in the next version if someone can confirm it's not required. Thanks -- Nicolin ] arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++ arch/arm64/include/asm/ptrace.h | 15 ++++++++++++ arch/arm64/kernel/entry.S | 4 ++-- arch/arm64/kernel/traps.c | 53 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 014d7d8..55dea62 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -220,6 +220,31 @@ (((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >> \ ESR_ELx_SYS64_ISS_OP2_SHIFT)) +/* ISS fields for MRC and MRS are very similar, so reuse SYS64 macros */ +#define ESR_ELx_CP15_32_ISS_MRC_MASK ESR_ELx_SYS64_ISS_SYS_MASK +#define ESR_ELx_CP15_32_ISS_MRC_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(0, 0, 0, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + +/* ISS field definitions for CP15 MRRC/MCRR instructions (same for CP14) */ +#define ESR_ELx_CP15_64_ISS_OPC1_SHIFT 16 +#define ESR_ELx_CP15_64_ISS_OPC1_MASK (UL(0xf) << ESR_ELx_CP15_64_ISS_OPC1_SHIFT) +#define ESR_ELx_CP15_64_ISS_RT2_SHIFT 10 +#define ESR_ELx_CP15_64_ISS_RT2_MASK (UL(0x1f) << ESR_ELx_CP15_64_ISS_RT2_SHIFT) +#define ESR_ELx_CP15_64_ISS_RT_SHIFT 5 +#define ESR_ELx_CP15_64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_CP15_64_ISS_RT_SHIFT) +#define ESR_ELx_CP15_64_ISS_CRM_SHIFT 1 +#define ESR_ELx_CP15_64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_CP15_64_ISS_CRM_SHIFT) +#define ESR_ELx_CP15_64_ISS_MRRC_MASK (ESR_ELx_CP15_64_ISS_OPC1_MASK | \ + ESR_ELx_CP15_64_ISS_CRM_MASK| \ + ESR_ELx_SYS64_ISS_DIR_MASK) + +#define ESR_ELx_CP15_64_ISS_MRRC_VAL(opc1, crm) \ + (((opc1) << ESR_ELx_CP15_64_ISS_OPC1_SHIFT) | \ + ((crm) << ESR_ELx_CP15_64_ISS_CRM_SHIFT)) + +#define ESR_ELx_CP15_64_ISS_MRRC_CNTVCT (ESR_ELx_CP15_64_ISS_MRRC_VAL(1, 14) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index 6069d66..50caf11 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -243,6 +243,21 @@ static inline void pt_regs_write_reg(struct pt_regs *regs, int r, regs->regs[r] = val; } +/* + * Write two registers given architectural register index r and r2. + * Used by 32-bit MRRC and MCRR instrutions for 64-bit results + */ +static inline void pt_regs_write_regs(struct pt_regs *regs, int r, int r2, + unsigned long val) +{ + if (r != 31 && r2 != 31) { + /* Save lower 32 bits to register r */ + regs->regs[r] = val & 0xffffffff; + /* Save higher 32 bits to register r2 */ + regs->regs[r2] = val >> 32; + } +} + /* Valid only for Kernel mode traps. */ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) { diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 6d14b8f..9d6cd95 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -636,9 +636,9 @@ el0_sync_compat: cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL0 b.eq el0_undef cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap - b.eq el0_undef + b.eq el0_sys cmp x24, #ESR_ELx_EC_CP15_64 // CP15 MRRC/MCRR trap - b.eq el0_undef + b.eq el0_sys cmp x24, #ESR_ELx_EC_CP14_MR // CP14 MRC/MCR trap b.eq el0_undef cmp x24, #ESR_ELx_EC_CP14_LS // CP14 LDC/STC trap diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 3d3588f..211cce7 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -454,6 +454,17 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); } +#ifdef CONFIG_COMPAT +static void cntvct_read_32_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt2 = (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT; + int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT; + + pt_regs_write_regs(regs, rt, rt2, arch_counter_get_cntvct()); + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); +} +#endif + static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) { int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; @@ -495,11 +506,49 @@ static struct sys64_hook sys64_hooks[] = { {}, }; +#ifdef CONFIG_COMPAT +static struct sys64_hook cp15_32_hooks[] = { + { + /* Trap read access to CNTFRQ via 32-bit insturction MRC */ + .esr_mask = ESR_ELx_CP15_32_ISS_MRC_MASK, + .esr_val = ESR_ELx_CP15_32_ISS_MRC_CNTFRQ, + .handler = cntfrq_read_handler, + }, + {}, +}; + +static struct sys64_hook cp15_64_hooks[] = { + { + /* Trap read access to CNTVCT via 32-bit insturction MRRC */ + .esr_mask = ESR_ELx_CP15_64_ISS_MRRC_MASK, + .esr_val = ESR_ELx_CP15_64_ISS_MRRC_CNTVCT, + .handler = cntvct_read_32_handler, + }, + {}, +}; +#endif + asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) { - struct sys64_hook *hook; + struct sys64_hook *hook = NULL; + + switch (ESR_ELx_EC(esr)) { +#ifdef CONFIG_COMPAT + case ESR_ELx_EC_CP15_32: + hook = cp15_32_hooks; + break; + case ESR_ELx_EC_CP15_64: + hook = cp15_64_hooks; + break; +#endif + case ESR_ELx_EC_SYS64: + hook = sys64_hooks; + break; + default: + break; + } - for (hook = sys64_hooks; hook->handler; hook++) + for (; hook && hook->handler; hook++) if ((hook->esr_mask & esr) == hook->esr_val) { hook->handler(esr, regs); return;