@@ -347,6 +347,9 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
347
347
cr4_clear_bits (X86_CR4_UMIP );
348
348
}
349
349
350
+ /* These bits should not change their value after CPU init is finished. */
351
+ static const unsigned long cr4_pinned_mask =
352
+ X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE ;
350
353
static DEFINE_STATIC_KEY_FALSE_RO (cr_pinning );
351
354
static unsigned long cr4_pinned_bits __ro_after_init ;
352
355
@@ -371,20 +374,20 @@ EXPORT_SYMBOL(native_write_cr0);
371
374
372
375
void native_write_cr4 (unsigned long val )
373
376
{
374
- unsigned long bits_missing = 0 ;
377
+ unsigned long bits_changed = 0 ;
375
378
376
379
set_register :
377
380
asm volatile ("mov %0,%%cr4" : "+r" (val ), "+m" (cr4_pinned_bits ));
378
381
379
382
if (static_branch_likely (& cr_pinning )) {
380
- if (unlikely ((val & cr4_pinned_bits ) != cr4_pinned_bits )) {
381
- bits_missing = ~ val & cr4_pinned_bits ;
382
- val |= bits_missing ;
383
+ if (unlikely ((val & cr4_pinned_mask ) != cr4_pinned_bits )) {
384
+ bits_changed = ( val & cr4_pinned_mask ) ^ cr4_pinned_bits ;
385
+ val = ( val & ~ cr4_pinned_mask ) | cr4_pinned_bits ;
383
386
goto set_register ;
384
387
}
385
- /* Warn after we've set the missing bits. */
386
- WARN_ONCE (bits_missing , "CR4 bits went missing: %lx!?\n" ,
387
- bits_missing );
388
+ /* Warn after we've corrected the changed bits. */
389
+ WARN_ONCE (bits_changed , "pinned CR4 bits changed: 0x %lx!?\n" ,
390
+ bits_changed );
388
391
}
389
392
}
390
393
#if IS_MODULE (CONFIG_LKDTM )
@@ -419,7 +422,7 @@ void cr4_init(void)
419
422
if (boot_cpu_has (X86_FEATURE_PCID ))
420
423
cr4 |= X86_CR4_PCIDE ;
421
424
if (static_branch_likely (& cr_pinning ))
422
- cr4 |= cr4_pinned_bits ;
425
+ cr4 = ( cr4 & ~ cr4_pinned_mask ) | cr4_pinned_bits ;
423
426
424
427
__write_cr4 (cr4 );
425
428
@@ -434,10 +437,7 @@ void cr4_init(void)
434
437
*/
435
438
static void __init setup_cr_pinning (void )
436
439
{
437
- unsigned long mask ;
438
-
439
- mask = (X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP );
440
- cr4_pinned_bits = this_cpu_read (cpu_tlbstate .cr4 ) & mask ;
440
+ cr4_pinned_bits = this_cpu_read (cpu_tlbstate .cr4 ) & cr4_pinned_mask ;
441
441
static_key_enable (& cr_pinning .key );
442
442
}
443
443
0 commit comments