public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: kernel test robot <lkp@intel.com>,
	oe-kbuild-all@lists.linux.dev, linux-kernel@vger.kernel.org,
	Arjan van de Ven <arjan@linux.intel.com>,
	x86@kernel.org, Luc Van Oostenryck <luc.vanoostenryck@gmail.com>,
	Sparse Mailing-list <linux-sparse@vger.kernel.org>,
	Uros Bizjak <ubizjak@gmail.com>
Subject: Re: arch/x86/include/asm/processor.h:698:16: sparse: sparse: incorrect type in initializer (different address spaces)
Date: Sun, 03 Mar 2024 17:31:21 +0100	[thread overview]
Message-ID: <87edcruvja.ffs@tglx> (raw)
In-Reply-To: <CAHk-=wiWhfdc4Sw2VBq_2nL2NDxmZS32xG4P7mBVwABGqUoJnw@mail.gmail.com>

On Sat, Mar 02 2024 at 14:49, Linus Torvalds wrote:
> On Sat, 2 Mar 2024 at 14:00, Thomas Gleixner <tglx@linutronix.de> wrote:
>>
>> I had commented out both. But the real reason is the EXPORT_SYMBOL,
>> which obviously wants to be EXPORT_PER_CPU_SYMBOL_GPL...
>
> Side note: while it's nice to hear that sparse kind of got this right,
> I wonder what gcc does when we start using the named address spaces
> for percpu variables.
>
> We actively make EXPORT_PER_CPU_SYMBOL_XYZ be a no-op for sparse
> exactly because sparse ended up warning about the regular
> EXPORT_SYMBOL, and we didn't have any "real" per-cpu export model.

Right.

> So EXPORT_PER_CPU_SYMBOL_GPL() is kind of an artificial "shut up
> sparse".

Aside of that it's also making it clear what this is about. So I don't
think it's purely artifical.

> But with __seg_gs/fs support for native percpu symbols with
> gcc, I wonder if we'll hit the same thing. Or is there something that
> makes gcc not warn about the named address spaces?

Right now the pending code in tip does not complain about the
EXPORT_PER_CPU_SYMBOL_GPL() part because our current macro maze is
hideous. Here is the preprocessor output.

This is DECLARE_PER_CPU() in the header:

extern __attribute__((section(".data..percpu" ""))) __typeof__(u64) x86_spec_ctrl_current;

Here is DEFINE_PER_CPU():

__attribute__((section(".data..percpu" ""))) __typeof__(u64) x86_spec_ctrl_current;

And the EXPORT:

extern typeof(x86_spec_ctrl_current) x86_spec_ctrl_current;

static void * __attribute__((__used__))
   __attribute__((__section__(".discard.addressable")))
   __UNIQUE_ID___addressable_x86_spec_ctrl_current804 = (void *)(uintptr_t)&x86_spec_ctrl_current;

   asm(".section \".export_symbol\",\"a\" ;
       __export_symbol_x86_spec_ctrl_current: ;
       .asciz \"GPL\" ; .asciz \"\" ; .balign 8 ; .quad x86_spec_ctrl_current ; .previous");

And the __seg_gs magic happens only in the per CPU accessor itself:

__attribute__((__noinline__)) __attribute__((no_instrument_function))
 __attribute((__section__(".noinstr.text")))
 __attribute__((__no_sanitize_address__))
 __attribute__((__no_profile_instrument_function__))
 u64 spec_ctrl_current(void)
{
 return ({
    // this_cpu_read(x86_spec_ctrl_current)

    typeof(x86_spec_ctrl_current) pscr_ret__;

    do { const void *__vpp_verify = (typeof((&(x86_spec_ctrl_current)) + 0))((void *)0); (void)__vpp_verify;
    } while (0);

    switch(sizeof(x86_spec_ctrl_current))
    {
    case 1: pscr_ret__ = ({
            *(volatile typeof(x86_spec_ctrl_current) __seg_gs *)(typeof(*&(x86_spec_ctrl_current)) __seg_gs *)(uintptr_t)(&(x86_spec_ctrl_current)); });
            break;
    case 2: pscr_ret__ = ({
            *(volatile typeof(x86_spec_ctrl_current) __seg_gs *)(typeof(*&(x86_spec_ctrl_current)) __seg_gs *)(uintptr_t)(&(x86_spec_ctrl_current)); });
            break;
    case 4: pscr_ret__ = ({
            *(volatile typeof(x86_spec_ctrl_current) __seg_gs *)(typeof(*&(x86_spec_ctrl_current)) __seg_gs *)(uintptr_t)(&(x86_spec_ctrl_current)); });
            break;
    case 8: pscr_ret__ = ({
            *(volatile typeof(x86_spec_ctrl_current) __seg_gs *)(typeof(*&(x86_spec_ctrl_current)) __seg_gs *)(uintptr_t)(&(x86_spec_ctrl_current)); });
            break;

    default: __bad_size_call_parameter(); break;
    }

    pscr_ret__;
  });
}

So all the export etc. just works because it all operates on a plain
data type and the __seg_gs is only bolted on via type casts in the
accessors.

As the per cpu variables are in the .data..percpu section the linker
puts them at address 0 and upwards. So the cast to a __seg_gs pointer
makes it end up at the real kernel address because of GSBASE + "offset".

The compiler converts this to RIP relative addressing:

  movq   $0x0,%gs:0x7e14169f(%rip)        # 1ba08 <fpu_fpregs_owner_ctx>

This obviously has a downside. If I do:

   u64 foo;

   this_cpu_read(foo);

the compiler is just happy to build that w/o complaining and it will
only explode at runtime because foo is a kernel data address which added
to GSBASE will result in accessing some random address:

  mov    %gs:0x15d08d4(%rip),%rax        # ffffffff834aac60 <x86_spec_ctrl_base>

This is not at all different from the inline ASM based version which is
in your tree. The only difference is that the macro maze is pure C and
the __set_gs cast allows the compiler to (micro) optimize, e.g. 'mov
%gs:...; movzbl' into a single 'movzbl'.

IOW, right now the only defense against such a mistake is actually the
sparse check. Maybe one of the coccinelle scripts has something similar,
I don't know.

I did not follow the __set_gs work closely, so I don't know whether Uros
ever tried to actually mark the per CPU variable __set_gs right away,
which would obviously catch the above 'foo' nonsense.

I think this should just work, but that would obviously require to do
the type cast magic at the EXPORT_SYMBOL side and in some other places.

Thanks,

        tglx



  reply	other threads:[~2024-03-03 16:31 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-01 20:12 arch/x86/include/asm/processor.h:698:16: sparse: sparse: incorrect type in initializer (different address spaces) kernel test robot
2024-03-01 21:57 ` Thomas Gleixner
2024-03-01 22:26   ` Thomas Gleixner
2024-03-02  9:43     ` Philip Li
2024-03-02 11:37     ` Thomas Gleixner
2024-03-02 15:44       ` Thomas Gleixner
2024-03-02 22:00         ` Thomas Gleixner
2024-03-02 22:49           ` Linus Torvalds
2024-03-03 16:31             ` Thomas Gleixner [this message]
2024-03-03 19:03               ` Uros Bizjak
2024-03-03 20:10                 ` Thomas Gleixner
2024-03-03 20:21                   ` Uros Bizjak
2024-03-03 20:24                     ` Uros Bizjak
2024-03-03 21:19                       ` Uros Bizjak
2024-03-03 23:49                       ` Thomas Gleixner
2024-03-04  5:42                         ` Uros Bizjak
2024-03-04  7:07                           ` Thomas Gleixner
2024-04-02 11:43                             ` Uros Bizjak
2024-04-03 17:57                               ` Nathan Chancellor
2024-04-04  6:56                                 ` Uros Bizjak
2024-04-29 21:30                         ` [RFC PATCH] Use x86 named address spaces to catch "sparse: incorrect type in initializer (different address spaces)" __percpu errors Uros Bizjak
2024-03-02 12:53 ` arch/x86/include/asm/processor.h:698:16: sparse: sparse: incorrect type in initializer (different address spaces) Yujie Liu
  -- strict thread matches above, loose matches on Subject: below --
2024-01-09 20:00 kernel test robot

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=87edcruvja.ffs@tglx \
    --to=tglx@linutronix.de \
    --cc=arjan@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=lkp@intel.com \
    --cc=luc.vanoostenryck@gmail.com \
    --cc=oe-kbuild-all@lists.linux.dev \
    --cc=torvalds@linux-foundation.org \
    --cc=ubizjak@gmail.com \
    --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