The arm1176jzfs documentation describing the armv6 CP15 Data Memory Barrier operation seems to specify the register value written to the coprocessor as "SBZ" ie Should Be Zero. See page 216 of: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf However the __a_barrier_v6() function which implements this in musl uses r0 as the register written to the coprocessor and doesn't initialise it. Should __a_barrier_v6() set r0 to 0 before issuing the mcr instruction? Or is it defined somewhere that this register value doesn't matter?
On Wed, Jan 22, 2020 at 05:30:53PM -0800, Andre McCurdy wrote:
> The arm1176jzfs documentation describing the armv6 CP15 Data Memory
> Barrier operation seems to specify the register value written to the
> coprocessor as "SBZ" ie Should Be Zero. See page 216 of:
>
> http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
>
> However the __a_barrier_v6() function which implements this in musl
> uses r0 as the register written to the coprocessor and doesn't
> initialise it. Should __a_barrier_v6() set r0 to 0 before issuing the
> mcr instruction? Or is it defined somewhere that this register value
> doesn't matter?
__a_barrier_* have a contract not to clobber r0 -- see the calling
code in arch/arm/atomic_arch.h:
static inline void a_barrier()
{
register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
__asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
}
We could probably switch to using ip as the register if needed.
However looking at Linux kernel source, no effort is made to zero the
register used (see arch/arm/include/asm/assembler.h for the definition
of the smp_dmb macro) so I think it must not actually matter...
Nice find, though. Let's see if we can get a better authoritative
answer on it.
Rich
On Wed, Jan 22, 2020 at 8:18 PM Rich Felker <dalias@libc.org> wrote:
> On Wed, Jan 22, 2020 at 05:30:53PM -0800, Andre McCurdy wrote:
> > The arm1176jzfs documentation describing the armv6 CP15 Data Memory
> > Barrier operation seems to specify the register value written to the
> > coprocessor as "SBZ" ie Should Be Zero. See page 216 of:
> >
> > http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
> >
> > However the __a_barrier_v6() function which implements this in musl
> > uses r0 as the register written to the coprocessor and doesn't
> > initialise it. Should __a_barrier_v6() set r0 to 0 before issuing the
> > mcr instruction? Or is it defined somewhere that this register value
> > doesn't matter?
>
> __a_barrier_* have a contract not to clobber r0 -- see the calling
> code in arch/arm/atomic_arch.h:
>
> static inline void a_barrier()
> {
> register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
> __asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
> }
>
> We could probably switch to using ip as the register if needed.
> However looking at Linux kernel source, no effort is made to zero the
> register used (see arch/arm/include/asm/assembler.h for the definition
> of the smp_dmb macro) so I think it must not actually matter...
>
> Nice find, though. Let's see if we can get a better authoritative
> answer on it.
OK. Another question: what's the reason for testing that the 3rd char
of AT_PLATFORM isn't [0-9] in __set_thread_area()? Isn't just testing
that the first two chars are "v6" enough to confirm armv6?
On Thu, Jan 23, 2020 at 06:09:57PM -0800, Andre McCurdy wrote:
> On Wed, Jan 22, 2020 at 8:18 PM Rich Felker <dalias@libc.org> wrote:
> > On Wed, Jan 22, 2020 at 05:30:53PM -0800, Andre McCurdy wrote:
> > > The arm1176jzfs documentation describing the armv6 CP15 Data Memory
> > > Barrier operation seems to specify the register value written to the
> > > coprocessor as "SBZ" ie Should Be Zero. See page 216 of:
> > >
> > > http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
> > >
> > > However the __a_barrier_v6() function which implements this in musl
> > > uses r0 as the register written to the coprocessor and doesn't
> > > initialise it. Should __a_barrier_v6() set r0 to 0 before issuing the
> > > mcr instruction? Or is it defined somewhere that this register value
> > > doesn't matter?
> >
> > __a_barrier_* have a contract not to clobber r0 -- see the calling
> > code in arch/arm/atomic_arch.h:
> >
> > static inline void a_barrier()
> > {
> > register uintptr_t ip __asm__("ip") = __a_barrier_ptr;
> > __asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
> > }
> >
> > We could probably switch to using ip as the register if needed.
> > However looking at Linux kernel source, no effort is made to zero the
> > register used (see arch/arm/include/asm/assembler.h for the definition
> > of the smp_dmb macro) so I think it must not actually matter...
> >
> > Nice find, though. Let's see if we can get a better authoritative
> > answer on it.
>
> OK. Another question: what's the reason for testing that the 3rd char
> of AT_PLATFORM isn't [0-9] in __set_thread_area()? Isn't just testing
> that the first two chars are "v6" enough to confirm armv6?
Indeed I suppose we should test that, though I don't seem "armv60" as
being likely now that they've mostly moved on to 64-bit for new isa
levels...
Rich