x86: do not allow to optimize flag_is_changeable_p() (rev. 2)
The flag_is_changeable_p() is used by has_cpuid_p() which can return different results in the code sequence below: if (!have_cpuid_p()) identify_cpu_without_cpuid(c); /* cyrix could have cpuid enabled via c_identify()*/ if (!have_cpuid_p()) return; Otherwise, the gcc 3.4.6 optimizes these two calls into one which make the code not working correctly. Cyrix cpus have the CPUID instruction enabled before the second call to the have_cpuid_p() but it is not detected due to the gcc optimization. Thus the ARR registers (mtrr like) are not detected on such a cpu. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
e2ce07c804
commit
94f6bac105
|
@ -124,18 +124,25 @@ static inline int flag_is_changeable_p(u32 flag)
|
||||||
{
|
{
|
||||||
u32 f1, f2;
|
u32 f1, f2;
|
||||||
|
|
||||||
asm("pushfl\n\t"
|
/*
|
||||||
"pushfl\n\t"
|
* Cyrix and IDT cpus allow disabling of CPUID
|
||||||
"popl %0\n\t"
|
* so the code below may return different results
|
||||||
"movl %0,%1\n\t"
|
* when it is executed before and after enabling
|
||||||
"xorl %2,%0\n\t"
|
* the CPUID. Add "volatile" to not allow gcc to
|
||||||
"pushl %0\n\t"
|
* optimize the subsequent calls to this function.
|
||||||
"popfl\n\t"
|
*/
|
||||||
"pushfl\n\t"
|
asm volatile ("pushfl\n\t"
|
||||||
"popl %0\n\t"
|
"pushfl\n\t"
|
||||||
"popfl\n\t"
|
"popl %0\n\t"
|
||||||
: "=&r" (f1), "=&r" (f2)
|
"movl %0,%1\n\t"
|
||||||
: "ir" (flag));
|
"xorl %2,%0\n\t"
|
||||||
|
"pushl %0\n\t"
|
||||||
|
"popfl\n\t"
|
||||||
|
"pushfl\n\t"
|
||||||
|
"popl %0\n\t"
|
||||||
|
"popfl\n\t"
|
||||||
|
: "=&r" (f1), "=&r" (f2)
|
||||||
|
: "ir" (flag));
|
||||||
|
|
||||||
return ((f1^f2) & flag) != 0;
|
return ((f1^f2) & flag) != 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue