From patchwork Wed May 20 16:18:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andr=C3=A9_Hentschel?= X-Patchwork-Id: 6447981 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0739E9F318 for ; Wed, 20 May 2015 16:21:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 128C52034C for ; Wed, 20 May 2015 16:21:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 237BD202FF for ; Wed, 20 May 2015 16:21:30 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Yv6i6-0002l6-1l; Wed, 20 May 2015 16:19:10 +0000 Received: from mo6-p00-ob.smtp.rzone.de ([2a01:238:20a:202:5300::12]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Yv6hz-0002bX-KH for linux-arm-kernel@lists.infradead.org; Wed, 20 May 2015 16:19:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1432138717; l=3825; s=domk; d=dawncrow.de; h=Content-Transfer-Encoding:Content-Type:Subject:CC:To:MIME-Version: From:Date; bh=7DsmGEqp6ZcnbcBz/9Um32/u/+UAgs5T0sRvyeLW18c=; b=B2TlX3t0ZTX4XlkXJNAu16FN1/iU041VoeUWD+6qX/7smeTmrLj3lGReUB4NAYDCyaQ qUHYzgaCwb3aFaEPhb1wIVSKwcNoq6jen5OhtSF9PnBvjV2vkMXnuDqnivypOyjA+snYI MbDhvpsCcb48+5HNh4SPQa3kX1h6vn55594= X-RZG-AUTH: :ImkWY2CseuihIZy6ZWWciR6unPh5JPSWE7VxbdUCFBN5njG7Q28CH4RMeHzjXw== X-RZG-CLASS-ID: mo00 Received: from [192.168.178.44] ([185.61.121.176]) by smtp.strato.de (RZmta 37.6 AUTH) with ESMTPSA id K030a5r4KGIUJ6c (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (curve secp521r1 with 521 ECDH bits, eq. 15360 bits RSA)) (Client did not present a certificate); Wed, 20 May 2015 18:18:30 +0200 (CEST) Message-ID: <555CB3D5.7000307@dawncrow.de> Date: Wed, 20 May 2015 18:18:29 +0200 From: =?windows-1252?Q?Andr=E9_Hentschel?= User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: "linux-arch@vger.kernel.org" Subject: [PATCH v2] arm64: Preserve the user r/w register tpidr_el0 on context switch and fork in compat mode X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150520_091904_031800_8317C39A X-CRM114-Status: GOOD ( 16.51 ) X-Spam-Score: -0.1 (/) Cc: Russell King - ARM Linux , "gregkh@linuxfoundation.org" , Will Deacon , "linux-kernel@vger.kernel.org" , Catalin Marinas , Nathan Lynch , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: AndrĂ© Hentschel Since commit a4780adeefd042482f624f5e0d577bf9cdcbb760 the user writeable TLS register on ARM is preserved per thread. This patch does it analogous to the ARM patch, but for compat mode on ARM64. Signed-off-by: AndrĂ© Hentschel Cc: Will Deacon Cc: Catalin Marinas --- This patch is against Linux 4.1-rc1 (b787f68c36d49bb1d9236f403813641efa74a031) v2: Trying to address suggestions by Will Deacon @Will Deacon: The macro you suggested is not helpful it seems, instead i introduced static functions. They also could be macros i guess, but it seems much cleaner to me to use functions as it only affects one file. Should the final version be send to rmk's patchtracker or will someone else pick it up? arch/arm64/include/asm/processor.h | 3 +++ arch/arm64/kernel/process.c | 41 +++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index d2c37a1..466a851 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -79,6 +79,9 @@ struct cpu_context { struct thread_struct { struct cpu_context cpu_context; /* cpu context */ unsigned long tp_value; +#ifdef CONFIG_COMPAT + unsigned long tp_compat; +#endif struct fpsimd_state fpsimd_state; unsigned long fault_address; /* fault info */ unsigned long fault_code; /* ESR_EL1 value */ diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index c6b1f3b..630f44b 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -58,6 +58,22 @@ unsigned long __stack_chk_guard __read_mostly; EXPORT_SYMBOL(__stack_chk_guard); #endif +static unsigned long get_tp_compat(struct thread_struct *p) +{ +#ifdef CONFIG_COMPAT + return p->tp_compat; +#else + return 0; +#endif +} + +static void set_tp_compat(struct thread_struct *p, unsigned long tpidr) +{ +#ifdef CONFIG_COMPAT + p->tp_compat = tpidr; +#endif +} + void soft_restart(unsigned long addr) { setup_mm_for_reboot(); @@ -219,6 +235,7 @@ static void tls_thread_flush(void) if (is_compat_task()) { current->thread.tp_value = 0; + set_tp_compat(¤t->thread, 0); /* * We need to ensure ordering between the shadow state and the @@ -259,17 +276,22 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); if (likely(!(p->flags & PF_KTHREAD))) { + unsigned long tpidr; *childregs = *current_pt_regs(); childregs->regs[0] = 0; + /* + * Read the current TLS pointer from tpidr_el0 as it may be + * out-of-sync with the saved value. + */ + asm("mrs %0, tpidr_el0" : "=r" (tpidr)); if (is_compat_thread(task_thread_info(p))) { + set_tp_compat(&p->thread, tpidr); + if (stack_start) childregs->compat_sp = stack_start; } else { - /* - * Read the current TLS pointer from tpidr_el0 as it may be - * out-of-sync with the saved value. - */ - asm("mrs %0, tpidr_el0" : "=r" (tls)); + tls = tpidr; + if (stack_start) { /* 16-byte aligned stack mandatory on AArch64 */ if (stack_start & 15) @@ -302,13 +324,14 @@ static void tls_thread_switch(struct task_struct *next) { unsigned long tpidr, tpidrro; - if (!is_compat_task()) { - asm("mrs %0, tpidr_el0" : "=r" (tpidr)); + asm("mrs %0, tpidr_el0" : "=r" (tpidr)); + if (is_compat_task()) + set_tp_compat(¤t->thread, tpidr); + else current->thread.tp_value = tpidr; - } if (is_compat_thread(task_thread_info(next))) { - tpidr = 0; + tpidr = get_tp_compat(&next->thread); tpidrro = next->thread.tp_value; } else { tpidr = next->thread.tp_value;