Received: by 10.213.65.68 with SMTP id h4csp1426873imn; Mon, 19 Mar 2018 04:01:30 -0700 (PDT) X-Google-Smtp-Source: AG47ELunruH4x3enuchMT0P6KNyV39pqNCpbg18ZNSGl6ozKFla7o3OxrMWjHSbdg9shVf+Nga4C X-Received: by 10.99.142.201 with SMTP id k192mr8771972pge.278.1521457290386; Mon, 19 Mar 2018 04:01:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521457290; cv=none; d=google.com; s=arc-20160816; b=ZgleXPytQuBaaHn9wyo6bv/kAYRTIP3IAokpRCJXmb2rvlzTAKliqWvz2qrE0g7dTK Xc5yI8/KMm84G7rXr/lgAmuit0ABths6f5WLda41pOYPfifW+dtdTavRgrMGFsWw4/3o gssmU3UFY/NuJBVJ7+7wH9eRcPH1qYNXaVuB7g3SXntxa7nV0/zS5JBGgHtNl5ZG4v6i W4XuZlA358xadtlhBHgq6qt78QxvJAnWsA9WB+pP6/eQ8I0KrYZVBc1Dgjffz2J9PnLL Jx+gkcZhYFYpHbT0DzP/3/ZNtlQuKbAKmsJkxMsBsqsF8UrN990f0POfAU//+ClbDIKt aH0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=GAGNQRsvGWF5hsZuGKfaP7mlBQ/s7+pX8oelkjtX6Lk=; b=fasqRw7oJgKGkREPfD1veFfwprXaFBprHIl+H9vFJ9dKsavSWAtZ5HppZ0YZvwCrXk 81VBvNrNBHsnqhVy2uqpXqV8KGvk0Q358JV8L/CY9PQfHVdgrRcYac8OyOcrIzbkITV2 xfvhxxpkQy0nmZxLdhnGhrL7uuyhjFlqn1VdShIS6BG3KaavZzJEVMLPkGHJeI5e6wbn Y+DQY9/fnraCHc4gJy6LC9s5sC8Yj8TiiX8gtU0JD07VzwcgCCGQrdwak36be+lU9dKI 5tJGkgNuRBtU9K5Ge/JI+bggjoapsx4GdjQ4bQ0p0vIscyr67+XJc1AAs/4y2vHBfC8Q fMhw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u3-v6si6231168plb.593.2018.03.19.04.01.15; Mon, 19 Mar 2018 04:01:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932957AbeCSLAK (ORCPT + 99 others); Mon, 19 Mar 2018 07:00:10 -0400 Received: from smtprelay.synopsys.com ([198.182.47.9]:37352 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932296AbeCSLAI (ORCPT ); Mon, 19 Mar 2018 07:00:08 -0400 Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by smtprelay.synopsys.com (Postfix) with ESMTP id 02FE324E132B; Mon, 19 Mar 2018 04:00:08 -0700 (PDT) Received: from mailhost.synopsys.com (localhost [127.0.0.1]) by mailhost.synopsys.com (Postfix) with ESMTP id BF0FE32A6; Mon, 19 Mar 2018 04:00:07 -0700 (PDT) Received: from ru20arcgnu1.internal.synopsys.com (ru20arcgnu1.internal.synopsys.com [10.121.9.48]) by mailhost.synopsys.com (Postfix) with ESMTP id F41C2320D; Mon, 19 Mar 2018 04:00:05 -0700 (PDT) From: Alexey Brodkin To: linux-snps-arc@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Vineet Gupta , Alexey Brodkin , Peter Zijlstra , Max Filippov , linux-arch@vger.kernel.org Subject: [PATCH] ARC: Improve cmpxchng syscall implementation Date: Mon, 19 Mar 2018 14:00:02 +0300 Message-Id: <20180319110002.27419-1-abrodkin@synopsys.com> X-Mailer: git-send-email 2.11.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org arc_usr_cmpxchg syscall is supposed to be used on platforms that lack support of Load-Locked/Store-Conditional instructions in hardware. And in that case we mimic missing hardware features with help of kernel's sycall that "atomically" checks current value in memory and then if it matches caller expectation new value is written to that same location. What's important in the description above: - Check-and-exchange must be "atomical" which means preemption must be disabled during entire "transaction" - Data accessed is from user-space, i.e. we're dealing with virtual addresses And in current implementation we have a couple of problems: 1. We do disable preemprion around __get_user() & __put_user() but that in its turn disables page fault handler. That means if a pointer to user's data has no mapping in the TLB we won't be able to access required data. Instead software "exception handling" code from __get_user_fn() will return -EFAULT. 2. What's worse if we're dealing with data from not yet allocated page (think of pre-copy-on-write state) we'll successfully read data but on write we'll silently return to user-space with correct result (which we really read just before). That leads to very strange problems in user-space app further down the line because new value was never written to the destination. 3. Regardless of what went wrong we'll return from syscall and user-space application will continue to execute. Even if user's pointer was completely bogus. In case of hardware LL/SC that app would have been killed by the kernel. With that change we attempt to imrove on all 3 items above: 1. We still disable preemption around read-and-write of user's data but if we happen to fail with either of them we're enabling preemption and try to force page fault so that we have a correct mapping in the TLB. Then re-try again in "atomic" context. 2. If real page fault fails or even access_ok() returns false we send SIGSEGV to the user-space process so if something goes seriously wrong we'll know about it much earlier. Signed-off-by: Alexey Brodkin Cc: Peter Zijlstra Cc: Vineet Gupta Cc: Max Filippov Cc: linux-arch@vger.kernel.org --- arch/arc/kernel/process.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 5ac3b547453f..d7d3e16133d6 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -47,7 +47,9 @@ SYSCALL_DEFINE0(arc_gettls) SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) { struct pt_regs *regs = current_pt_regs(); - int uval = -EFAULT; + struct page *page; + u32 val; + int ret; /* * This is only for old cores lacking LLOCK/SCOND, which by defintion @@ -60,23 +62,48 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) /* Z indicates to userspace if operation succeded */ regs->status32 &= ~STATUS_Z_MASK; - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; + ret = access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)); + if (!ret) + goto fail; +again: preempt_disable(); - if (__get_user(uval, uaddr)) - goto done; - - if (uval == expected) { - if (!__put_user(new, uaddr)) + ret = __get_user(val, uaddr); + if (ret == -EFAULT) { + preempt_enable(); + ret = get_user_pages_fast((unsigned long)uaddr, 1, 1, &page); + if (ret < 0) + goto fail; + + put_page(page); + goto again; + } else if (ret) + goto fail; + + if (val == expected) { + ret = __put_user(new, uaddr); + if (!ret) regs->status32 |= STATUS_Z_MASK; } -done: preempt_enable(); - return uval; + if (ret == -EFAULT) { + ret = get_user_pages_fast((unsigned long)uaddr, 1, 1, &page); + if (ret < 0) + goto fail; + + put_page(page); + goto again; + } else if (ret) + goto fail; + + return val; + +fail: + force_sig(SIGSEGV, current); + return ret; } #ifdef CONFIG_ISA_ARCV2 -- 2.11.0