Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp1121208imm; Fri, 15 Jun 2018 11:32:51 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJr/UKVImDwFvQCvoJQcZYyx5h9eWVbCqmwWOe2Z0hDSt91hC41j1pT52t3g9M1kwQhEBY2 X-Received: by 2002:a63:9611:: with SMTP id c17-v6mr2577062pge.361.1529087571392; Fri, 15 Jun 2018 11:32:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529087571; cv=none; d=google.com; s=arc-20160816; b=fbq7Ed1fnymxLkk1hkNxPKVhUEJK7ZO8NBUsNTIso+EQeK0m+sTPwgYFcfZ6QEKpyn RBcmaTKTBokddT9zGzMrmSoUMMYygObQgwI77Ihnt3GIqFCwKvliS7mY1UMBoUBfTLgU TiEI3IaBjIRqJ+d09AHEMY6AL70ay9hSrpIFud4690JQfwY783M1n+dpmaFBSovt+BSY 1orjyRl1bVJcuf4fnkl9Bm0bbsGtVhGvOVLBUc496fu7ZGEvgIGIBXCmndNmuhdDUdQy aaxjnX3h2PRzj/Xe/tYQumQZ75de3YFoqNu4FPMDTXClEaJJ7a9mk2E0PmDjjq7+fe2d JutA== 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:dkim-signature :arc-authentication-results; bh=0c1+fJxNw9X0/mjC882AyjGpq6tE8UnWpe7eXiwan58=; b=KNSNjZnK1rR/D75DOSusjTswkMewZQfFy802TRD5/WlROMyFxRlfL8QQEXJGRYiomI N+g5GuO0+G+Nj5HMlKzUd0PweNzm5YScA/YkgG6xSRHheh3eU/22RBNfGr7uqS27lS4Q 76vOijklRPbHv4+f40HjbMJoaMPqpJSHxmNc5va3P/6IQLwx9PKLc1NDelrN7Va/5DU1 VYSUPNSzhYFJB+CuJhPy69xDLdizhWjjlStq626dhpm+ByHcbIZVpT4I3n6VmTaFHfPh +KVtamFZZuXX77Qz68nqSDeuKVT+DNcgdvO9Rfg2YyI29906OuvWNyRk09NPc25ffIjS 8LEA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lf3fB19w; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s186-v6si7994197pfb.39.2018.06.15.11.32.36; Fri, 15 Jun 2018 11:32:51 -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; dkim=pass header.i=@kernel.org header.s=default header.b=lf3fB19w; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756564AbeFOScK (ORCPT + 99 others); Fri, 15 Jun 2018 14:32:10 -0400 Received: from mail.kernel.org ([198.145.29.99]:57568 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756489AbeFOScJ (ORCPT ); Fri, 15 Jun 2018 14:32:09 -0400 Received: from mail-wm0-f41.google.com (mail-wm0-f41.google.com [74.125.82.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 639EB208AF for ; Fri, 15 Jun 2018 18:32:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1529087528; bh=C9wIssmBQ0gJeTEgrFunr9lm2m/cJsqQnR5nEEQ0puk=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=lf3fB19wkxp3DSEjKIR99klR8rQ3wnpHbwQTb9rcjrNOdZkGjIwRgjb1Ecd1gul12 vl47RGh7uQrYgd9FuH+Wi0ufgo64aA1SUG94KBKlUf7bhRdNT0sjl82qVGVv0WBX4Y gNrM0Z4INxRsQ3FCAuMiYGJnuF47pyKgQfBNAhS8= Received: by mail-wm0-f41.google.com with SMTP id r125-v6so5428478wmg.2 for ; Fri, 15 Jun 2018 11:32:08 -0700 (PDT) X-Gm-Message-State: APt69E1htiI9FDPomlsKQRq0dKsHi3cHhvNmcTD9k5B0Xt2JBeXMP1vZ moYafaVfT4vLGA0kumNS+RwYvq/NmGPl4zH2Am3dFQ== X-Received: by 2002:a1c:f902:: with SMTP id x2-v6mr1953393wmh.116.1529087526870; Fri, 15 Jun 2018 11:32:06 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Andy Lutomirski Date: Fri, 15 Jun 2018 11:31:55 -0700 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: Lazy FPU restoration / moving kernel_fpu_end() to context switch To: "Jason A. Donenfeld" , Rik van Riel , Dave Hansen Cc: LKML , X86 ML Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jun 15, 2018 at 6:11 AM Jason A. Donenfeld wrote: > > Hi Andy & folks, > > Lots of crypto routines look like this: > > kernel_fpu_begin(); > encrypt(); > kernel_fpu_end(); > > If you call such a routine twice, you get: > > kernel_fpu_begin(); > encrypt(); > kernel_fpu_end(); > kernel_fpu_begin(); > encrypt(); > kernel_fpu_end(); > > In a loop this looks like: > > for (thing) { > kernel_fpu_begin(); > encrypt(thing); > kernel_fpu_end(); > } > > This is obviously very bad, because begin() and end() are slow, so > WireGuard does the obvious: > > kernel_fpu_begin(); > for (thing) > encrypt(thing); > kernel_fpu_end(); > > This is fine and well, and the crypto API I'm working on will enable > this to be done in a clear way, but I do wonder if maybe this is not > something that should be happening at the level of the caller, but > rather in the fpu functions themselves. Namely, what are your thoughts > on modifying kernel_fpu_end() so that it doesn't actually restore the > state, but just reenables preemption and marks that on the next > context switch, the state should be restored? Then, essentially, > kernel_fpu_begin() and end() become free after the first usage of > kernel_fpu_begin(). > > Is this something feasible? I know that performance-wise, I'm really > gaining a lot from hoisting those functions out of the loops, and API > wise, it'd be slightly simpler to implement if I didn't have to all > for that hoisting. Hi Jason- Funny you asked. This has been discussed a few times, although not quite in the form you imagined. The idea that we've tossed around is to restore FPU state on return to user mode. Roughly, we'd introduce a new thread flag TIF_FPU_UNLOADED (name TBD). prepare_exit_to_usermode() would notice this flag, copy the fpstate to fpregs, and clear the flag. (Or maybe exit_to_usermode_loop() -- No one has quite thought it through, but I think it should be outside the loop.) We'd update all the FPU accessors to understand the flag. We'd probably have a helper like: void unload_user_fpstate(void) that would do nothing if TIF_FPU_UNLOADED is set. If TIF_FPU_UNLOADED is clear, it would move the state to memory and set TIF_FPU_UNLOADED. We'd call unload_user_fpstate() during context switch in the prev task context and in kernel_fpu_begin(). The one major complication I know of is that PKRU is different from all other FPU state in that it needs to be loaded when *kernel* code does any user memory access. So we'd need to make sure that context switches load the new task's PKRU eagerly. Using WRPKRU is easy, but, unless we do something very clever, actually finding PKRU in the in-memory fpstate image may be slightly nontrivial. I suppose we could eagerly load the new FPU state on context switches, but I'm not sure I see any point. We'd still have to load it when we switch back to user mode, so it would be slower but not necessarily any simpler. I'd love to review patches to make this change, but I don't have the bandwidth to write them right now.