diff mbox

[10/11] x86, rwsem: provide __down_write_killable

Message ID 20160413124943.GH14351@dhcp22.suse.cz (mailing list archive)
State New, archived
Headers show

Commit Message

Michal Hocko April 13, 2016, 12:49 p.m. UTC
On Wed 13-04-16 12:27:31, Ingo Molnar wrote:
> 
> * Ingo Molnar <mingo@kernel.org> wrote:
> 
> > I'm testing your patches today, if they are otherwise OK [...]
> 
> got this build failure:
> 
>   ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints

Hmm, I have no idea why 64b didn't have problem with the asm but 32b
complains. Anyway, the following makes both happy. I have checked the
generated code for 64b and it hasn't changed after the patch. 32b also
seems to be generating a proper code. My gcc asm()-foo is rather weak so
I would feel better if somebody double checked after me.
---
From d23f4e6994670bf2c5d864f2190f21022b4499b2 Mon Sep 17 00:00:00 2001
From: Michal Hocko <mhocko@suse.com>
Date: Wed, 13 Apr 2016 14:21:25 +0200
Subject: [PATCH] x86: __down_read_trylock fix 32b build failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Ingo has noticed the following compilation error with CONFIG_X86_32=y
./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints

The reason seems to be that 32b doesn't like ret being input and output
argument sharing the same register with sem which is only the input. Fix
this by making ret output only and use %3 (aka sem) for xadd.

ret initialization is not needed now because this is done implicitly
by the asm even for the fast path as both sem and ret share the same
register.

Reported-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Michal Hocko <mhocko@suse.com>
---
 arch/x86/include/asm/rwsem.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Michal Hocko April 17, 2016, 4:59 p.m. UTC | #1
On Wed 13-04-16 14:49:43, Michal Hocko wrote:
> On Wed 13-04-16 12:27:31, Ingo Molnar wrote:
> > 
> > * Ingo Molnar <mingo@kernel.org> wrote:
> > 
> > > I'm testing your patches today, if they are otherwise OK [...]
> > 
> > got this build failure:
> > 
> >   ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints
> 
> Hmm, I have no idea why 64b didn't have problem with the asm but 32b
> complains. Anyway, the following makes both happy. I have checked the
> generated code for 64b and it hasn't changed after the patch. 32b also
> seems to be generating a proper code. My gcc asm()-foo is rather weak so
> I would feel better if somebody double checked after me.

Peter, Ingo, does the patch makes sense to you?
Thanks!

> ---
> From d23f4e6994670bf2c5d864f2190f21022b4499b2 Mon Sep 17 00:00:00 2001
> From: Michal Hocko <mhocko@suse.com>
> Date: Wed, 13 Apr 2016 14:21:25 +0200
> Subject: [PATCH] x86: __down_read_trylock fix 32b build failure
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> Ingo has noticed the following compilation error with CONFIG_X86_32=y
> ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints
> 
> The reason seems to be that 32b doesn't like ret being input and output
> argument sharing the same register with sem which is only the input. Fix
> this by making ret output only and use %3 (aka sem) for xadd.
> 
> ret initialization is not needed now because this is done implicitly
> by the asm even for the fast path as both sem and ret share the same
> register.
> 
> Reported-by: Ingo Molnar <mingo@kernel.org>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> ---
>  arch/x86/include/asm/rwsem.h | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h
> index d759c5f70f49..453744c1d347 100644
> --- a/arch/x86/include/asm/rwsem.h
> +++ b/arch/x86/include/asm/rwsem.h
> @@ -102,9 +102,9 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
>  #define ____down_write(sem, slow_path)			\
>  ({							\
>  	long tmp;					\
> -	struct rw_semaphore* ret = sem;			\
> +	struct rw_semaphore* ret;			\
>  	asm volatile("# beginning down_write\n\t"	\
> -		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"	\
> +		     LOCK_PREFIX "  xadd      %1,(%3)\n\t"	\
>  		     /* adds 0xffff0001, returns the old value */ \
>  		     "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \
>  		     /* was the active mask 0 before? */\
> @@ -112,7 +112,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
>  		     "  call " slow_path "\n"		\
>  		     "1:\n"				\
>  		     "# ending down_write"		\
> -		     : "+m" (sem->count), "=d" (tmp), "+a" (ret)	\
> +		     : "+m" (sem->count), "=d" (tmp), "=a" (ret)	\
>  		     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
>  		     : "memory", "cc");			\
>  	ret;						\
> -- 
> 2.8.0.rc3
> 
> -- 
> Michal Hocko
> SUSE Labs
Peter Zijlstra April 20, 2016, 1:40 p.m. UTC | #2
On Wed, Apr 13, 2016 at 02:49:43PM +0200, Michal Hocko wrote:
> On Wed 13-04-16 12:27:31, Ingo Molnar wrote:
> > 
> > * Ingo Molnar <mingo@kernel.org> wrote:
> > 
> > > I'm testing your patches today, if they are otherwise OK [...]
> > 
> > got this build failure:
> > 
> >   ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints
> 
> Hmm, I have no idea why 64b didn't have problem with the asm but 32b
> complains. Anyway, the following makes both happy. I have checked the
> generated code for 64b and it hasn't changed after the patch. 32b also
> seems to be generating a proper code. My gcc asm()-foo is rather weak so
> I would feel better if somebody double checked after me.

I completely blow at this gcc-asm constraints thing too :/

In any case, Ingo will you look after the rest of these patches, or do
you want me to pick up the remaining bits?
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
H. Peter Anvin April 20, 2016, 6:04 p.m. UTC | #3
On April 20, 2016 6:40:19 AM PDT, Peter Zijlstra <peterz@infradead.org> wrote:
>On Wed, Apr 13, 2016 at 02:49:43PM +0200, Michal Hocko wrote:
>> On Wed 13-04-16 12:27:31, Ingo Molnar wrote:
>> > 
>> > * Ingo Molnar <mingo@kernel.org> wrote:
>> > 
>> > > I'm testing your patches today, if they are otherwise OK [...]
>> > 
>> > got this build failure:
>> > 
>> >   ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has
>impossible constraints
>> 
>> Hmm, I have no idea why 64b didn't have problem with the asm but 32b
>> complains. Anyway, the following makes both happy. I have checked the
>> generated code for 64b and it hasn't changed after the patch. 32b
>also
>> seems to be generating a proper code. My gcc asm()-foo is rather weak
>so
>> I would feel better if somebody double checked after me.
>
>I completely blow at this gcc-asm constraints thing too :/
>
>In any case, Ingo will you look after the rest of these patches, or do
>you want me to pick up the remaining bits?

The reason it breaks is because the same register can't be an input-output register and a separate input.  However, the input side of the input-output is probably undefined, and so gcc may not notice.
Borislav Petkov April 20, 2016, 8:45 p.m. UTC | #4
On Wed, Apr 20, 2016 at 11:04:05AM -0700, H. Peter Anvin wrote:
> The reason it breaks is because the same register can't be an
> input-output register and a separate input. However, the input side of
> the input-output is probably undefined, and so gcc may not notice.

So Michal and I talked about this a while ago. Why do we need the '"a"
(sem)' input dependency if '"+a" (ret)' already supplies the same thing?

There's also that "=d" (tmp) thing which we don't really need as an
output, right?

I.e., can we simplify like this?

---
#define ____down_write(sem, slow_path)                  \
({                                                      \
        long tmp = RWSEM_ACTIVE_WRITE_BIAS;             \
	struct rw_semaphore* ret = sem;			\
                                                        \
        asm volatile("# beginning down_write\n\t"       \
                     LOCK_PREFIX "  xadd      %[tmp],(%[ret])\n\t"      \
                     /* adds 0xffff0001, returns the old value */ \
                     "  test " __ASM_SEL(%w[tmp],%k[tmp]) "," __ASM_SEL(%w[tmp],%k[tmp]) "\n\t" \
                     /* was the active mask 0 before? */\
                     "  jz        1f\n"                 \
                     "  call " slow_path "\n"           \
                     "1:\n"                             \
                     "# ending down_write"              \
                     : "+m" (sem->count), [ret] "+a" (ret) \
                     : [tmp] "d" (tmp)                  \
                     : "memory", "cc");                 \
        ret;                                            \
})
Michal Hocko April 20, 2016, 8:58 p.m. UTC | #5
On Wed 20-04-16 22:45:01, Borislav Petkov wrote:
> On Wed, Apr 20, 2016 at 11:04:05AM -0700, H. Peter Anvin wrote:
> > The reason it breaks is because the same register can't be an
> > input-output register and a separate input. However, the input side of
> > the input-output is probably undefined, and so gcc may not notice.
> 
> So Michal and I talked about this a while ago. Why do we need the '"a"
> (sem)' input dependency if '"+a" (ret)' already supplies the same thing?
> 
> There's also that "=d" (tmp) thing which we don't really need as an
> output, right?
> 
> I.e., can we simplify like this?

I am for any simplification, my gcc-asm-foo is just too weak and I
wanted my change to be as minimal as possible. So if you feel you can
clean up this I would more than welcome that. Maybe a follow up patch
would be a better approach so that we can check that the generated code
hasn't changed.

Thanks!
H. Peter Anvin April 20, 2016, 9:06 p.m. UTC | #6
On 04/20/2016 01:45 PM, Borislav Petkov wrote:
> On Wed, Apr 20, 2016 at 11:04:05AM -0700, H. Peter Anvin wrote:
>> The reason it breaks is because the same register can't be an
>> input-output register and a separate input. However, the input side of
>> the input-output is probably undefined, and so gcc may not notice.
> 
> So Michal and I talked about this a while ago. Why do we need the '"a"
> (sem)' input dependency if '"+a" (ret)' already supplies the same thing?
> 

Setting ret to sem doesn't make any sense.  Just use "=a" and "a".

	-hpa


--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Borislav Petkov April 20, 2016, 9:36 p.m. UTC | #7
On Wed, Apr 20, 2016 at 02:06:33PM -0700, H. Peter Anvin wrote:
> Setting ret to sem doesn't make any sense.  Just use "=a" and "a".

Yeah, that's what Michal's patch ontop does.

And to answer my own question: we need the "a" (sem) input for the fast
path.

I guess we can still move "1" (RWSEM_ACTIVE_WRITE_BIAS) before the asm():

	long tmp = RWSEM_ACTIVE_WRITE_BIAS;

One thing I'm still not clear on is why we need the output tmp operand:
"=d" (tmp) ?
H. Peter Anvin April 20, 2016, 10:29 p.m. UTC | #8
On April 20, 2016 2:36:37 PM PDT, Borislav Petkov <bp@alien8.de> wrote:
>On Wed, Apr 20, 2016 at 02:06:33PM -0700, H. Peter Anvin wrote:
>> Setting ret to sem doesn't make any sense.  Just use "=a" and "a".
>
>Yeah, that's what Michal's patch ontop does.
>
>And to answer my own question: we need the "a" (sem) input for the fast
>path.
>
>I guess we can still move "1" (RWSEM_ACTIVE_WRITE_BIAS) before the
>asm():
>
>	long tmp = RWSEM_ACTIVE_WRITE_BIAS;
>
>One thing I'm still not clear on is why we need the output tmp operand:
>"=d" (tmp) ?

Since it is a fixed register we could just mark edx clobbered, but with more flexible register constraints it can permit gcc to allocate a temp resister for us.
Borislav Petkov April 21, 2016, 11:35 a.m. UTC | #9
On Wed, Apr 20, 2016 at 03:29:30PM -0700, H. Peter Anvin wrote:
> Since it is a fixed register we could just mark edx clobbered, but
> with more flexible register constraints it can permit gcc to allocate
> a temp resister for us. --

Right.

I'll try to hack up a cleanup ontop once the dust here settles and Ingo
pushes out the pile.

Thanks.
Michal Hocko April 21, 2016, 1:09 p.m. UTC | #10
On Thu 21-04-16 13:35:16, Borislav Petkov wrote:
> On Wed, Apr 20, 2016 at 03:29:30PM -0700, H. Peter Anvin wrote:
> > Since it is a fixed register we could just mark edx clobbered, but
> > with more flexible register constraints it can permit gcc to allocate
> > a temp resister for us. --
> 
> Right.
> 
> I'll try to hack up a cleanup ontop once the dust here settles and Ingo
> pushes out the pile.

Thanks Boris! This is highly appreciated.
Borislav Petkov April 21, 2016, 1:21 p.m. UTC | #11
On Thu, Apr 21, 2016 at 09:09:11AM -0400, Michal Hocko wrote:
> Thanks Boris! This is highly appreciated.

I know ;-)
Ingo Molnar April 22, 2016, 6:53 a.m. UTC | #12
* Peter Zijlstra <peterz@infradead.org> wrote:

> On Wed, Apr 13, 2016 at 02:49:43PM +0200, Michal Hocko wrote:
> > On Wed 13-04-16 12:27:31, Ingo Molnar wrote:
> > > 
> > > * Ingo Molnar <mingo@kernel.org> wrote:
> > > 
> > > > I'm testing your patches today, if they are otherwise OK [...]
> > > 
> > > got this build failure:
> > > 
> > >   ./arch/x86/include/asm/rwsem.h:106:2: error: ‘asm’ operand has impossible constraints
> > 
> > Hmm, I have no idea why 64b didn't have problem with the asm but 32b
> > complains. Anyway, the following makes both happy. I have checked the
> > generated code for 64b and it hasn't changed after the patch. 32b also
> > seems to be generating a proper code. My gcc asm()-foo is rather weak so
> > I would feel better if somebody double checked after me.
> 
> I completely blow at this gcc-asm constraints thing too :/
> 
> In any case, Ingo will you look after the rest of these patches, or do
> you want me to pick up the remaining bits?

Yeah, it's on my list!

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h
index d759c5f70f49..453744c1d347 100644
--- a/arch/x86/include/asm/rwsem.h
+++ b/arch/x86/include/asm/rwsem.h
@@ -102,9 +102,9 @@  static inline int __down_read_trylock(struct rw_semaphore *sem)
 #define ____down_write(sem, slow_path)			\
 ({							\
 	long tmp;					\
-	struct rw_semaphore* ret = sem;			\
+	struct rw_semaphore* ret;			\
 	asm volatile("# beginning down_write\n\t"	\
-		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"	\
+		     LOCK_PREFIX "  xadd      %1,(%3)\n\t"	\
 		     /* adds 0xffff0001, returns the old value */ \
 		     "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \
 		     /* was the active mask 0 before? */\
@@ -112,7 +112,7 @@  static inline int __down_read_trylock(struct rw_semaphore *sem)
 		     "  call " slow_path "\n"		\
 		     "1:\n"				\
 		     "# ending down_write"		\
-		     : "+m" (sem->count), "=d" (tmp), "+a" (ret)	\
+		     : "+m" (sem->count), "=d" (tmp), "=a" (ret)	\
 		     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
 		     : "memory", "cc");			\
 	ret;						\