Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753067AbcLCPDE (ORCPT ); Sat, 3 Dec 2016 10:03:04 -0500 Received: from mail.skyhub.de ([78.46.96.112]:37867 "EHLO mail.skyhub.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752798AbcLCPDC (ORCPT ); Sat, 3 Dec 2016 10:03:02 -0500 Date: Sat, 3 Dec 2016 16:02:58 +0100 From: Borislav Petkov To: Linus Torvalds Cc: Andy Lutomirski , Peter Anvin , the arch/x86 maintainers , One Thousand Gnomes , "linux-kernel@vger.kernel.org" , Brian Gerst , Matthew Whitehead , Henrique de Moraes Holschuh , Peter Zijlstra , Andrew Cooper Subject: [PATCH] x86/alternatives: Do not use sync_core() to serialize I$ Message-ID: <20161203150258.vwr5zzco7ctgc4pe@pd.tnic> References: <0a21157c2233ba7d0781bbf07866b3f2d7e7c25d.1480638597.git.luto@kernel.org> <20161202180343.gehqor7lgtmzwqq3@pd.tnic> <20161202185008.tdziqrzi4a3axord@pd.tnic> <20161202192050.l5l3rcwems6hptub@pd.tnic> <20161202192844.elq2py3cxizjs2bx@pd.tnic> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20161202192844.elq2py3cxizjs2bx@pd.tnic> User-Agent: NeoMutt/20161014 (1.7.1) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3379 Lines: 92 On Fri, Dec 02, 2016 at 08:28:44PM +0100, Borislav Petkov wrote: > Ah, it is called only from apply_alternatives() but sure, it is safer > this way. Lemme do that and run it through the boxes to see whether > anything catches fire. Looks good, ran it on a bunch of machines, two of them huge AMD and Intel, 8-socket monsters. Here is a version with a commit message: --- From: Borislav Petkov Date: Fri, 2 Dec 2016 23:18:51 +0100 Subject: [PATCH] x86/alternatives: Do not use sync_core() to serialize I$ We use sync_core() in the alternatives code to stop speculative execution of prefetched instructions because we are potentially changing them and don't want to execute stale bytes. What it does on most machines is call CPUID which is a serializing instruction. And that's expensive. However, the instruction cache is serialized when we're on the local CPU and are changing the data through the same virtual address. So then, we don't need the serializing CPUID but a simple control flow change. Last being accomplished with a CALL/RET which the noinline causes. So let's try it. Signed-off-by: Borislav Petkov Suggested-by: Linus Torvalds Cc: Andy Lutomirski --- arch/x86/kernel/alternative.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 5cb272a7a5a3..c5b8f760473c 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -337,7 +337,11 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf) n_dspl, (unsigned long)orig_insn + n_dspl + repl_len); } -static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr) +/* + * "noinline" to cause control flow change and thus invalidate I$ and + * cause refetch after modification. + */ +static void __init_or_module noinline optimize_nops(struct alt_instr *a, u8 *instr) { unsigned long flags; @@ -346,7 +350,6 @@ static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr) local_irq_save(flags); add_nops(instr + (a->instrlen - a->padlen), a->padlen); - sync_core(); local_irq_restore(flags); DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ", @@ -359,9 +362,12 @@ static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr) * This implies that asymmetric systems where APs have less capabilities than * the boot processor are not handled. Tough. Make sure you disable such * features by hand. + * + * Marked "noinline" to cause control flow change and thus insn cache + * to refetch changed I$ lines. */ -void __init_or_module apply_alternatives(struct alt_instr *start, - struct alt_instr *end) +void __init_or_module noinline apply_alternatives(struct alt_instr *start, + struct alt_instr *end) { struct alt_instr *a; u8 *instr, *replacement; @@ -667,7 +673,6 @@ void *__init_or_module text_poke_early(void *addr, const void *opcode, unsigned long flags; local_irq_save(flags); memcpy(addr, opcode, len); - sync_core(); local_irq_restore(flags); /* Could also do a CLFLUSH here to speed up CPU recovery; but that causes hangs on some VIA CPUs. */ -- 2.11.0 -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.