On Sun, 2004-03-28 at 10:24, Arkadiusz Miskiewicz wrote:
> ACPI uses cmpxchg so it's not possible to build it for i386 it seems.
>
> +__acpi_release_global_lock (unsigned int *lock)
> +{
> + unsigned int old, new, val;
> + do {
> + old = *lock;
> + new = old & ~0x3;
> + val = cmpxchg(lock, old, new);
> + } while (unlikely (val != old));
> + return old & 0x1;
> +}
>
> -o vmlinux
> drivers/acpi/acpi.o(.text+0x4cf4): In function
> `acpi_ev_global_lock_handler':
> : undefined reference to `cmpxchg'
> drivers/acpi/acpi.o(.text+0x4dc6): In function
> `acpi_ev_acquire_global_lock':
> : undefined reference to `cmpxchg'
> drivers/acpi/acpi.o(.text+0x4e4b): In function
> `acpi_ev_release_global_lock':
> : undefined reference to `cmpxchg'
ACPI unconditionally used cmpxchg before this change also -- from asm().
The asm() was broken, so we replaced it with C,
which invokes the cmpxchg macro, which isn't defined for
an 80386 build.
I guess it is a build bug that the assembler allowed us
to invoke cmpxchg in an asm() for an 80386 build in earlier releases.
I'm open to suggestions on the right way to fix this.
1. recommend CONFIG_ACPI=n for 80386 build.
2. force CONFIG_ACPI=n for 80386 build.
3. invoke cmpxchg from acpi even for 80386 build.
4. re-implement locks for the 80386 case.
I guess it depends on why one would build
for 808386 and CONFIG_ACPI=y. Certainly
there is no risk of 80386 hardware actually
running the CMPXCHG in the ACPI code --
80386 was EOL'd long before ACPI came out
and 2.4.25 (and earlier) would have died on us.
I don't like #1 b/c I don't want to get more
e-mail like this;-)
#2 wouldn't bother me. But if somebody is
building for i386 for the purpose for de-tuning
the compiler and they really do want ACPI support,
it would bother them.
#3 would be the old behaviour, which also
wouldn't bother me. I guess we'd duplicate the
macro inside the ACPI code so that others didn't
use it by mistake.
#4 would be an academic exercise, since the code
would never actually execute on an 80386.
suggestions?
thanks,
-Len
Hi Len,
On Sun, Mar 28, 2004 at 11:49:15PM -0500, Len Brown wrote:
> ACPI unconditionally used cmpxchg before this change also -- from asm().
> The asm() was broken, so we replaced it with C,
> which invokes the cmpxchg macro, which isn't defined for
> an 80386 build.
>
> I guess it is a build bug that the assembler allowed us
> to invoke cmpxchg in an asm() for an 80386 build in earlier releases.
>
> I'm open to suggestions on the right way to fix this.
>
> 1. recommend CONFIG_ACPI=n for 80386 build.
>
> 2. force CONFIG_ACPI=n for 80386 build.
>
> 3. invoke cmpxchg from acpi even for 80386 build.
>
> 4. re-implement locks for the 80386 case.
I like this one, but a simpler way : don't support SMP in this case, so that
we won't have to play with locks. This would lead to something like this :
#ifndef CONFIG_X86_CMPXCHG
#ifndef CONFIG_SMP
#define cmpxchg(lock,old,new) ((*lock == old) ? ((*lock = new), old) : (*lock))
#else
#define cmpxchg(lock,old,new) This_System_Is_Not_Supported
#endif
#endif
This code (if valid) might be added to asm-i386/system.h so that we don't
touch ACPI code.
Any comments ?
Willy
On 28 Mar 2004 23:49:15 -0500
Len Brown <[email protected]> wrote:
>
> I'm open to suggestions on the right way to fix this.
>
> 1. recommend CONFIG_ACPI=n for 80386 build.
>
> 2. force CONFIG_ACPI=n for 80386 build.
>
> 3. invoke cmpxchg from acpi even for 80386 build.
I think (3) is best. Just define it always, even when the kernel is built for
i386. I considered it always a bug that cmpxchg was not defined in i386 builds.
The users of it just have to ensure it won't actually run on an i386 (by cpuid
or implicitely like ACPI does)
-Andi
On Monday 29 March 2004 07:22, Willy Tarreau wrote:
> Hi Len,
>
> On Sun, Mar 28, 2004 at 11:49:15PM -0500, Len Brown wrote:
> > ACPI unconditionally used cmpxchg before this change also -- from asm().
> > The asm() was broken, so we replaced it with C,
> > which invokes the cmpxchg macro, which isn't defined for
> > an 80386 build.
> >
> > I guess it is a build bug that the assembler allowed us
> > to invoke cmpxchg in an asm() for an 80386 build in earlier releases.
> >
> > I'm open to suggestions on the right way to fix this.
> >
> > 1. recommend CONFIG_ACPI=n for 80386 build.
> >
> > 2. force CONFIG_ACPI=n for 80386 build.
> >
> > 3. invoke cmpxchg from acpi even for 80386 build.
> >
> > 4. re-implement locks for the 80386 case.
>
> I like this one, but a simpler way : don't support SMP in this case, so
> that we won't have to play with locks. This would lead to something like
> this :
Yes, SMP makes sense only on 486+
> #ifndef CONFIG_X86_CMPXCHG
> #ifndef CONFIG_SMP
> #define cmpxchg(lock,old,new) ((*lock == old) ? ((*lock = new), old) :
> (*lock)) #else
> #define cmpxchg(lock,old,new) This_System_Is_Not_Supported
> #endif
> #endif
>
> This code (if valid) might be added to asm-i386/system.h so that we don't
> touch ACPI code.
>
> Any comments ?
Inline func please. We definitely don't want to evaluate
lock and old expressions several times.
--
vda
On Mon, Mar 29, 2004 at 09:01:47AM +0200, Denis Vlasenko wrote:
> > > 4. re-implement locks for the 80386 case.
> >
> > I like this one, but a simpler way : don't support SMP in this case, so
> > that we won't have to play with locks. This would lead to something like
> > this :
>
> Yes, SMP makes sense only on 486+
Indeed, Andi made a good point : some people compile for 386 as a generic
target which can potentially run on more recent hardware with ACPI support.
May be we should consider this behaviour broken anyway, since there are
other features that will never be available, such as TSC. So why not simply
disable ACPI for 386 ?
> Inline func please. We definitely don't want to evaluate
> lock and old expressions several times.
That's right. But I'm too lazy this evening for something which has too few
chances of being the definitive solution :-)
Cheers,
willy
On Mon, 2004-03-29 at 00:22, Willy Tarreau wrote:
> > 4. re-implement locks for the 80386 case.
>
> I like this one, but a simpler way : don't support SMP in this case, so that
> we won't have to play with locks. This would lead to something like this :
Linux uses this locking mechanism to coordinate shared access
to hardware registers with embedded controllers,
which is true also on uniprocessors too.
thanks,
-Len
On Llu, 2004-03-29 at 23:07, Len Brown wrote:
> Linux uses this locking mechanism to coordinate shared access
> to hardware registers with embedded controllers,
> which is true also on uniprocessors too.
If the ACPI layer simply refuses to run on a CPU without cmpxchg
then I can't see there being a problem, there don't appear to be
any 386 processors with ACPI
On Tue, 30 Mar 2004, Alan Cox wrote:
> On Llu, 2004-03-29 at 23:07, Len Brown wrote:
> > Linux uses this locking mechanism to coordinate shared access
> > to hardware registers with embedded controllers,
> > which is true also on uniprocessors too.
>
> If the ACPI layer simply refuses to run on a CPU without cmpxchg
> then I can't see there being a problem, there don't appear to be
> any 386 processors with ACPI
>
Yep, but to get to use cmpxchg, you need to compile as a '486 or
higher. This breaks i386.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
On Tue, Mar 30, 2004 at 08:15:46AM -0500, Richard B. Johnson wrote:
> On Tue, 30 Mar 2004, Alan Cox wrote:
>
> > On Llu, 2004-03-29 at 23:07, Len Brown wrote:
> > > Linux uses this locking mechanism to coordinate shared access
> > > to hardware registers with embedded controllers,
> > > which is true also on uniprocessors too.
> >
> > If the ACPI layer simply refuses to run on a CPU without cmpxchg
> > then I can't see there being a problem, there don't appear to be
> > any 386 processors with ACPI
> >
>
> Yep, but to get to use cmpxchg, you need to compile as a '486 or
> higher. This breaks i386.
OK, so why not compile the cmpxchg instruction even on i386 targets
to let generic kernels stay compatible with everything, but disable
ACPI at boot if the processor does not feature cmpxchg ? This could
be helpful for boot/install kernels which try to support a wide
range of platforms, and may need ACPI to correctly enable interrupts
on others.
Cheers,
Willy
On Tue, 30 Mar 2004, Willy Tarreau wrote:
> On Tue, Mar 30, 2004 at 08:15:46AM -0500, Richard B. Johnson wrote:
> > On Tue, 30 Mar 2004, Alan Cox wrote:
> >
> > > On Llu, 2004-03-29 at 23:07, Len Brown wrote:
> > > > Linux uses this locking mechanism to coordinate shared access
> > > > to hardware registers with embedded controllers,
> > > > which is true also on uniprocessors too.
> > >
> > > If the ACPI layer simply refuses to run on a CPU without cmpxchg
> > > then I can't see there being a problem, there don't appear to be
> > > any 386 processors with ACPI
> > >
> >
> > Yep, but to get to use cmpxchg, you need to compile as a '486 or
> > higher. This breaks i386.
>
> OK, so why not compile the cmpxchg instruction even on i386 targets
> to let generic kernels stay compatible with everything, but disable
> ACPI at boot if the processor does not feature cmpxchg ? This could
> be helpful for boot/install kernels which try to support a wide
> range of platforms, and may need ACPI to correctly enable interrupts
> on others.
>
> Cheers,
> Willy
>
Because it would get used (by the compiler) in other code as well!
As soon as the 386 sees it, you get an "invalid instruction trap"
and you are dead.
It might be a good idea to declare that after version xxx,
'386 compatibility is no longer provided. There is plenty of
usability for '386s in 2.4.nn, for instance.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
> > OK, so why not compile the cmpxchg instruction even on i386 targets
> > to let generic kernels stay compatible with everything, but disable
> > ACPI at boot if the processor does not feature cmpxchg ? This could
> > be helpful for boot/install kernels which try to support a wide
> > range of platforms, and may need ACPI to correctly enable interrupts
> > on others.
> >
> > Cheers,
> > Willy
> >
>
> Because it would get used (by the compiler) in other code as well!
> As soon as the 386 sees it, you get an "invalid instruction trap"
> and you are dead.
That's not what I meant. I only meant to declare the cmpxchg() function.
Nobody uses it in 386 code right now, otherwise this code would not compile
on 386 (like ACPI now). So the function would not be used by anything else
but ACPI (at the moment). Then, drivers (such as ACPI) who know they will
need cmpxchg() would be responsible for testing the flag upon initialisation
and refuse to complete initialization if the instruction is not available.
> It might be a good idea to declare that after version xxx,
> '386 compatibility is no longer provided. There is plenty of
> usability for '386s in 2.4.nn, for instance.
I don't like the idea of dropping 386 compatibility in the stable
series. For instance, my home firewall still was a miniature 386sx
a few months ago, so there may be other people in similar situation.
Making CONFIG_ACPI depend on CONFIG_CMPXCHG would be less of a hassle
in this case, because it would imply that people either compile for
486+ with ACPI or for 386+ without ACPI.
Cheers,
Willy
On Tue, 30 Mar 2004, Willy Tarreau wrote:
>
> > > OK, so why not compile the cmpxchg instruction even on i386 targets
> > > to let generic kernels stay compatible with everything, but disable
> > > ACPI at boot if the processor does not feature cmpxchg ? This could
> > > be helpful for boot/install kernels which try to support a wide
> > > range of platforms, and may need ACPI to correctly enable interrupts
> > > on others.
> > >
> > > Cheers,
> > > Willy
> > >
> >
> > Because it would get used (by the compiler) in other code as well!
> > As soon as the 386 sees it, you get an "invalid instruction trap"
> > and you are dead.
>
> That's not what I meant. I only meant to declare the cmpxchg() function.
It's not a function. It is actual op-codes. If you compile with
'486 or higher, the C compiler is free to spew out these op-codes
any time it thinks it's a viable instruction sequence. Since
it basically replaces two other op-codes, gcc might certainly use
if for optimization.
This is independent of the macro that is defined in a header to
use this sequence .
[SNIPPED...]
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
> > That's not what I meant. I only meant to declare the cmpxchg() function.
>
> It's not a function. It is actual op-codes.
I know it's an opcode (I even wrote an emulator for it). But it's used
as an inline function in linux. Check include/asm-i386/system.h.
> If you compile with '486 or higher, the C compiler is free to spew
> out these op-codes any time it thinks it's a viable instruction
> sequence. Since it basically replaces two other op-codes, gcc might
> certainly use if for optimization.
Yes, only if you compile with -m486 or higher. When Linux is compiled for
386 target, the -march=i386 is correctly appended, which prevents gcc from
using this instruction (as well as bswap and xadd BTW).
In what I described, a 386 target would be compiled with -march=i386,
but the cmpxchg() FUNCTION will still reference the cmpxchg op-code
in the __asm__ statement, and this is perfectly valid. In this case,
only callers of the cmpxchg() FUNCTION will have a chance to use it.
And at the moment, the only client seems to be ACPI.
Anyway, I think that basically we understand ourselves, and it's just
a matter of words.
Cheers,
Willy
Willy Tarreau wrote:
> In what I described, a 386 target would be compiled with -march=i386,
> but the cmpxchg() FUNCTION will still reference the cmpxchg op-code
> in the __asm__ statement, and this is perfectly valid. In this case,
> only callers of the cmpxchg() FUNCTION will have a chance to use it.
> And at the moment, the only client seems to be ACPI.
Will the assembler even let you compile the cmpxchg asm instruction if
you're building for i386?
Chris
Sorry I didn't reply to this thread, after Alan wrote I figured
the topic was closed;-)
Yes, per my initial message, gcc _will_ generate cmpxchg for the 80386
build. Indeed, it has been doing so for over a year with ACPI's
previous private (and flawed) asm() invocation of cmpxchg.
Andi/Alan suggested we invoke cmpxchg always in ACPI,
but disable ACPI at boot-time in the unlikely event we find
ourselves running on a cpu without that instruction.
Luming has already taking a swing at this patch here:
http://bugzilla.kernel.org/show_bug.cgi?id=2391
thanks,
-Len
Dnia Tuesday 30 of March 2004 19:44, Len Brown napisa?:
> Luming has already taking a swing at this patch here:
> http://bugzilla.kernel.org/show_bug.cgi?id=2391
Wouldn't be better to just remove #ifdef CONFIG_X86_CMPXCHG around __cmpxchg()
and cmpxchg macro in ./include/asm-i386/system.h so cmpxchg() would be there
always even on i386 but leave CONFIG_X86_CMPXCHG macro if anyone want's to
check for it in some code. No code duplication and you get what you need.
It would be something like:
#ifdef CONFIG_X86_CMPXCHG
#define __HAVE_ARCH_CMPXCHG 1
#endif
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
}
#define cmpxchg(ptr,o,n)\
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
instead of current:
#ifdef CONFIG_X86_CMPXCHG
#define __HAVE_ARCH_CMPXCHG 1
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
}
#define cmpxchg(ptr,o,n)\
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
#else
/* Compiling for a 386 proper. Is it worth implementing via cli/sti? */
#endif
?
> thanks,
> -Len
--
Arkadiusz Mi?kiewicz CS at FoE, Wroclaw University of Technology
arekm.pld-linux.org, 1024/3DB19BBD, JID: arekm.jabber.org, PLD/Linux
Len Brown wrote:
> Sorry I didn't reply to this thread, after Alan wrote I figured
> the topic was closed;-)
>
> Yes, per my initial message, gcc _will_ generate cmpxchg for the 80386
> build. Indeed, it has been doing so for over a year with ACPI's
> previous private (and flawed) asm() invocation of cmpxchg.
>
> Andi/Alan suggested we invoke cmpxchg always in ACPI,
> but disable ACPI at boot-time in the unlikely event we find
> ourselves running on a cpu without that instruction.
Is there no reasonable way to avoid using it in ACPI? It's not as if
performance was critical there, or the code gets run often. Too bad it
can't just be emulated like floating point, but I don't think it can on SMP.
I have to think Alan is right as usual.
--
-bill davidsen ([email protected])
"The secret to procrastination is to put things off until the
last possible moment - but no longer" -me
I can make sure that ACPI checks implicitly or explicitly
that CMPXCHG is available -- but I can't make sure that
some other random part of the kernel which may not have
been written yet does. So I'd rather that they not build,
like ACPI didn't.
BTW. CMPXCHG (486 and above) doesn't seem to be in CPUID,
CMPXCHG8B is, but that starts with Pentium and above.
Maybe simpler to rely on the implicit "check" that we
did in previous releases... Earliest known ACPI
implementation as on Pentium-1.
cheers,
-Len
On Tue, 2004-03-30 at 13:30, Arkadiusz Miskiewicz wrote:
> Dnia Tuesday 30 of March 2004 19:44, Len Brown napisa?:
>
> > Luming has already taking a swing at this patch here:
> > http://bugzilla.kernel.org/show_bug.cgi?id=2391
> Wouldn't be better to just remove #ifdef CONFIG_X86_CMPXCHG around __cmpxchg()
> and cmpxchg macro in ./include/asm-i386/system.h so cmpxchg() would be there
> always even on i386 but leave CONFIG_X86_CMPXCHG macro if anyone want's to
> check for it in some code. No code duplication and you get what you need.
>
> It would be something like:
>
> #ifdef CONFIG_X86_CMPXCHG
> #define __HAVE_ARCH_CMPXCHG 1
> #endif
> static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
> unsigned long new, int size)
> {
> }
> #define cmpxchg(ptr,o,n)\
> ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
> (unsigned long)(n),sizeof(*(ptr))))
>
> instead of current:
>
> #ifdef CONFIG_X86_CMPXCHG
> #define __HAVE_ARCH_CMPXCHG 1
>
> static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
> unsigned long new, int size)
> {
> }
> #define cmpxchg(ptr,o,n)\
> ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
> (unsigned long)(n),sizeof(*(ptr))))
>
> #else
> /* Compiling for a 386 proper. Is it worth implementing via cli/sti? */
> #endif
>
> ?
>
> > thanks,
> > -Len
Dnia Tuesday 30 of March 2004 22:05, Len Brown napisa?:
> I can make sure that ACPI checks implicitly or explicitly
> that CMPXCHG is available -- but I can't make sure that
> some other random part of the kernel which may not have
> been written yet does. So I'd rather that they not build,
> like ACPI didn't.
Well, I asked for this because there is similar case with some DRI drivers in
kernel. These drivers use cmpxchg and some time ago it was not possible to
build them for i386 (and of course run on 486+). This AFAIK did not change.
These not yet written parts of kernel do not exist so nothing to worry about
right now. Anyway there always could be #warning for i386 - easy to catch
while compiling and would allow to fix that future kernel code then.
> cheers,
> -Len
> > Wouldn't be better to just remove #ifdef CONFIG_X86_CMPXCHG around
> > __cmpxchg() and cmpxchg macro in ./include/asm-i386/system.h so cmpxchg()
> > would be there always even on i386 but leave CONFIG_X86_CMPXCHG macro if
> > anyone want's to check for it in some code. No code duplication and you
> > get what you need.
--
Arkadiusz Mi?kiewicz CS at FoE, Wroclaw University of Technology
arekm.pld-linux.org, 1024/3DB19BBD, JID: arekm.jabber.org, PLD/Linux
Okay, simplicity wins;-)
Build for 80386 -- get a build-time warning -- that should do.
thanks,
-Len
ps. earliest ACPI implementation is said to in the late Pentium (1) era.
===== arch/i386/kernel/acpi/boot.c 1.56 vs edited =====
--- 1.56/arch/i386/kernel/acpi/boot.c Fri Mar 26 17:50:48 2004
+++ edited/arch/i386/kernel/acpi/boot.c Tue Mar 30 16:23:39 2004
@@ -67,6 +67,10 @@
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#endif
+#ifndef __HAVE_ARCH_CMPXCHG
+#warning ACPI uses CMPXCHG, i486 and later hardware
+#endif
+
/*
--------------------------------------------------------------------------
Boot-time Configuration
-------------------------------------------------------------------------- */
===== include/asm-i386/system.h 1.30 vs edited =====
--- 1.30/include/asm-i386/system.h Fri Nov 21 01:24:00 2003
+++ edited/include/asm-i386/system.h Tue Mar 30 16:05:30 2004
@@ -241,6 +241,7 @@
#ifdef CONFIG_X86_CMPXCHG
#define __HAVE_ARCH_CMPXCHG 1
+#endif
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long
old,
unsigned long new, int size)
@@ -273,10 +274,6 @@
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
-#else
-/* Compiling for a 386 proper. Is it worth implementing via cli/sti?
*/
-#endif
-
#ifdef __KERNEL__
struct alt_instr {
__u8 *instr; /* original instruction */
On Tue, 30 Mar 2004, Bill Davidsen wrote:
> Is there no reasonable way to avoid using it in ACPI? It's not as if
> performance was critical there, or the code gets run often. Too bad it
> can't just be emulated like floating point, but I don't think it can on SMP.
Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
spinlock. With SMP operation included.
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +
On Wed, 31 Mar 2004, Maciej W. Rozycki wrote:
> On Tue, 30 Mar 2004, Bill Davidsen wrote:
>
> > Is there no reasonable way to avoid using it in ACPI? It's not as if
> > performance was critical there, or the code gets run often. Too bad it
> > can't just be emulated like floating point, but I don't think it can on SMP.
>
> Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> spinlock. With SMP operation included.
Clearly they can be replaced with inline code, as for catching the ill-op
fault and emulating inline, I want to think about that a bit on SMP, in
the case where multiple CPUs are accessing different locations, one is in
kernel and one in user mode, etc.
If it can be emulated safely in all cases, then that provides an out for
the 386 case. To be useful it would have to be correct for all
combinations of SMP, preempt and an interrupt and any point.
--
bill davidsen <[email protected]>
CTO, TMR Associates, Inc
Doing interesting things with little computers since 1979.
Maciej W. Rozycki wrote:
> Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> spinlock. With SMP operation included.
Nope. Len Brown wrote:
> Linux uses this locking mechanism to coordinate shared access
> to hardware registers with embedded controllers,
> which is true also on uniprocessors too.
You can't do that with a spinlock. The embedded controllers would
need to know about the spinlock.
-- Jamie
On Wed, 31 Mar 2004, Jamie Lokier wrote:
> > Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> > spinlock. With SMP operation included.
>
> Nope. Len Brown wrote:
>
> > Linux uses this locking mechanism to coordinate shared access
> > to hardware registers with embedded controllers,
> > which is true also on uniprocessors too.
>
> You can't do that with a spinlock. The embedded controllers would
> need to know about the spinlock.
Hmm, does it mean we support x86 systems where an iomem resource has to
be atomically accessible by a CPU and a peripheral controller?
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +
On Thu, 1 Apr 2004, Maciej W. Rozycki wrote:
> On Wed, 31 Mar 2004, Jamie Lokier wrote:
>
> > > Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> > > spinlock. With SMP operation included.
> >
> > Nope. Len Brown wrote:
> >
> > > Linux uses this locking mechanism to coordinate shared access
> > > to hardware registers with embedded controllers,
> > > which is true also on uniprocessors too.
> >
> > You can't do that with a spinlock. The embedded controllers would
> > need to know about the spinlock.
>
> Hmm, does it mean we support x86 systems where an iomem resource has to
> be atomically accessible by a CPU and a peripheral controller?
>
> --
> + Maciej W. Rozycki, Technical University of Gdansk, Poland +
> +--------------------------------------------------------------+
> + e-mail: [email protected], PGP key available +
Of course they all can be emulated. And some "embedded
controllers" don't care and won't have a clue.
The whole idea of atomic operations is to have the specific
operation complete entirely so there is no intermediate
state that can catch you with your pants down.
For instance, If I code something in 'C' as:
x++;
I would expect that the value of x after the sequence-
point is exactly one more than it was before. However,
if x happens to be a long long in ix86 machines, you
are screwed because the operation occurs in two stages.
addl $1,(x) # Low word
adcl $0,4(x) # CY into high word
If you got interrupted between the first and second operation,
AND if the result of the operation was used before it was
completed, the user gets the wrong value.
In Intel machines ALL memory operations are atomic. What
the means is that if I make code that does:
addl %eax,(memory)
... what's in memory will always be the sum of what it was
before and the value in the EAX register. However, if I
made code that did:
movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory
... such operations are not atomic even though they do the
same thing.
A long time ago, somebody invented the 'lock' instruction
for Intel machines. It turns out that the first ones locked
the whole bus during an operation. Eventually somebody looked
at that, and by the time the '486 came out, they no longer
locked the whole bus. Then somebody else said; "WTF...
Why do we even need this stuff". It was a throw-back to
early primitive machines where there were only load and
store operations in memory. All arithmetic had to be done
in registers. Now, there are only a couple instructions you
can use the lock prefix with, or you get an invalid opcode
trap, and they are really no-ops because the instruction
itself is atomic.
To make the:
movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory
... code atomic, you need only to prevent it from being
interrupted. On a non-SMP machine, it's easy.
pushf # Save flags
cli # Clear interrupt bit
movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory
popf # Restore flags (and interrupt bit)
It's a bit more complicated on SMP machines because CLI only
affects the CPU that fetched it. You need a spin-lock for
that.
Now, if my memory operand happens to be some bits that
control a machine, we are not talking about atomic operations
at all, but the order of operations. This could take a
whole chapter in a book.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.
On Thu, 2004-04-01 at 07:29, Maciej W. Rozycki wrote:
> On Wed, 31 Mar 2004, Jamie Lokier wrote:
>
> > > Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> > > spinlock. With SMP operation included.
> >
> > Nope. Len Brown wrote:
> >
> > > Linux uses this locking mechanism to coordinate shared access
> > > to hardware registers with embedded controllers,
> > > which is true also on uniprocessors too.
> >
> > You can't do that with a spinlock. The embedded controllers would
> > need to know about the spinlock.
>
> Hmm, does it mean we support x86 systems where an iomem resource has to
> be atomically accessible by a CPU and a peripheral controller?
ACPI specifies a location in regular memory that is used to contain the
lock. The lock is used both by the CPU and by the embedded controller
to cover access to shared registers. We don't spin on this lock because
we don't know how long the embedded controller might hold it. Instead
when we fail to acquire it we schedule an event to trigger when the lock
is free.
cheers,
-Len
On Thu, 1 Apr 2004, Len Brown wrote:
> ACPI specifies a location in regular memory that is used to contain the
> lock. The lock is used both by the CPU and by the embedded controller
> to cover access to shared registers. We don't spin on this lock because
> we don't know how long the embedded controller might hold it. Instead
> when we fail to acquire it we schedule an event to trigger when the lock
> is free.
OK, that's clear to me now. Then does this lock really require
"cmpxchg"? Wouldn't a lone "xchg" suffice?
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +