From: nicolas.ferre@atmel.com (Nicolas Ferre)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] AT91: pm: make sure that r0 is 0 when dealing with cache operations
Date: Mon, 25 Oct 2010 11:56:37 +0200 [thread overview]
Message-ID: <4CC55455.5060308@atmel.com> (raw)
In-Reply-To: <20101022164247.GB29119@n2100.arm.linux.org.uk>
Hi Russell,
Le 22/10/2010 18:42, Russell King - ARM Linux :
> On Fri, Oct 22, 2010 at 07:29:00PM +0200, Nicolas Ferre wrote:
>> When using CP15 cache operations (c7), we make sure that Rd (r0)
>> is actually 0 as ARM 926 TRM is saying.
>
> Err, no. From the GCC manual:
>
> | Note that even a volatile `asm' instruction can be moved in ways
> | that appear insignificant to the compiler, such as across jump
> | instructions. You can't expect a sequence of volatile `asm'
> | instructions to remain perfectly consecutive. If you want consecutive
> | output, use a single `asm'. Also, GCC will perform some optimizations
> | across a volatile `asm' instruction; GCC does not "forget everything"
> | when it encounters a volatile `asm' instruction the way some other
> | compilers do.
>
> So:
>
> asm volatile("foo");
> asm volatile("bar");
>
> is not guaranteed to produce the following uninterrupted code sequence:
>
> foo
> bar
>
> The compiler is free to insert other instructions inbetween these two
> asm statements.
>
> It's also not permitted to modify registers without telling gcc that
> they've been modified.
>
>> + asm("mov r0, #0"); /* clear r0 for CP15 accesses */
>> asm("b 1f; .align 5; 1:");
>> asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
>
> That means the above is completely unacceptable. It should be:
>
> asm("mov r0, #0;"
> "b 1f;"
> ".align 5;"
> "1: mcr p15, 0, r0, c7, c10, 4" : : : "r0");
Thanks a lot for your detailed explanation.
I modify my patch according to your comments:
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -261,8 +261,13 @@ static int at91_pm_enter(suspend_state_t state)
* For ARM 926 based chips, this requirement is weaker
* as at91sam9 can access a RAM in self-refresh mode.
*/
- asm("b 1f; .align 5; 1:");
- asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+ asm volatile ( "mov r0, #0\n\t"
+ "b 1f\n\t"
+ ".align 5\n\t"
+ "1: mcr p15, 0, r0, c7, c10, 4\n\t"
+ : /* no output */
+ : /* no input */
+ : "r0");
saved_lpr = sdram_selfrefresh_enable();
wait_for_interrupt_enable();
sdram_selfrefresh_disable(saved_lpr);
>> --- a/arch/arm/mach-at91/pm.h
>> +++ b/arch/arm/mach-at91/pm.h
>> @@ -21,7 +21,7 @@ static inline u32 sdram_selfrefresh_enable(void)
>> }
>>
>> #define sdram_selfrefresh_disable(saved_lpr) at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
>> -#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4")
>> +#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4") /* r0 is 0 here */
>
> No, r0 is not guaranteed to be zero here. Use dsb() here instead which
> gets it right.
In fact it is Wait For Interrupt and not dsb... but anyway you are right: I modify it like this:
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,7 +21,8 @@ static inline u32 sdram_selfrefresh_enable(void)
}
#define sdram_selfrefresh_disable(saved_lpr) at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
-#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4")
+#define wait_for_interrupt_enable() asm volatile ("mcr p15, 0, %0, c7, c0, 4" \
+ : : "r" (0))
#elif defined(CONFIG_ARCH_AT91CAP9)
#include <mach/at91cap9_ddrsdr.h>
I repost this modified patch now...
Bye,
--
Nicolas Ferre
WARNING: multiple messages have this Message-ID (diff)
From: Nicolas Ferre <nicolas.ferre@atmel.com>
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, avictor.za@gmail.com,
plagnioj@jcrosoft.com
Subject: Re: [PATCH 2/2] AT91: pm: make sure that r0 is 0 when dealing with cache operations
Date: Mon, 25 Oct 2010 11:56:37 +0200 [thread overview]
Message-ID: <4CC55455.5060308@atmel.com> (raw)
In-Reply-To: <20101022164247.GB29119@n2100.arm.linux.org.uk>
Hi Russell,
Le 22/10/2010 18:42, Russell King - ARM Linux :
> On Fri, Oct 22, 2010 at 07:29:00PM +0200, Nicolas Ferre wrote:
>> When using CP15 cache operations (c7), we make sure that Rd (r0)
>> is actually 0 as ARM 926 TRM is saying.
>
> Err, no. From the GCC manual:
>
> | Note that even a volatile `asm' instruction can be moved in ways
> | that appear insignificant to the compiler, such as across jump
> | instructions. You can't expect a sequence of volatile `asm'
> | instructions to remain perfectly consecutive. If you want consecutive
> | output, use a single `asm'. Also, GCC will perform some optimizations
> | across a volatile `asm' instruction; GCC does not "forget everything"
> | when it encounters a volatile `asm' instruction the way some other
> | compilers do.
>
> So:
>
> asm volatile("foo");
> asm volatile("bar");
>
> is not guaranteed to produce the following uninterrupted code sequence:
>
> foo
> bar
>
> The compiler is free to insert other instructions inbetween these two
> asm statements.
>
> It's also not permitted to modify registers without telling gcc that
> they've been modified.
>
>> + asm("mov r0, #0"); /* clear r0 for CP15 accesses */
>> asm("b 1f; .align 5; 1:");
>> asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
>
> That means the above is completely unacceptable. It should be:
>
> asm("mov r0, #0;"
> "b 1f;"
> ".align 5;"
> "1: mcr p15, 0, r0, c7, c10, 4" : : : "r0");
Thanks a lot for your detailed explanation.
I modify my patch according to your comments:
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -261,8 +261,13 @@ static int at91_pm_enter(suspend_state_t state)
* For ARM 926 based chips, this requirement is weaker
* as at91sam9 can access a RAM in self-refresh mode.
*/
- asm("b 1f; .align 5; 1:");
- asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+ asm volatile ( "mov r0, #0\n\t"
+ "b 1f\n\t"
+ ".align 5\n\t"
+ "1: mcr p15, 0, r0, c7, c10, 4\n\t"
+ : /* no output */
+ : /* no input */
+ : "r0");
saved_lpr = sdram_selfrefresh_enable();
wait_for_interrupt_enable();
sdram_selfrefresh_disable(saved_lpr);
>> --- a/arch/arm/mach-at91/pm.h
>> +++ b/arch/arm/mach-at91/pm.h
>> @@ -21,7 +21,7 @@ static inline u32 sdram_selfrefresh_enable(void)
>> }
>>
>> #define sdram_selfrefresh_disable(saved_lpr) at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
>> -#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4")
>> +#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4") /* r0 is 0 here */
>
> No, r0 is not guaranteed to be zero here. Use dsb() here instead which
> gets it right.
In fact it is Wait For Interrupt and not dsb... but anyway you are right: I modify it like this:
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,7 +21,8 @@ static inline u32 sdram_selfrefresh_enable(void)
}
#define sdram_selfrefresh_disable(saved_lpr) at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
-#define wait_for_interrupt_enable() asm("mcr p15, 0, r0, c7, c0, 4")
+#define wait_for_interrupt_enable() asm volatile ("mcr p15, 0, %0, c7, c0, 4" \
+ : : "r" (0))
#elif defined(CONFIG_ARCH_AT91CAP9)
#include <mach/at91cap9_ddrsdr.h>
I repost this modified patch now...
Bye,
--
Nicolas Ferre
next prev parent reply other threads:[~2010-10-25 9:56 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-22 17:28 [PATCH 1/2] AT91: pm: use plain cpu_do_idle() for "wait for interrupt" Nicolas Ferre
2010-10-22 17:28 ` Nicolas Ferre
2010-10-22 17:28 ` [PATCH v3] at91/atmel-mci: inclusion of sd/mmc driver in at91sam9g45 chip and board Nicolas Ferre
2010-10-22 17:28 ` Nicolas Ferre
2010-10-22 17:29 ` [PATCH 2/2] AT91: pm: make sure that r0 is 0 when dealing with cache operations Nicolas Ferre
2010-10-22 17:29 ` Nicolas Ferre
2010-10-22 16:42 ` Russell King - ARM Linux
2010-10-22 16:42 ` Russell King - ARM Linux
2010-10-25 9:56 ` Nicolas Ferre [this message]
2010-10-25 9:56 ` Nicolas Ferre
2010-10-25 11:09 ` [PATCH 2/2 v2] " Nicolas Ferre
2010-10-25 11:09 ` Nicolas Ferre
2010-10-22 17:29 ` [PATCH] AT91: rtc: enable built-in RTC in Kconfig for at91sam9g45 family Nicolas Ferre
2010-10-22 17:29 ` Nicolas Ferre
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=4CC55455.5060308@atmel.com \
--to=nicolas.ferre@atmel.com \
--cc=linux-arm-kernel@lists.infradead.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.