On Wed, Jan 16, 2019 at 10:59 AM Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> wrote: > *) I've always considered __noderef as really meaning "must not be > dereferenced except by some special purpose operation which > effectively do the real deref". In the present case (percpu & > uaccess (on x86)), it's clear that the special operation is > the asm memory op but isn't this essentially incidental? I agree that it's somewhat incidental rather than anything hugely by design. That said, the *design* of __noderef was literally to make sure that the *compiler* never derefences things, and the "special thing" that does dereference was literally meant to be an inline asm. The "{get,put}_user()" case was exactly what __noderef was designed for. So it *is* very much by design, but then the implementation not *checking* inline asm arguments was kind of an incidental thing. Which is why I very much admit that it's annoying. The good news is that the asm constraints aren't really all that architecture-specific. Yes, all the various register classes etc obviously are, but within the concept of "the compiler never dereferences it", the only asm constraints that matter are "m" and "p", I think. "m" means "memory", and "p" means "address". They are kind of the same, except for a gcc memory access ordering situation, I think. > Thinking a bit more about it and looking at some dumps I made: > It seems that most of these these 'noderef in asm operand' > warnings (99.5%) come from percpu operations (which have an API > using an lvalue and not a pointer, unlike the uaccess API). > > I begin to suspect that the warnings occuring with an uaccess > operation come from some other kind of error (possibly a missing > call to degenerate()). Hmm. The uaccess cases definitely pass the lvalue in some cases. Not the cases where we just end up doing a special "call" sequence (the normal get_user/put_user() case). But look closer: the cases where we actaully inline the access itself, we generate a "LKmode" lvalue with that "__m(addr)" thing, and the actual access is done by the inline asm. See __get_user_asm(), __get_user_asm_nozero(), __get_user_asm_ex() and __put_user_goto(). (Some of this has changed recently, so __put_user_goto() is a new version of __put_user_asm(), so if you don't look at current kernel -git, that's what you'll see instead). Linus