linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Andi Kleen <andi@firstfloor.org>
Cc: Andi Kleen <ak@linux.intel.com>,
	x86@kernel.org, Andrew Morton <akpm@linux-foundation.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>
Subject: Re: [PATCH 02/17] x86, lto: Mark all top level asm statements as .text
Date: Wed, 27 Mar 2019 15:20:08 +0100 (CET)	[thread overview]
Message-ID: <alpine.DEB.2.21.1903270820530.1789@nanos.tec.linutronix.de> (raw)
In-Reply-To: <20190327005523.bbxxittqf4d5bdz5@two.firstfloor.org>

Andi,

On Tue, 26 Mar 2019, Andi Kleen wrote:
> > Well, we better should know the real reason for this wreckage. I mean, the
> > default section for text is suprisingly .text. I don't see a reason why
> > this would be any different for an assembly function implemented in a C
> > file.
> 
> What happens is that when the function before the asm changes
> the section, gcc only changes it back for the next function/variable
> with a different section. But it doesn't change it back for the asm.
> 
> 
> e.g. here
> 
> __attribute__((section("foo"))) void func(void)
> {
> }
> 
> asm("foo:\n");
> 
> gives with gcc -S (might be different with optimization):
> 
>  .section foo,"ax",@progbits <----------------- sets the section
>  .globl func
>  .type func, @function

SNIP

> .LFE0:
>  .size func, .-func
> <--------------------------- no section reset before the asm
> #APP
>  foo:
> 
>  .ident "GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
>  .section .note.GNU-stack,"",@progbits

Makes sense, but comes as a surprise when the thing is actually marked as a
function.

> But gcc reorders functions even without LTO inside files, so it could
> eventually happen.

Adding

+void __init foo(void)
+{
+       pr_info("foo\n");
+}

right before the kretprobe_trampoline and compiling it with GCC 6.

So one would assume that kretprobe_trampoline now ends up in
.init.text. But it ends up in the .text section because it's reordered and
ends up at the top of .text.

So clearly stuff gets reordered and those top level ASM constructs which
lack a section are just working by chance and we need the annotations and
backport them.

We also need a way to detect such wreckage automatically. This can happen
again and as the GCC behaviour is random there is no guarantee that it's
noticed right away. Josh, can objtool help here or do we need some other
form of checking that?

So independent of the LTO issue, this information needs to be in the
changelog.

For the patch itself. The kprobes/vide/error-inject parts are fine because
these are clearly functions: ".type $NAME, @function\n".

But this hunk not so much:

--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -372,7 +372,7 @@ extern struct paravirt_patch_template pv_ops;
 
>  #define DEF_NATIVE(ops, name, code)					\
> 	__visible extern const char start_##ops##_##name[], end_##ops##_##name[];	\
> -	asm(NATIVE_LABEL("start_", ops, name) code NATIVE_LABEL("end_", ops, name))
> +	asm(".text\n\t" NATIVE_LABEL("start_", ops, name) code NATIVE_LABEL("end_", ops, name))

Because it is NOT text.

That 'code' is never executed in place. It's a patch table, which is used
by the alternative code to patch in the native instructions so the pv_ops
indirection can be avoided on bare metal. It's only copied into a buffer
nothing else. So blindly slapping '.text' on it is just wrong.

But that's not the only thing which is wrong here. DEF_NATIVE is only used
in paravirt_patch_32/64.c and the resulting labels are not used outside of
this either. So why are these labels global and the c declaration __visible
extern?

global was already in the original paravirt code and should have never been
there in the first place.

But __visible? That was added via:

  commit 9a55fdbe941e ("x86, asmlinkage, paravirt: Add __visible/asmlinkage to xen paravirt ops")

with a completely empty changelog. Really helpful.

And further down the road it was again LTO "improved":

commit 824a2870098fa536 ("x86, asmlinkage, paravirt: Don't rely on local assembler labels")

with the following changelog in 2013:

    "The paravirt patching code assumes that it can reference a
     local assembler label between two different top level assembler
     statements. This does not work with LTO
     where the assembler code may end up in different assembler files.
    
     Replace it with extern / global /asm linkage labels."
    
This clearly shows that it was never analyzed proper and even the current
patch lacks any form of proper root cause analysis as the "changelog"
clearly shows:

  "With gcc 8 toplevel assembler statements that do not mark themselves
   as .text may end up in other sections. I had boot crashes because
   various assembler statements ended up in the middle of the initcall
   section."

Admittedly it contains at least some information, which is progress over an
empty changelog. But it's clearly NOT a gcc8 problem and it has absolutely
nothing to do with LTO, which the subject suggests.

Is it really necessary, that I need to:

  - urge you to talk with GCC people?

  - ask about whether this needs to be backported?

  - ask whether this is an LTO only problem?

  - do your homework of analysing the root cause?

  - do your homework of analysing the patched code?

  - do your homework of fixing it proper?

And you ask why it takes ages to get your stuff merged? Yes, it takes ages
because patches based on 'works for me' engineering are simply not
acceptable. You have a proven track record of that and I'm trusting you and
your patches not at all. Done that, got burned often enough. Not going to
happen again. It's solely up to you to change that situation.

Proper fix below.

Thanks,

	tglx

8<-------------------

--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -367,11 +367,15 @@ extern struct paravirt_patch_template pv
 	_paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]")
 
 /* Simple instruction patching code. */
-#define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
+#define NATIVE_LABEL(a,x,b) "\n" a #x "_" #b ":\n\t"
 
 #define DEF_NATIVE(ops, name, code)					\
-	__visible extern const char start_##ops##_##name[], end_##ops##_##name[];	\
-	asm(NATIVE_LABEL("start_", ops, name) code NATIVE_LABEL("end_", ops, name))
+	static const char start_##ops##_##name[], end_##ops##_##name[]; \
+	asm(".pushsection .rodata, \"a\"\n"				\
+	    NATIVE_LABEL("start_", ops, name)				\
+	    code							\
+	    NATIVE_LABEL("end_", ops, name)				\
+	    ".popsection\n")
 
 unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len);
 unsigned paravirt_patch_default(u8 type, void *insnbuf,




  parent reply	other threads:[~2019-03-27 14:20 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-21 21:59 Fixes and cleanup from LTO tree Andi Kleen
2019-03-21 21:59 ` [PATCH 01/17] kbuild: Disable -Waddress-of-packed-member for gcc 9 Andi Kleen
2019-03-22 13:58   ` Arnd Bergmann
2019-03-22 16:31     ` Andi Kleen
2019-03-22 16:39     ` Peter Zijlstra
2019-03-22 16:57       ` Arnd Bergmann
2019-03-22 16:58       ` Andi Kleen
2019-03-25 16:27         ` David Laight
2019-04-01  1:04     ` Masahiro Yamada
2019-03-21 21:59 ` [PATCH 02/17] x86, lto: Mark all top level asm statements as .text Andi Kleen
2019-03-26 17:03   ` Thomas Gleixner
2019-03-26 21:38     ` Andi Kleen
2019-03-26 22:25       ` Thomas Gleixner
2019-03-27  0:55         ` Andi Kleen
2019-03-27  1:08           ` Andi Kleen
2019-03-27 14:20           ` Thomas Gleixner [this message]
2019-03-27 14:39             ` Ingo Molnar
2019-03-27 14:59             ` Andi Kleen
2019-03-27 15:08               ` Thomas Gleixner
2019-03-27 15:45                 ` Andi Kleen
2019-03-27 19:08                   ` Thomas Gleixner
2019-03-27 20:40                     ` Andi Kleen
2019-03-27 21:55                       ` Thomas Gleixner
2019-03-27 22:29                         ` Andi Kleen
2019-03-27 22:50                           ` Thomas Gleixner
2019-04-02  8:54                             ` Thomas Gleixner
2019-03-21 21:59 ` [PATCH 03/17] x86: Don't inline __const_udelay Andi Kleen
2019-03-21 21:59 ` [PATCH 04/17] init: Add __noreorder and mark initcalls __noreorder Andi Kleen
2019-03-21 21:59 ` [PATCH 05/17] Use C version for SYSCALL_ALIAS Andi Kleen
2019-03-21 21:59 ` [PATCH 06/17] locking/core: Mark spinlocks noinline when inline spinlocks are disabled Andi Kleen
2019-03-21 21:59 ` [PATCH 07/17] amdkfd: Fix extern declaration Andi Kleen
2019-03-21 22:00 ` [PATCH 08/17] x86/speculation: Fix __initconst in bugs.c Andi Kleen
2019-03-26 17:24   ` Thomas Gleixner
2019-03-21 22:00 ` [PATCH 09/17] x86/kvm: Make steal_time visible Andi Kleen
2019-03-21 22:00 ` [PATCH 10/17] delta: Fix buffer overrun in delta_ipc_open Andi Kleen
2019-04-01 13:37   ` Hugues FRUCHET
2019-04-01 16:54     ` Andi Kleen
2019-04-02  9:56       ` Hugues FRUCHET
2019-03-21 22:00 ` [PATCH 11/17] x86/kprobes: Make trampoline_handler global and visible Andi Kleen
2019-03-23  9:45   ` Masami Hiramatsu
2019-03-23 14:35     ` Andi Kleen
2019-03-25  1:53       ` Masami Hiramatsu
2019-03-21 22:00 ` [PATCH 12/17] afs: Avoid section confusion in CM_NAME Andi Kleen
2019-03-21 22:00 ` [PATCH 13/17] ASoC: AMD: Fix incorrect extern Andi Kleen
2019-03-21 22:00 ` [PATCH 14/17] crypto: Don't mark AES tables const and cacheline_aligned Andi Kleen
2019-03-26  8:42   ` Rasmus Villemoes
2019-03-26 18:30     ` Andi Kleen
2019-03-21 22:00 ` [PATCH 15/17] x86/hyperv: Make hv_vcpu_is_preempted visible Andi Kleen
2019-03-26  8:15   ` Yi Sun
2019-03-21 22:00 ` [PATCH 16/17] x86/xen: Mark xen_vcpu_stolen as __visible Andi Kleen
2019-03-21 22:00 ` [PATCH 17/17] dm: Fix const confusion in dm Andi Kleen
2019-03-22  8:34 ` [PATCH 12/17] afs: Avoid section confusion in CM_NAME David Howells
2019-03-26 17:00 ` Fixes and cleanup from LTO tree Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.DEB.2.21.1903270820530.1789@nanos.tec.linutronix.de \
    --to=tglx@linutronix.de \
    --cc=ak@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi@firstfloor.org \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).