[PATCH 1/3] hvc_dcc: Fix bad code generation by marking assembly volatile

Nicolas Pitre nico at fluxnic.net
Mon Dec 20 16:39:10 EST 2010


On Mon, 20 Dec 2010, Stephen Boyd wrote:

> Without marking the asm __dcc_getstatus() volatile my compiler
> decides it can cache the value of __ret in a register and then
> check the value of it continually in hvc_dcc_put_chars() (I had
> to replace get_wait/put_wait with 1 and fixup the branch
> otherwise my disassembler barfed on __dcc_(get|put)char).
> 
> 00000000 <hvc_dcc_put_chars>:
>    0:   ee103e11        mrc     14, 0, r3, cr0, cr1, {0}
>    4:   e3a0c000        mov     ip, #0  ; 0x0
>    8:   e2033202        and     r3, r3, #536870912      ; 0x20000000
>    c:   ea000006        b       2c <hvc_dcc_put_chars+0x2c>
>   10:   e3530000        cmp     r3, #0  ; 0x0
>   14:   1afffffd        bne     10 <hvc_dcc_put_chars+0x10>
>   18:   e7d1000c        ldrb    r0, [r1, ip]
>   1c:   ee10fe11        mrc     14, 0, pc, cr0, cr1, {0}
>   20:   2afffffd        bcs     1c <hvc_dcc_put_chars+0x1c>
>   24:   ee000e15        mcr     14, 0, r0, cr0, cr5, {0}
>   28:   e28cc001        add     ip, ip, #1      ; 0x1
>   2c:   e15c0002        cmp     ip, r2
>   30:   bafffff6        blt     10 <hvc_dcc_put_chars+0x10>
>   34:   e1a00002        mov     r0, r2
>   38:   e12fff1e        bx      lr
> 
> As you can see, the value of the mrc is checked against
> DCC_STATUS_TX (bit 29) and then stored in r3 for later use.
> Marking the asm volatile produces the following:
> 
> 00000000 <hvc_dcc_put_chars>:
>    0:   e3a03000        mov     r3, #0  ; 0x0
>    4:   ea000007        b       28 <hvc_dcc_put_chars+0x28>
>    8:   ee100e11        mrc     14, 0, r0, cr0, cr1, {0}
>    c:   e3100202        tst     r0, #536870912  ; 0x20000000
>   10:   1afffffc        bne     8 <hvc_dcc_put_chars+0x8>
>   14:   e7d10003        ldrb    r0, [r1, r3]
>   18:   ee10fe11        mrc     14, 0, pc, cr0, cr1, {0}
>   1c:   2afffffd        bcs     18 <hvc_dcc_put_chars+0x18>
>   20:   ee000e15        mcr     14, 0, r0, cr0, cr5, {0}
>   24:   e2833001        add     r3, r3, #1      ; 0x1
>   28:   e1530002        cmp     r3, r2
>   2c:   bafffff5        blt     8 <hvc_dcc_put_chars+0x8>
>   30:   e1a00002        mov     r0, r2
>   34:   e12fff1e        bx      lr
> 
> which looks better and actually works. Mark all the inline
> assembly in this file as volatile since we don't want the
> compiler to optimize away these statements or move them around
> in any way.
> 
> Cc: Tony Lindgren <tony at atomide.com>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Nicolas Pitre <nicolas.pitre at linaro.org>
> Cc: Daniel Walker <dwalker at codeaurora.org>
> Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>

Acked-by: Nicolas Pitre <nicolas.pitre at linaro.org>


> ---
>  drivers/char/hvc_dcc.c |   11 +++++------
>  1 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/char/hvc_dcc.c b/drivers/char/hvc_dcc.c
> index 6470f63..155ec10 100644
> --- a/drivers/char/hvc_dcc.c
> +++ b/drivers/char/hvc_dcc.c
> @@ -33,8 +33,7 @@
>  static inline u32 __dcc_getstatus(void)
>  {
>  	u32 __ret;
> -
> -	asm("mrc p14, 0, %0, c0, c1, 0	@ read comms ctrl reg"
> +	asm volatile("mrc p14, 0, %0, c0, c1, 0	@ read comms ctrl reg"
>  		: "=r" (__ret) : : "cc");
>  
>  	return __ret;
> @@ -46,7 +45,7 @@ static inline char __dcc_getchar(void)
>  {
>  	char __c;
>  
> -	asm("get_wait:	mrc p14, 0, pc, c0, c1, 0                          \n\
> +	asm volatile("get_wait:	mrc p14, 0, pc, c0, c1, 0                  \n\
>  			bne get_wait                                       \n\
>  			mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
>  		: "=r" (__c) : : "cc");
> @@ -58,7 +57,7 @@ static inline char __dcc_getchar(void)
>  {
>  	char __c;
>  
> -	asm("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
> +	asm volatile("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
>  		: "=r" (__c));
>  
>  	return __c;
> @@ -68,7 +67,7 @@ static inline char __dcc_getchar(void)
>  #if defined(CONFIG_CPU_V7)
>  static inline void __dcc_putchar(char c)
>  {
> -	asm("put_wait:	mrc p14, 0, pc, c0, c1, 0                 \n\
> +	asm volatile("put_wait:	mrc p14, 0, pc, c0, c1, 0         \n\
>  			bcs put_wait                              \n\
>  			mcr p14, 0, %0, c0, c5, 0                   "
>  	: : "r" (c) : "cc");
> @@ -76,7 +75,7 @@ static inline void __dcc_putchar(char c)
>  #else
>  static inline void __dcc_putchar(char c)
>  {
> -	asm("mcr p14, 0, %0, c0, c5, 0	@ write a char"
> +	asm volatile("mcr p14, 0, %0, c0, c5, 0	@ write a char"
>  		: /* no output register */
>  		: "r" (c));
>  }
> -- 
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
> 



More information about the linux-arm-kernel mailing list