@@ -272,54 +272,65 @@ struct microcode_ctrl {
272
272
273
273
DEFINE_STATIC_KEY_FALSE (microcode_nmi_handler_enable );
274
274
static DEFINE_PER_CPU (struct microcode_ctrl , ucode_ctrl ) ;
275
+ static unsigned int loops_per_usec ;
275
276
static atomic_t late_cpus_in ;
276
277
277
- static bool wait_for_cpus (atomic_t * cnt )
278
+ static noinstr bool wait_for_cpus (atomic_t * cnt )
278
279
{
279
- unsigned int timeout ;
280
+ unsigned int timeout , loops ;
280
281
281
- WARN_ON_ONCE (atomic_dec_return (cnt ) < 0 );
282
+ WARN_ON_ONCE (raw_atomic_dec_return (cnt ) < 0 );
282
283
283
284
for (timeout = 0 ; timeout < USEC_PER_SEC ; timeout ++ ) {
284
- if (!atomic_read (cnt ))
285
+ if (!raw_atomic_read (cnt ))
285
286
return true;
286
287
287
- udelay (1 );
288
+ for (loops = 0 ; loops < loops_per_usec ; loops ++ )
289
+ cpu_relax ();
288
290
289
291
/* If invoked directly, tickle the NMI watchdog */
290
- if (!microcode_ops -> use_nmi && !(timeout % USEC_PER_MSEC ))
292
+ if (!microcode_ops -> use_nmi && !(timeout % USEC_PER_MSEC )) {
293
+ instrumentation_begin ();
291
294
touch_nmi_watchdog ();
295
+ instrumentation_end ();
296
+ }
292
297
}
293
298
/* Prevent the late comers from making progress and let them time out */
294
- atomic_inc (cnt );
299
+ raw_atomic_inc (cnt );
295
300
return false;
296
301
}
297
302
298
- static bool wait_for_ctrl (void )
303
+ static noinstr bool wait_for_ctrl (void )
299
304
{
300
- unsigned int timeout ;
305
+ unsigned int timeout , loops ;
301
306
302
307
for (timeout = 0 ; timeout < USEC_PER_SEC ; timeout ++ ) {
303
- if (this_cpu_read (ucode_ctrl .ctrl ) != SCTRL_WAIT )
308
+ if (raw_cpu_read (ucode_ctrl .ctrl ) != SCTRL_WAIT )
304
309
return true;
305
- udelay (1 );
310
+
311
+ for (loops = 0 ; loops < loops_per_usec ; loops ++ )
312
+ cpu_relax ();
313
+
306
314
/* If invoked directly, tickle the NMI watchdog */
307
- if (!microcode_ops -> use_nmi && !(timeout % 1000 ))
315
+ if (!microcode_ops -> use_nmi && !(timeout % USEC_PER_MSEC )) {
316
+ instrumentation_begin ();
308
317
touch_nmi_watchdog ();
318
+ instrumentation_end ();
319
+ }
309
320
}
310
321
return false;
311
322
}
312
323
313
- static void load_secondary (unsigned int cpu )
324
+ /*
325
+ * Protected against instrumentation up to the point where the primary
326
+ * thread completed the update. See microcode_nmi_handler() for details.
327
+ */
328
+ static noinstr bool load_secondary_wait (unsigned int ctrl_cpu )
314
329
{
315
- unsigned int ctrl_cpu = this_cpu_read (ucode_ctrl .ctrl_cpu );
316
- enum ucode_state ret ;
317
-
318
330
/* Initial rendezvous to ensure that all CPUs have arrived */
319
331
if (!wait_for_cpus (& late_cpus_in )) {
320
- pr_err_once ("load: %d CPUs timed out\n" , atomic_read (& late_cpus_in ) - 1 );
321
- this_cpu_write (ucode_ctrl .result , UCODE_TIMEOUT );
322
- return ;
332
+ raw_cpu_write (ucode_ctrl .result , UCODE_TIMEOUT );
333
+ return false;
323
334
}
324
335
325
336
/*
@@ -329,9 +340,33 @@ static void load_secondary(unsigned int cpu)
329
340
* scheduler, watchdogs etc. There is no way to safely evacuate the
330
341
* machine.
331
342
*/
332
- if (!wait_for_ctrl ())
333
- panic ("Microcode load: Primary CPU %d timed out\n" , ctrl_cpu );
343
+ if (wait_for_ctrl ())
344
+ return true;
345
+
346
+ instrumentation_begin ();
347
+ panic ("Microcode load: Primary CPU %d timed out\n" , ctrl_cpu );
348
+ instrumentation_end ();
349
+ }
334
350
351
+ /*
352
+ * Protected against instrumentation up to the point where the primary
353
+ * thread completed the update. See microcode_nmi_handler() for details.
354
+ */
355
+ static noinstr void load_secondary (unsigned int cpu )
356
+ {
357
+ unsigned int ctrl_cpu = raw_cpu_read (ucode_ctrl .ctrl_cpu );
358
+ enum ucode_state ret ;
359
+
360
+ if (!load_secondary_wait (ctrl_cpu )) {
361
+ instrumentation_begin ();
362
+ pr_err_once ("load: %d CPUs timed out\n" ,
363
+ atomic_read (& late_cpus_in ) - 1 );
364
+ instrumentation_end ();
365
+ return ;
366
+ }
367
+
368
+ /* Primary thread completed. Allow to invoke instrumentable code */
369
+ instrumentation_begin ();
335
370
/*
336
371
* If the primary succeeded then invoke the apply() callback,
337
372
* otherwise copy the state from the primary thread.
@@ -343,6 +378,7 @@ static void load_secondary(unsigned int cpu)
343
378
344
379
this_cpu_write (ucode_ctrl .result , ret );
345
380
this_cpu_write (ucode_ctrl .ctrl , SCTRL_DONE );
381
+ instrumentation_end ();
346
382
}
347
383
348
384
static void load_primary (unsigned int cpu )
@@ -380,25 +416,43 @@ static void load_primary(unsigned int cpu)
380
416
}
381
417
}
382
418
383
- static bool microcode_update_handler (void )
419
+ static noinstr bool microcode_update_handler (void )
384
420
{
385
- unsigned int cpu = smp_processor_id ();
421
+ unsigned int cpu = raw_smp_processor_id ();
386
422
387
- if (this_cpu_read (ucode_ctrl .ctrl_cpu ) == cpu )
423
+ if (raw_cpu_read (ucode_ctrl .ctrl_cpu ) == cpu ) {
424
+ instrumentation_begin ();
388
425
load_primary (cpu );
389
- else
426
+ instrumentation_end ();
427
+ } else {
390
428
load_secondary (cpu );
429
+ }
391
430
431
+ instrumentation_begin ();
392
432
touch_nmi_watchdog ();
433
+ instrumentation_end ();
434
+
393
435
return true;
394
436
}
395
437
396
- bool microcode_nmi_handler (void )
438
+ /*
439
+ * Protection against instrumentation is required for CPUs which are not
440
+ * safe against an NMI which is delivered to the secondary SMT sibling
441
+ * while the primary thread updates the microcode. Instrumentation can end
442
+ * up in #INT3, #DB and #PF. The IRET from those exceptions reenables NMI
443
+ * which is the opposite of what the NMI rendezvous is trying to achieve.
444
+ *
445
+ * The primary thread is safe versus instrumentation as the actual
446
+ * microcode update handles this correctly. It's only the sibling code
447
+ * path which must be NMI safe until the primary thread completed the
448
+ * update.
449
+ */
450
+ bool noinstr microcode_nmi_handler (void )
397
451
{
398
- if (!this_cpu_read (ucode_ctrl .nmi_enabled ))
452
+ if (!raw_cpu_read (ucode_ctrl .nmi_enabled ))
399
453
return false;
400
454
401
- this_cpu_write (ucode_ctrl .nmi_enabled , false);
455
+ raw_cpu_write (ucode_ctrl .nmi_enabled , false);
402
456
return microcode_update_handler ();
403
457
}
404
458
@@ -425,6 +479,7 @@ static int load_late_stop_cpus(void)
425
479
pr_err ("You should switch to early loading, if possible.\n" );
426
480
427
481
atomic_set (& late_cpus_in , num_online_cpus ());
482
+ loops_per_usec = loops_per_jiffy / (TICK_NSEC / 1000 );
428
483
429
484
/*
430
485
* Take a snapshot before the microcode update in order to compare and
0 commit comments