diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 55c80ffb8719..fdccfe9dc63d 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1394,9 +1394,12 @@ static inline void mwait_play_dead(void) | |||
1394 | unsigned int highest_cstate = 0; | 1394 | unsigned int highest_cstate = 0; |
1395 | unsigned int highest_subcstate = 0; | 1395 | unsigned int highest_subcstate = 0; |
1396 | int i; | 1396 | int i; |
1397 | void *mwait_ptr; | ||
1397 | 1398 | ||
1398 | if (!cpu_has(¤t_cpu_data, X86_FEATURE_MWAIT)) | 1399 | if (!cpu_has(¤t_cpu_data, X86_FEATURE_MWAIT)) |
1399 | return; | 1400 | return; |
1401 | if (!cpu_has(¤t_cpu_data, X86_FEATURE_CLFLSH)) | ||
1402 | return; | ||
1400 | if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | 1403 | if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
1401 | return; | 1404 | return; |
1402 | 1405 | ||
@@ -1422,10 +1425,25 @@ static inline void mwait_play_dead(void) | |||
1422 | (highest_subcstate - 1); | 1425 | (highest_subcstate - 1); |
1423 | } | 1426 | } |
1424 | 1427 | ||
1428 | /* | ||
1429 | * This should be a memory location in a cache line which is | ||
1430 | * unlikely to be touched by other processors. The actual | ||
1431 | * content is immaterial as it is not actually modified in any way. | ||
1432 | */ | ||
1433 | mwait_ptr = ¤t_thread_info()->flags; | ||
1434 | |||
1425 | wbinvd(); | 1435 | wbinvd(); |
1426 | 1436 | ||
1427 | while (1) { | 1437 | while (1) { |
1428 | __monitor(¤t_thread_info()->flags, 0, 0); | 1438 | /* |
1439 | * The CLFLUSH is a workaround for erratum AAI65 for | ||
1440 | * the Xeon 7400 series. It's not clear it is actually | ||
1441 | * needed, but it should be harmless in either case. | ||
1442 | * The WBINVD is insufficient due to the spurious-wakeup | ||
1443 | * case where we return around the loop. | ||
1444 | */ | ||
1445 | clflush(mwait_ptr); | ||
1446 | __monitor(mwait_ptr, 0, 0); | ||
1429 | mb(); | 1447 | mb(); |
1430 | __mwait(eax, 0); | 1448 | __mwait(eax, 0); |
1431 | } | 1449 | } |