Received: by 2002:a25:683:0:0:0:0:0 with SMTP id 125csp416109ybg; Fri, 12 Jun 2020 05:07:25 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwPH+lj/CsNVcrsUCYe8mw7gGhwTiHywebZlz5T7mojwJTSXW/CemA9m04Rw2inxmjdDsJ2 X-Received: by 2002:a17:906:22da:: with SMTP id q26mr367318eja.256.1591963645387; Fri, 12 Jun 2020 05:07:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591963645; cv=none; d=google.com; s=arc-20160816; b=rv8lPjWP8tPz5Iur7BnuRAdKqaFqbalTDh5V2GoH9FyjR2JWCdCoPv6AVHIPzuI9Se 3HJAdvIhH003W3dj7VcakfffmmkcJMezU3LTnFjxmnT8si4bn2SlVj8GKRcjs+ISmkWK dbbOBAyLW2XSpgxMIGW3hNasBqUXmbuXGthOKqu4piLHeaCqx1J6KUiiQcNyONJNJ7o8 d/8haf5s6cbgzknx4fTxQboYPLFK3YVobZxUMjo53eOqqT+msy8u1Z9ieriDEs2nuXaN Hpt/85u+hLgT2kO/7MjJnBwIoo6BZPaRQtre11BtQu9S0ChzmVSIxBsNzb1v5pTfg3pW s6bg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version; bh=ekhzkaPupqzYeXV2F/7alWA8c9/Equm3pHlL1wBQjq0=; b=cw6XUySx3WaHrrbBLkzvxqjcCTCM+3S/ECX3Y8dbXZdZOHoY+u1/qT1x6A5ozt3ou6 fvlX/kOoYq3dwbm3ebo58GyLjOe7jMFHwxrnhoWMYlFrhYqH0VTvqe1un3+eUz7WRuRa S8cLme9gqzZn5qIsEA4DH3VyHC1WEi5TeLBHEbYf9H5zQkjjPcUweWpK1G8KSSZB7Nue CrtYIx5aeX6e57/iHxHNvrFY19oDc+hpaCMIRa4D6TT5iKotBRFjfp++ixWbOOrs+8og C9SR5eoIiGpODd+ZJBjK9VqaIASsGUIL5a5wuC1ieoW6yS9eiXBH/Paw1v0lEfYlccyH OYSw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o12si3083843edr.155.2020.06.12.05.06.58; Fri, 12 Jun 2020 05:07:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726101AbgFLMCd (ORCPT + 99 others); Fri, 12 Jun 2020 08:02:33 -0400 Received: from mout.kundenserver.de ([212.227.126.131]:58577 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725886AbgFLMCd (ORCPT ); Fri, 12 Jun 2020 08:02:33 -0400 Received: from mail-qv1-f47.google.com ([209.85.219.47]) by mrelayeu.kundenserver.de (mreue012 [212.227.15.129]) with ESMTPSA (Nemesis) id 1MaHOX-1jOS5C2qmL-00WC6W for ; Fri, 12 Jun 2020 14:02:31 +0200 Received: by mail-qv1-f47.google.com with SMTP id p15so4210873qvr.9 for ; Fri, 12 Jun 2020 05:02:31 -0700 (PDT) X-Gm-Message-State: AOAM531yWUIiDLH+/Q4cBa1ph4Y+/rmHKdIX4fjelErVFRWhTpc1epR+ HRxu+J+K5ngIqs6vNr3yFDyHfaEFO7fAktxkZCk= X-Received: by 2002:a0c:ba0c:: with SMTP id w12mr12628573qvf.4.1591963350524; Fri, 12 Jun 2020 05:02:30 -0700 (PDT) MIME-Version: 1.0 References: <9e1de19f35e2d5e1d115c9ec3b7c3284b4a4e077.1591885760.git.afzal.mohd.ma@gmail.com> In-Reply-To: <9e1de19f35e2d5e1d115c9ec3b7c3284b4a4e077.1591885760.git.afzal.mohd.ma@gmail.com> From: Arnd Bergmann Date: Fri, 12 Jun 2020 14:02:13 +0200 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [RFC 1/3] lib: copy_{from,to}_user using gup & kmap_atomic() To: afzal mohammed Cc: Russell King - ARM Linux admin , Linus Walleij , "linux-kernel@vger.kernel.org" , Linux-MM , Linux ARM , Nicolas Pitre , Catalin Marinas , Will Deacon Content-Type: text/plain; charset="UTF-8" X-Provags-ID: V03:K1:YC/v+nicOl6cvJOVTGJY/HVyIWGBFraAlRDgozF0T0qDrGiQw3k 5ggN15KSh3EdkJ9S53+BrUGcg9E+WSHs3F0ttUIisfps+e5vEhmbv8krGCc/kPfAha2U1W+ 44JinSYeOypkKjDWyoCbwGDNTnSTREIE2CRJYbEcjI9Qo953hennwGqZwPPJXxUx4EKnyNh oIYNplDQKG2I6tfDcmViA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:MOGUWIfZU4s=:xR6L6qkvFA3jtnoOTHFgl7 Bv++m24RMPCQCEf6Ul+htjmpgfvjrUsCQVZInIoYAP9ReJrpsav0CQQ/RqZY6H0izSSEYSLNG FEKsS1ieMg6knaMlpIqxAucqdL5ZNpxPuz7N8TEqAIjYbJLCrCPgP+ABQTzwp5LzIAA2cT4CT aoCtlrzDQ+FITt9wPeT1nlTzsNN0MxSS76dcq98jdu4dguJHdgdXP5FmII87QqU75xu67vX2Q uMFbamBOlvdfHLiIKsFpGFFmOub1uruAe4c30dxyoIgS/tj11ahnCgB6Zimz2dwO5FdNzZILL Afe/f//qGG+de+zd0CBHE4URhXBe9L7PFDskG+C2qEWx0K+aKqsPeg4akdz2uTLvW+sE1B/Bi HKEeLWJYrQySxV2+M+Tw1Zm3LHIX8us9lfYxrHl+sfSZpXrynLrJEsKFVWnUzM8giQ0anHzGC ipDCX+Z824NS3Z798Etn/lLtyALFJDbkKawNchDBATMD9HnYzguw+VbMIAXht1aa2gGNNsv2i 2kifS1uOy865/SJ9tRPIJ1WTbeb76wcGZ4B8CVYz5HD5zjD7+2+xGjG33vrcYkpbg/f6RAjuC mFYp/XpojOdyrlud0fjZaRWrVtN5Fl1m1rle9L4fciyvu5zV1oteKFudeN+ADP3xcPN74rchh Bg8o7oqoq29Im8H/EUDKwLWEK1eLWkEK5XIi307K0+7MP8vSRBciUdGuGXstWJ8tcHv/7DElU Nli6O/oVk1Cf8LCStNfqysIg4CoTH+HPkb0Wxhklif5+jDw4y0dWcRTPoa48yEZlkKrTJCfUj m9c/pcJGao/oVt4/gje8ypihC1sjx5UNUa1euGLcf57eLcpoJg= Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jun 12, 2020 at 12:18 PM afzal mohammed wrote: > > copy_{from,to}_user() uaccess helpers are implemented by user page > pinning, followed by temporary kernel mapping & then memcpy(). This > helps to achieve user page copy when current virtual address mapping > of the CPU excludes user pages. > > Performance wise, results are not encouraging, 'dd' on tmpfs results, > > ARM Cortex-A8, BeagleBone White (256MiB RAM): > w/o series - ~29.5 MB/s > w/ series - ~20.5 MB/s > w/ series & highmem disabled - ~21.2 MB/s > > On Cortex-A15(2GiB RAM) in QEMU: > w/o series - ~4 MB/s > w/ series - ~2.6 MB/s > > Roughly a one-third drop in performance. Disabling highmem improves > performance only slightly. > > 'hackbench' also showed a similar pattern. > > uaccess routines using page pinning & temporary kernel mapping is not > something new, it has been done long long ago by Ingo [1] as part of > 4G/4G user/kernel mapping implementation on x86, though not merged in > mainline. > > [1] https://lore.kernel.org/lkml/Pine.LNX.4.44.0307082332450.17252-100000@localhost.localdomain/ Nice changelog text! I agree the performance drop is not great. There are probably some things that can be done to optimize it, but I guess most of the overhead is from the page table operations and cannot be avoided. What was the exact 'dd' command you used, in particular the block size? Note that by default, 'dd' will request 512 bytes at a time, so you usually only access a single page. It would be interesting to see the overhead with other typical or extreme block sizes, e.g. '1', '64', '4K', '64K' or '1M'. If you want to drill down into where exactly the overhead is (i.e. get_user_pages or kmap_atomic, or something different), using 'perf record dd ..', and 'perf report' may be helpful. > +static int copy_chunk_from_user(unsigned long from, int len, void *arg) > +{ > + unsigned long *to_ptr = arg, to = *to_ptr; > + > + memcpy((void *) to, (void *) from, len); > + *to_ptr += len; > + return 0; > +} > + > +static int copy_chunk_to_user(unsigned long to, int len, void *arg) > +{ > + unsigned long *from_ptr = arg, from = *from_ptr; > + > + memcpy((void *) to, (void *) from, len); > + *from_ptr += len; > + return 0; > +} Will gcc optimize away the indirect function call and inline everything? If not, that would be a small part of the overhead. > +unsigned long gup_kmap_copy_from_user(void *to, const void __user *from, unsigned long n) > +{ > + struct page **pages; > + int num_pages, ret, i; > + > + if (uaccess_kernel()) { > + memcpy(to, (__force void *)from, n); > + return 0; > + } > + > + num_pages = DIV_ROUND_UP((unsigned long)from + n, PAGE_SIZE) - > + (unsigned long)from / PAGE_SIZE; Make sure this doesn't turn into actual division operations but uses shifts. It might even be clearer here to open-code the shift operation so readers can see what this is meant to compile into. > + pages = kmalloc_array(num_pages, sizeof(*pages), GFP_KERNEL | __GFP_ZERO); > + if (!pages) > + goto end; Another micro-optimization may be to avoid the kmalloc for the common case, e.g. anything with "num_pages <= 64", using an array on the stack. > + ret = get_user_pages_fast((unsigned long)from, num_pages, 0, pages); > + if (ret < 0) > + goto free_pages; > + > + if (ret != num_pages) { > + num_pages = ret; > + goto put_pages; > + } I think this is technically incorrect: if get_user_pages_fast() only gets some of the pages, you should continue with the short buffer and return the number of remaining bytes rather than not copying anything. I think you did that correctly for a failed kmap_atomic(), but this has to use the same logic. Arnd