aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/acpi/cstate.c122
-rw-r--r--arch/i386/kernel/process.c22
-rw-r--r--arch/x86_64/kernel/process.c22
-rw-r--r--drivers/acpi/processor_idle.c101
-rw-r--r--include/acpi/pdc_intel.h9
-rw-r--r--include/acpi/processor.h18
-rw-r--r--include/asm-i386/processor.h2
-rw-r--r--include/asm-x86_64/processor.h2
8 files changed, 242 insertions, 56 deletions
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 25db49ef1770..20563e52c622 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/acpi.h> 12#include <linux/acpi.h>
13#include <linux/cpu.h>
13 14
14#include <acpi/processor.h> 15#include <acpi/processor.h>
15#include <asm/acpi.h> 16#include <asm/acpi.h>
@@ -41,5 +42,124 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
41 flags->bm_check = 1; 42 flags->bm_check = 1;
42 } 43 }
43} 44}
44
45EXPORT_SYMBOL(acpi_processor_power_init_bm_check); 45EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
46
47/* The code below handles cstate entry with monitor-mwait pair on Intel*/
48
49struct cstate_entry_s {
50 struct {
51 unsigned int eax;
52 unsigned int ecx;
53 } states[ACPI_PROCESSOR_MAX_POWER];
54};
55static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */
56
57static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
58
59#define MWAIT_SUBSTATE_MASK (0xf)
60#define MWAIT_SUBSTATE_SIZE (4)
61
62#define CPUID_MWAIT_LEAF (5)
63#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
64#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
65
66#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
67
68#define NATIVE_CSTATE_BEYOND_HALT (2)
69
70int acpi_processor_ffh_cstate_probe(unsigned int cpu,
71 struct acpi_processor_cx *cx, struct acpi_power_register *reg)
72{
73 struct cstate_entry_s *percpu_entry;
74 struct cpuinfo_x86 *c = cpu_data + cpu;
75
76 cpumask_t saved_mask;
77 int retval;
78 unsigned int eax, ebx, ecx, edx;
79 unsigned int edx_part;
80 unsigned int cstate_type; /* C-state type and not ACPI C-state type */
81 unsigned int num_cstate_subtype;
82
83 if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
84 return -1;
85
86 if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
87 return -1;
88
89 percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
90 percpu_entry->states[cx->index].eax = 0;
91 percpu_entry->states[cx->index].ecx = 0;
92
93 /* Make sure we are running on right CPU */
94 saved_mask = current->cpus_allowed;
95 retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
96 if (retval)
97 return -1;
98
99 cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
100
101 /* Check whether this particular cx_type (in CST) is supported or not */
102 cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1;
103 edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
104 num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
105
106 retval = 0;
107 if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
108 retval = -1;
109 goto out;
110 }
111
112 /* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
113 if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
114 !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
115 retval = -1;
116 goto out;
117 }
118 percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
119
120 /* Use the hint in CST */
121 percpu_entry->states[cx->index].eax = cx->address;
122
123 if (!mwait_supported[cstate_type]) {
124 mwait_supported[cstate_type] = 1;
125 printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
126 "state\n", cx->type);
127 }
128
129out:
130 set_cpus_allowed(current, saved_mask);
131 return retval;
132}
133EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
134
135void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
136{
137 unsigned int cpu = smp_processor_id();
138 struct cstate_entry_s *percpu_entry;
139
140 percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
141 mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
142 percpu_entry->states[cx->index].ecx);
143}
144EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);
145
146static int __init ffh_cstate_init(void)
147{
148 struct cpuinfo_x86 *c = &boot_cpu_data;
149 if (c->x86_vendor != X86_VENDOR_INTEL)
150 return -1;
151
152 cpu_cstate_entry = alloc_percpu(struct cstate_entry_s);
153 return 0;
154}
155
156static void __exit ffh_cstate_exit(void)
157{
158 if (cpu_cstate_entry) {
159 free_percpu(cpu_cstate_entry);
160 cpu_cstate_entry = NULL;
161 }
162}
163
164arch_initcall(ffh_cstate_init);
165__exitcall(ffh_cstate_exit);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index b0a07801d9df..57d375900afb 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -236,20 +236,28 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
236 * We execute MONITOR against need_resched and enter optimized wait state 236 * We execute MONITOR against need_resched and enter optimized wait state
237 * through MWAIT. Whenever someone changes need_resched, we would be woken 237 * through MWAIT. Whenever someone changes need_resched, we would be woken
238 * up from MWAIT (without an IPI). 238 * up from MWAIT (without an IPI).
239 *
240 * New with Core Duo processors, MWAIT can take some hints based on CPU
241 * capability.
239 */ 242 */
240static void mwait_idle(void) 243void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
241{ 244{
242 local_irq_enable(); 245 if (!need_resched()) {
243
244 while (!need_resched()) {
245 __monitor((void *)&current_thread_info()->flags, 0, 0); 246 __monitor((void *)&current_thread_info()->flags, 0, 0);
246 smp_mb(); 247 smp_mb();
247 if (need_resched()) 248 if (!need_resched())
248 break; 249 __mwait(eax, ecx);
249 __mwait(0, 0);
250 } 250 }
251} 251}
252 252
253/* Default MONITOR/MWAIT with no hints, used for default C1 state */
254static void mwait_idle(void)
255{
256 local_irq_enable();
257 while (!need_resched())
258 mwait_idle_with_hints(0, 0);
259}
260
253void __devinit select_idle_routine(const struct cpuinfo_x86 *c) 261void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
254{ 262{
255 if (cpu_has(c, X86_FEATURE_MWAIT)) { 263 if (cpu_has(c, X86_FEATURE_MWAIT)) {
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 5e95b257ee26..49f7fac6229e 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -238,20 +238,28 @@ void cpu_idle (void)
238 * We execute MONITOR against need_resched and enter optimized wait state 238 * We execute MONITOR against need_resched and enter optimized wait state
239 * through MWAIT. Whenever someone changes need_resched, we would be woken 239 * through MWAIT. Whenever someone changes need_resched, we would be woken
240 * up from MWAIT (without an IPI). 240 * up from MWAIT (without an IPI).
241 *
242 * New with Core Duo processors, MWAIT can take some hints based on CPU
243 * capability.
241 */ 244 */
242static void mwait_idle(void) 245void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
243{ 246{
244 local_irq_enable(); 247 if (!need_resched()) {
245
246 while (!need_resched()) {
247 __monitor((void *)&current_thread_info()->flags, 0, 0); 248 __monitor((void *)&current_thread_info()->flags, 0, 0);
248 smp_mb(); 249 smp_mb();
249 if (need_resched()) 250 if (!need_resched())
250 break; 251 __mwait(eax, ecx);
251 __mwait(0, 0);
252 } 252 }
253} 253}
254 254
255/* Default MONITOR/MWAIT with no hints, used for default C1 state */
256static void mwait_idle(void)
257{
258 local_irq_enable();
259 while (!need_resched())
260 mwait_idle_with_hints(0,0);
261}
262
255void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) 263void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
256{ 264{
257 static int printed; 265 static int printed;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 0a395fca843b..429a39dbd75d 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -219,6 +219,23 @@ static void acpi_safe_halt(void)
219 219
220static atomic_t c3_cpu_count; 220static atomic_t c3_cpu_count;
221 221
222/* Common C-state entry for C2, C3, .. */
223static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
224{
225 if (cstate->space_id == ACPI_CSTATE_FFH) {
226 /* Call into architectural FFH based C-state */
227 acpi_processor_ffh_cstate_enter(cstate);
228 } else {
229 int unused;
230 /* IO port based C-state */
231 inb(cstate->address);
232 /* Dummy wait op - must do something useless after P_LVL2 read
233 because chipsets cannot guarantee that STPCLK# signal
234 gets asserted in time to freeze execution properly. */
235 unused = inl(acpi_fadt.xpm_tmr_blk.address);
236 }
237}
238
222static void acpi_processor_idle(void) 239static void acpi_processor_idle(void)
223{ 240{
224 struct acpi_processor *pr = NULL; 241 struct acpi_processor *pr = NULL;
@@ -361,11 +378,7 @@ static void acpi_processor_idle(void)
361 /* Get start time (ticks) */ 378 /* Get start time (ticks) */
362 t1 = inl(acpi_fadt.xpm_tmr_blk.address); 379 t1 = inl(acpi_fadt.xpm_tmr_blk.address);
363 /* Invoke C2 */ 380 /* Invoke C2 */
364 inb(cx->address); 381 acpi_cstate_enter(cx);
365 /* Dummy wait op - must do something useless after P_LVL2 read
366 because chipsets cannot guarantee that STPCLK# signal
367 gets asserted in time to freeze execution properly. */
368 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
369 /* Get end time (ticks) */ 382 /* Get end time (ticks) */
370 t2 = inl(acpi_fadt.xpm_tmr_blk.address); 383 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
371 384
@@ -401,9 +414,7 @@ static void acpi_processor_idle(void)
401 /* Get start time (ticks) */ 414 /* Get start time (ticks) */
402 t1 = inl(acpi_fadt.xpm_tmr_blk.address); 415 t1 = inl(acpi_fadt.xpm_tmr_blk.address);
403 /* Invoke C3 */ 416 /* Invoke C3 */
404 inb(cx->address); 417 acpi_cstate_enter(cx);
405 /* Dummy wait op (see above) */
406 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
407 /* Get end time (ticks) */ 418 /* Get end time (ticks) */
408 t2 = inl(acpi_fadt.xpm_tmr_blk.address); 419 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
409 if (pr->flags.bm_check) { 420 if (pr->flags.bm_check) {
@@ -628,20 +639,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
628 return 0; 639 return 0;
629} 640}
630 641
631static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) 642static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
632{ 643{
633 644 if (!pr->power.states[ACPI_STATE_C1].valid) {
634 /* Zero initialize all the C-states info. */ 645 /* set the first C-State to C1 */
635 memset(pr->power.states, 0, sizeof(pr->power.states)); 646 /* all processors need to support C1 */
636 647 pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
637 /* set the first C-State to C1 */ 648 pr->power.states[ACPI_STATE_C1].valid = 1;
638 pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; 649 }
639 650 /* the C0 state only exists as a filler in our array */
640 /* the C0 state only exists as a filler in our array,
641 * and all processors need to support C1 */
642 pr->power.states[ACPI_STATE_C0].valid = 1; 651 pr->power.states[ACPI_STATE_C0].valid = 1;
643 pr->power.states[ACPI_STATE_C1].valid = 1;
644
645 return 0; 652 return 0;
646} 653}
647 654
@@ -658,12 +665,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
658 if (nocst) 665 if (nocst)
659 return -ENODEV; 666 return -ENODEV;
660 667
661 current_count = 1; 668 current_count = 0;
662
663 /* Zero initialize C2 onwards and prepare for fresh CST lookup */
664 for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++)
665 memset(&(pr->power.states[i]), 0,
666 sizeof(struct acpi_processor_cx));
667 669
668 status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); 670 status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
669 if (ACPI_FAILURE(status)) { 671 if (ACPI_FAILURE(status)) {
@@ -718,22 +720,39 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
718 (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) 720 (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
719 continue; 721 continue;
720 722
721 cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ?
722 0 : reg->address;
723
724 /* There should be an easy way to extract an integer... */ 723 /* There should be an easy way to extract an integer... */
725 obj = (union acpi_object *)&(element->package.elements[1]); 724 obj = (union acpi_object *)&(element->package.elements[1]);
726 if (obj->type != ACPI_TYPE_INTEGER) 725 if (obj->type != ACPI_TYPE_INTEGER)
727 continue; 726 continue;
728 727
729 cx.type = obj->integer.value; 728 cx.type = obj->integer.value;
730 729 /*
731 if ((cx.type != ACPI_STATE_C1) && 730 * Some buggy BIOSes won't list C1 in _CST -
732 (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) 731 * Let acpi_processor_get_power_info_default() handle them later
733 continue; 732 */
734 733 if (i == 1 && cx.type != ACPI_STATE_C1)
735 if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) 734 current_count++;
736 continue; 735
736 cx.address = reg->address;
737 cx.index = current_count + 1;
738
739 cx.space_id = ACPI_CSTATE_SYSTEMIO;
740 if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
741 if (acpi_processor_ffh_cstate_probe
742 (pr->id, &cx, reg) == 0) {
743 cx.space_id = ACPI_CSTATE_FFH;
744 } else if (cx.type != ACPI_STATE_C1) {
745 /*
746 * C1 is a special case where FIXED_HARDWARE
747 * can be handled in non-MWAIT way as well.
748 * In that case, save this _CST entry info.
749 * That is, we retain space_id of SYSTEM_IO for
750 * halt based C1.
751 * Otherwise, ignore this info and continue.
752 */
753 continue;
754 }
755 }
737 756
738 obj = (union acpi_object *)&(element->package.elements[2]); 757 obj = (union acpi_object *)&(element->package.elements[2]);
739 if (obj->type != ACPI_TYPE_INTEGER) 758 if (obj->type != ACPI_TYPE_INTEGER)
@@ -938,12 +957,18 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
938 /* NOTE: the idle thread may not be running while calling 957 /* NOTE: the idle thread may not be running while calling
939 * this function */ 958 * this function */
940 959
941 /* Adding C1 state */ 960 /* Zero initialize all the C-states info. */
942 acpi_processor_get_power_info_default_c1(pr); 961 memset(pr->power.states, 0, sizeof(pr->power.states));
962
943 result = acpi_processor_get_power_info_cst(pr); 963 result = acpi_processor_get_power_info_cst(pr);
944 if (result == -ENODEV) 964 if (result == -ENODEV)
945 acpi_processor_get_power_info_fadt(pr); 965 acpi_processor_get_power_info_fadt(pr);
946 966
967 if (result)
968 return result;
969
970 acpi_processor_get_power_info_default(pr);
971
947 pr->power.count = acpi_processor_power_verify(pr); 972 pr->power.count = acpi_processor_power_verify(pr);
948 973
949 /* 974 /*
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index c5472be6f3a2..e72bfdd887f9 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -13,6 +13,7 @@
13#define ACPI_PDC_SMP_C_SWCOORD (0x0040) 13#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
14#define ACPI_PDC_SMP_T_SWCOORD (0x0080) 14#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
15#define ACPI_PDC_C_C1_FFH (0x0100) 15#define ACPI_PDC_C_C1_FFH (0x0100)
16#define ACPI_PDC_C_C2C3_FFH (0x0200)
16 17
17#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ 18#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
18 ACPI_PDC_C_C1_HALT | \ 19 ACPI_PDC_C_C1_HALT | \
@@ -23,8 +24,10 @@
23 ACPI_PDC_SMP_P_SWCOORD | \ 24 ACPI_PDC_SMP_P_SWCOORD | \
24 ACPI_PDC_P_FFH) 25 ACPI_PDC_P_FFH)
25 26
26#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ 27#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
27 ACPI_PDC_SMP_C1PT | \ 28 ACPI_PDC_SMP_C1PT | \
28 ACPI_PDC_C_C1_HALT) 29 ACPI_PDC_C_C1_HALT | \
30 ACPI_PDC_C_C1_FFH | \
31 ACPI_PDC_C_C2C3_FFH)
29 32
30#endif /* __PDC_INTEL_H__ */ 33#endif /* __PDC_INTEL_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 9dd5b75961f8..7798d2a9f793 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -29,6 +29,9 @@
29#define DOMAIN_COORD_TYPE_SW_ANY 0xfd 29#define DOMAIN_COORD_TYPE_SW_ANY 0xfd
30#define DOMAIN_COORD_TYPE_HW_ALL 0xfe 30#define DOMAIN_COORD_TYPE_HW_ALL 0xfe
31 31
32#define ACPI_CSTATE_SYSTEMIO (0)
33#define ACPI_CSTATE_FFH (1)
34
32/* Power Management */ 35/* Power Management */
33 36
34struct acpi_processor_cx; 37struct acpi_processor_cx;
@@ -58,6 +61,8 @@ struct acpi_processor_cx {
58 u8 valid; 61 u8 valid;
59 u8 type; 62 u8 type;
60 u32 address; 63 u32 address;
64 u8 space_id;
65 u8 index;
61 u32 latency; 66 u32 latency;
62 u32 latency_ticks; 67 u32 latency_ticks;
63 u32 power; 68 u32 power;
@@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr);
206#ifdef ARCH_HAS_POWER_INIT 211#ifdef ARCH_HAS_POWER_INIT
207void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, 212void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
208 unsigned int cpu); 213 unsigned int cpu);
214int acpi_processor_ffh_cstate_probe(unsigned int cpu,
215 struct acpi_processor_cx *cx, struct acpi_power_register *reg);
216void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cstate);
209#else 217#else
210static inline void acpi_processor_power_init_bm_check(struct 218static inline void acpi_processor_power_init_bm_check(struct
211 acpi_processor_flags 219 acpi_processor_flags
@@ -214,6 +222,16 @@ static inline void acpi_processor_power_init_bm_check(struct
214 flags->bm_check = 1; 222 flags->bm_check = 1;
215 return; 223 return;
216} 224}
225static inline int acpi_processor_ffh_cstate_probe(unsigned int cpu,
226 struct acpi_processor_cx *cx, struct acpi_power_register *reg)
227{
228 return -1;
229}
230static inline void acpi_processor_ffh_cstate_enter(
231 struct acpi_processor_cx *cstate)
232{
233 return;
234}
217#endif 235#endif
218 236
219/* in processor_perflib.c */ 237/* in processor_perflib.c */
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 2277127696d2..e0ddca94d50c 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -306,6 +306,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
306 : :"a" (eax), "c" (ecx)); 306 : :"a" (eax), "c" (ecx));
307} 307}
308 308
309extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
310
309/* from system description table in BIOS. Mostly for MCA use, but 311/* from system description table in BIOS. Mostly for MCA use, but
310others may find it useful. */ 312others may find it useful. */
311extern unsigned int machine_id; 313extern unsigned int machine_id;
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index de9c3147ee4c..cef17e0f828c 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -475,6 +475,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
475 : :"a" (eax), "c" (ecx)); 475 : :"a" (eax), "c" (ecx));
476} 476}
477 477
478extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
479
478#define stack_current() \ 480#define stack_current() \
479({ \ 481({ \
480 struct thread_info *ti; \ 482 struct thread_info *ti; \