linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/RFC 0/7] ACCESS_ONCE and non-scalar accesses
@ 2014-11-24 13:03 Christian Borntraeger
  2014-11-24 13:03 ` [PATCH 1/7] KVM: s390: Fix ipte locking Christian Borntraeger
                   ` (11 more replies)
  0 siblings, 12 replies; 43+ messages in thread
From: Christian Borntraeger @ 2014-11-24 13:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: "linux-arch, Paolo Bonzini, paulmck, mingo, torvalds,
	Catalin Marinas, Will Deacon, Christian Borntraeger

As discussed on LKML http://marc.info/?i=54611D86.4040306%40de.ibm.com
ACCESS_ONCE might fail with specific compiler for non-scalar accesses.

Here is a set of patches to tackle that problem. (The first patch
is already in kvm/next).
The last patch will force ACCESS_ONCE to error-out if it is used
on non-scalar accesses.
I have cross-compiled the resulting kernel with defconfig for
microblaze, m68k, alpha, s390,x86_64, i686, sparc, sparc64, mips,
ia64, arm and arm64.

So hopefully this patch set should be complete regarding the non-scalar
accesses. (As Linus pointed out, accesses > word size are a problem
on its own, but this patch set does not tackle this)

The result is also available as 0d199efcfc9875b8de17bb4fe1d87a27bd39a172
on
git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux.git ACCESS_ONCE

Now:
- It would be good to have the changes reviewed by component experts.
- It would also be good if architecture maintainers could double check, that
  "kernel: Force ACCESS_ONCE to work only on scalar types" does not break
  anything beyond defconfig.
- some comments about cc stable

Thanks

Christian
----------------------------------------------------------------
Christian Borntraeger (7):
      KVM: s390: Fix ipte locking
      mm: replace page table access via ACCESS_ONCE with barriers
      x86: Rework ACCESS_ONCE for spinlock code
      x86: Replace ACCESS_ONCE in gup with a barrier
      mips: Replace ACCESS_ONCE in gup with a barrier
      arm64: Replace ACCESS_ONCE for spinlock code with barriers
      kernel: Force ACCESS_ONCE to work only on scalar types

 arch/arm64/include/asm/spinlock.h |  7 +++++--
 arch/mips/mm/gup.c                |  6 ++++--
 arch/s390/kvm/gaccess.c           | 20 ++++++++++++++------
 arch/x86/include/asm/spinlock.h   | 14 +++++++++-----
 arch/x86/mm/gup.c                 |  7 +++++--
 include/linux/compiler.h          | 12 +++++++++++-
 mm/gup.c                          |  4 +++-
 mm/memory.c                       |  3 ++-
 mm/rmap.c                         |  3 ++-
 9 files changed, 55 insertions(+), 21 deletions(-)


^ permalink raw reply	[flat|nested] 43+ messages in thread
* Re: [PATCH/RFC 7/7] kernel: Force ACCESS_ONCE to work only on scalar types
@ 2014-11-24 20:29 Alexei Starovoitov
  2014-11-24 20:45 ` Christian Borntraeger
  2014-11-24 20:48 ` Paul E. McKenney
  0 siblings, 2 replies; 43+ messages in thread
From: Alexei Starovoitov @ 2014-11-24 20:29 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Linus Torvalds, David Howells, linux-kernel@vger.kernel.org,
	linux-arch@vger.kernel.org, linux-mips, linux-x86_64, linux-s390,
	Paolo Bonzini, Paul McKenney, Ingo Molnar, Catalin Marinas,
	Will Deacon

On Mon, Nov 24, 2014 at 11:07 AM, Christian Borntraeger
<borntraeger@de.ibm.com> wrote:
>
> Anyone with a new propopal? ;-)                                        ^

one more proposal :)
#define __ACCESS_ONCE(x) ({ typeof(x) __var = 0; (volatile typeof(x) *)&(x); })
#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x))

works as lvalue...
the basic idea is the same:
constant zero can be used to initialize any scalar
(including pointers), but unions and structs will fail to compile as:
"error: invalid initializer"

If I'm reading pr58145 gcc bug report correctly, it
miscompiles only structs, so we can let ACCESS_ONCE
to work on unions. Then the following will rejects structs only:
#define __ACCESS_ONCE(x) ({ (typeof(x))0; (volatile typeof(x) *)&(x); })
#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x))

^ permalink raw reply	[flat|nested] 43+ messages in thread
* Re: [PATCH/RFC 7/7] kernel: Force ACCESS_ONCE to work only on scalar types
@ 2014-11-24 22:58 Alexei Starovoitov
  2014-11-24 22:58 ` Alexei Starovoitov
  2014-11-25  0:00 ` Linus Torvalds
  0 siblings, 2 replies; 43+ messages in thread
From: Alexei Starovoitov @ 2014-11-24 22:58 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: David Howells, Christian Borntraeger,
	linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
	linux-mips, linux-x86_64, linux-s390, Paolo Bonzini,
	Paul McKenney, Ingo Molnar, Catalin Marinas, Will Deacon

On Mon, Nov 24, 2014 at 12:34 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Mon, Nov 24, 2014 at 12:04 PM, David Howells <dhowells@redhat.com> wrote:
>>
>> Reserve ACCESS_ONCE() for reading and add an ASSIGN_ONCE() or something like
>> that for writing?
>
> I wouldn't mind that. We've had situations where reading and writing
> isn't really similar - like alpha where reading a byte is atomic, but
> writing one isn't.
>
> Then we could also make it have the "get_user()/put_user()" kind of
> semantics - .and then use the same "sizeopf()" tricks that we use for
> get_user/put_user.
>
> That would actually work around the gcc bug a completely different way:
>
>   #define ACCESS_ONCE(p) \
>       ({ typeof(*p) __val; __read_once_size(p, &__val, sizeof(__val)); __val; })
>
> and then we can do things like this:
>
>   static __always_inline void __read_once_size(volatile void *p, void
> *res, int size)
>   {
>        switch (size) {
>        case 1: *(u8 *)res = *(volatile u8 *)p; break;
>        case 2: *(u16 *)res = *(volatile u16 *)p; break;
>        case 4: *(u32 *)res = *(volatile u32 *)p; break;
> #ifdef CONFIG_64BIT
>        case 8: *(u64 *)res = *(volatile u64 *)p; break;
> #endif
>        }
>   }
>
> and same for ASSIGN_ONCE(val, p).
>
> That also hopefully avoids the whole "oops, gcc has a bug", because
> the actual volatile access is always done using a scalar type, even if
> the type of "__val" may in fact be a structure.

I've changed gcc pr58145-1.c reproducer to use
__read_once_size() approach above, but it
didn't help to workaround the bug.
gcc 'sra' pass still lost 'volatile' modifier.

modified reproducer:
struct S { unsigned int data; };
void bar(int val)
{
  struct S _s = { .data = val };
  *(volatile struct S *) 0x880000UL = ACCESS_ONCE(&_s);
}
assembler code looks as expected, but
internal gcc state after 'sra' pass is
missing volatile...

^ permalink raw reply	[flat|nested] 43+ messages in thread
* Re: [PATCH/RFC 7/7] kernel: Force ACCESS_ONCE to work only on scalar types
@ 2014-11-25  2:28 Alexei Starovoitov
  0 siblings, 0 replies; 43+ messages in thread
From: Alexei Starovoitov @ 2014-11-25  2:28 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: David Howells, Christian Borntraeger,
	linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
	linux-mips, linux-x86_64, linux-s390, Paolo Bonzini,
	Paul McKenney, Ingo Molnar, Catalin Marinas, Will Deacon

On Mon, Nov 24, 2014 at 4:00 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Mon, Nov 24, 2014 at 2:58 PM, Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
>>
>> I've changed gcc pr58145-1.c reproducer to use
>> __read_once_size() approach above
>
> I don't think you did.
>
>> modified reproducer:
>> struct S { unsigned int data; };
>> void bar(int val)
>> {
>>   struct S _s = { .data = val };
>>   *(volatile struct S *) 0x880000UL = ACCESS_ONCE(&_s);
>> }
>
> My approach never had "volatile struct S *". The only volatile
> pointers were the actual byte/word/etc pointers, and those generated

you're right. In my invalid snippet above the ACCESS_ONCE
to struct on stack gets optimized away and only 'volatile struct *'
in left hand side is triggering the bug.

Have tried the following which blends your proposal
with original code from Christian:
/* bad
#define ACCESS_ONCE(x) *((volatile typeof(x) *)&(x))
*/

/* good */
#define ACCESS_ONCE(p) \
      ({ typeof(*p) __val; __read_once_size(p, &__val, sizeof(__val)); __val; })

static __always_inline void __read_once_size(volatile void *p, void
*res, int size)
{
     switch (size) {
     case 1: *(u8 *)res = *(volatile u8 *)p; break;
     case 2: *(u16 *)res = *(volatile u16 *)p; break;
     case 4: *(u32 *)res = *(volatile u32 *)p; break;
     case 8: *(u64 *)res = *(volatile u64 *)p; break;
     }
}

union ipte_control {
        unsigned long val;
        struct {
                unsigned long k  : 1;
                unsigned long kh : 31;
                unsigned long kg : 32;
        };
};

struct kvm_vcpu {
        union ipte_control ic;
};

void ipte_unlock_siif(struct kvm_vcpu *vcpu)
{
        union ipte_control old, new, *ic;

        ic = &vcpu->ic;
        do {
                new = old = ACCESS_ONCE(ic);
                new.kh--;
                if (!new.kh)
                        new.k = 0;
        } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
}

generated code looks correct with and without strict-aliasing
and volatile marking is preserved properly.
(to check for volatile marks add -fdump-tree-optimized
 and look for {v} in *.optimized)

> Pretty? No. But then, the standard C aliasing rules are so broken that
> "pretty" doesn't really come into play..

Agree. I don't see any warnings or code generation issues with and
without strict-aliasing with your original __read_once_size(), so no need
to play union tricks. Initially I was worried that extra always_inline
function will make generated code worse in critical paths where
ACCESS_ONCE is used, but after looking close enough, it seems
all should be fine.

Note, with unmodified ACCESS_ONCE all architectures (even x64)
are missing volatile markings with gcc 4.6.3, 4.7.2 for Christian's
use case.

^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2014-11-25  2:28 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-24 13:03 [PATCH/RFC 0/7] ACCESS_ONCE and non-scalar accesses Christian Borntraeger
2014-11-24 13:03 ` [PATCH 1/7] KVM: s390: Fix ipte locking Christian Borntraeger
2014-11-24 13:03 ` Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 2/7] mm: replace page table access via ACCESS_ONCE with barriers Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 3/7] x86: Rework ACCESS_ONCE for spinlock code Christian Borntraeger
2014-11-24 13:03 ` Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 4/7] x86: Replace ACCESS_ONCE in gup with a barrier Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 5/7] mips: " Christian Borntraeger
2014-11-24 13:03 ` Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 6/7] arm64: Replace ACCESS_ONCE for spinlock code with barriers Christian Borntraeger
2014-11-24 13:03 ` Christian Borntraeger
2014-11-24 18:50   ` Christian Borntraeger
2014-11-24 18:50     ` Christian Borntraeger
2014-11-24 13:03 ` [PATCH/RFC 7/7] kernel: Force ACCESS_ONCE to work only on scalar types Christian Borntraeger
2014-11-24 13:30 ` David Howells
2014-11-24 17:30   ` Linus Torvalds
2014-11-24 18:02   ` Alexei Starovoitov
2014-11-24 18:02     ` Alexei Starovoitov
2014-11-24 18:35     ` Linus Torvalds
2014-11-24 18:35       ` Linus Torvalds
2014-11-24 19:07       ` Christian Borntraeger
2014-11-24 19:07         ` Christian Borntraeger
2014-11-24 19:14         ` Linus Torvalds
2014-11-24 19:42           ` Paul E. McKenney
2014-11-24 20:19             ` Linus Torvalds
2014-11-24 20:46               ` Paul E. McKenney
2014-11-24 20:28             ` Christian Borntraeger
2014-11-24 20:28               ` Christian Borntraeger
2014-11-24 20:04       ` David Howells
2014-11-24 20:34         ` Linus Torvalds
2014-11-24 20:34           ` Linus Torvalds
2014-11-24 20:53           ` Christian Borntraeger
2014-11-24 21:02             ` Linus Torvalds
2014-11-24 21:16               ` Christian Borntraeger
2014-11-24 21:16                 ` Christian Borntraeger
  -- strict thread matches above, loose matches on Subject: below --
2014-11-24 20:29 Alexei Starovoitov
2014-11-24 20:45 ` Christian Borntraeger
2014-11-24 20:45   ` Christian Borntraeger
2014-11-24 20:48 ` Paul E. McKenney
2014-11-24 22:58 Alexei Starovoitov
2014-11-24 22:58 ` Alexei Starovoitov
2014-11-25  0:00 ` Linus Torvalds
2014-11-25  2:28 Alexei Starovoitov

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).