@@ -34,6 +34,7 @@ static void delay_loop(u64 __loops);
34
34
* during boot.
35
35
*/
36
36
static void (* delay_fn )(u64 ) __ro_after_init = delay_loop ;
37
+ static void (* delay_halt_fn )(u64 start , u64 cycles ) __ro_after_init ;
37
38
38
39
/* simple loop based delay: */
39
40
static void delay_loop (u64 __loops )
@@ -100,9 +101,33 @@ static void delay_tsc(u64 cycles)
100
101
* counts with TSC frequency. The input value is the number of TSC cycles
101
102
* to wait. MWAITX will also exit when the timer expires.
102
103
*/
103
- static void delay_mwaitx ( u64 cycles )
104
+ static void delay_halt_mwaitx ( u64 unused , u64 cycles )
104
105
{
105
- u64 start , end , delay ;
106
+ u64 delay ;
107
+
108
+ delay = min_t (u64 , MWAITX_MAX_WAIT_CYCLES , cycles );
109
+ /*
110
+ * Use cpu_tss_rw as a cacheline-aligned, seldomly accessed per-cpu
111
+ * variable as the monitor target.
112
+ */
113
+ __monitorx (raw_cpu_ptr (& cpu_tss_rw ), 0 , 0 );
114
+
115
+ /*
116
+ * AMD, like Intel, supports the EAX hint and EAX=0xf means, do not
117
+ * enter any deep C-state and we use it here in delay() to minimize
118
+ * wakeup latency.
119
+ */
120
+ __mwaitx (MWAITX_DISABLE_CSTATES , delay , MWAITX_ECX_TIMER_ENABLE );
121
+ }
122
+
123
+ /*
124
+ * Call a vendor specific function to delay for a given amount of time. Because
125
+ * these functions may return earlier than requested, check for actual elapsed
126
+ * time and call again until done.
127
+ */
128
+ static void delay_halt (u64 __cycles )
129
+ {
130
+ u64 start , end , cycles = __cycles ;
106
131
107
132
/*
108
133
* Timer value of 0 causes MWAITX to wait indefinitely, unless there
@@ -114,21 +139,7 @@ static void delay_mwaitx(u64 cycles)
114
139
start = rdtsc_ordered ();
115
140
116
141
for (;;) {
117
- delay = min_t (u64 , MWAITX_MAX_WAIT_CYCLES , cycles );
118
-
119
- /*
120
- * Use cpu_tss_rw as a cacheline-aligned, seldomly
121
- * accessed per-cpu variable as the monitor target.
122
- */
123
- __monitorx (raw_cpu_ptr (& cpu_tss_rw ), 0 , 0 );
124
-
125
- /*
126
- * AMD, like Intel's MWAIT version, supports the EAX hint and
127
- * EAX=0xf0 means, do not enter any deep C-state and we use it
128
- * here in delay() to minimize wakeup latency.
129
- */
130
- __mwaitx (MWAITX_DISABLE_CSTATES , delay , MWAITX_ECX_TIMER_ENABLE );
131
-
142
+ delay_halt_fn (start , cycles );
132
143
end = rdtsc_ordered ();
133
144
134
145
if (cycles <= end - start )
@@ -147,7 +158,8 @@ void __init use_tsc_delay(void)
147
158
148
159
void use_mwaitx_delay (void )
149
160
{
150
- delay_fn = delay_mwaitx ;
161
+ delay_halt_fn = delay_halt_mwaitx ;
162
+ delay_fn = delay_halt ;
151
163
}
152
164
153
165
int read_current_timer (unsigned long * timer_val )
0 commit comments