Re: a problem in cpucheck.c on x86

From: Denys Vlasenko
Date: Thu Dec 15 2011 - 03:31:08 EST


On Thu, Dec 15, 2011 at 8:51 AM, ttlxzz ccc <boyzccc@xxxxxxxxx> wrote:
> Hi,all:
>
> In arch/x86/boot/cpucheck.c
> static int has_eflag(u32 mask)
> {
>        u32 f0, f1;
>
>        asm("pushfl ; "
>            "pushfl ; "
>            "popl %0 ; "
>            "movl %0,%1 ; "
>            "xorl %2,%1 ; "
>            "pushl %1 ; "
>            "popfl ; "
>            "pushfl ; "
>            "popl %1 ; "
>            "popfl"
>            : "=&r" (f0), "=&r" (f1)
>            : "ri" (mask));
>
>        return !!((f0^f1) & mask);
> }
>
>            "pushl %1 ; "
>            "popfl ; "
>            "pushfl ; "
>            "popl %1 ; "
> I don't know what does above 4 instructions do,

They move value from register %1 to EFLAGS register, and back.
Some bits in EFLAGS are immutable, thus this operation
can change %1.

Basically, this operation checks whether bit we flipped by xor
is really mutable in EFLAGS, or not.

> and I rewirte it like this:
>
> static int has_eflag(u32 mask)
> {
>        u32 f0;
>
>        asm("pushfl ; "
>            "pushfl ; "
>            "popl %0 ; "
>            "popfl"
>            : "=&r" (f0));

Well, you can get rid of outer pair of pushfl/popfl too, then...

>        return ~f0 & mask;
>
> }
> It works well, and I just want to know is there some special meanings
> of the 4 instructions?

Maybe it works on your particular CPU (meaning: kernel doesn't
misdetect anything dangerous on your CPU), but in general
what you did is wrong, and will surely cause breakage on other CPUs.

--
vda
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/