public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ashok Raj <ashok.raj@intel.com>
To: Dave Hansen <dave.hansen@intel.com>
Cc: Borislav Petkov <bp@alien8.de>,
	Thomas Gleixner <tglx@linutronix.de>, X86-kernel <x86@kernel.org>,
	LKML Mailing List <linux-kernel@vger.kernel.org>,
	Tony Luck <tony.luck@intel.com>,
	"Alison Schofield" <alison.schofield@intel.com>,
	Reinette Chatre <reinette.chatre@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	"Ashok Raj" <ashok.raj@intel.com>
Subject: Re: [PATCH v3 2/6] x86/microcode/core: Take a snapshot before and after applying microcode
Date: Tue, 3 Jan 2023 11:37:54 -0800	[thread overview]
Message-ID: <Y7SEEtHdeKmPchJ0@a4bf019067fa.jf.intel.com> (raw)
In-Reply-To: <efafb54e-5447-fd5e-8f8b-1fc150087d35@intel.com>

On Tue, Jan 03, 2023 at 10:46:56AM -0800, Dave Hansen wrote:
> On 1/3/23 10:02, Ashok Raj wrote:
> > The kernel caches features about each CPU's features at boot in an
> > x86_capability[] structure. The microcode update takes one snapshot and
> > compares it with the saved copy at boot.
> > 
> > However, the capabilities in the boot copy can be turned off as a result of
> > certain command line parameters or configuration restrictions. This can
> > cause a mismatch when comparing the values before and after the microcode
> > update.
> > 
> > microcode_check() is called after an update to report any previously
> > cached CPUID bits might have changed due to the update.
> > 
> > microcode_store_cpu_caps() basically stores the original CPU reported
> > values and not the OS modified values. This will avoid giving a false
> > warning even if no capabilities have changed.
> > 
> > Ignore the capabilities recorded at boot. Take a new snapshot before the
> > update and compare with a snapshot after the update to eliminate the false
> > warning.
> ...
> 
> It took me a moment to square this "Ignore the capabilities recorded at
> boot." statement with the continued existence of:
> 
> 	memcpy(info->x86_capability, &boot_cpu_data.x86_capability, ...
> 
> I think just adding "hardware" might help:
> 
> 	Ignore all hardware capabilities recorded at boot.
> 
> Or even adding one more sentence:
> 
> 	Only consult the synthetic capabilities recorded at boot so that
> 	a simple memcmp() can be used for comparisons.

Rewritten this multiple times, but it still seems confusing, however hard I
try :-(

Its not consulting just the synthetic capabilties, but all real
capabilities reported by hardware including synthetic ones. For e.g. 
if we turn off SGX, but HW still exposes it, the new snapshot will 
have SGX but previous copy doesn't as it has gone through some more
filtering during enabling. That is what resulted in the miscompare. 

Does this replacement sound better?

Ignore any changes to capabilities applied by the kernel during any
feature enabling and check against raw capabilities exposed by the
hardware


> 
> > diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
> > index 387578049de0..ac2e67156b9b 100644
> > --- a/arch/x86/include/asm/processor.h
> > +++ b/arch/x86/include/asm/processor.h
> > @@ -697,6 +697,7 @@ bool xen_set_default_idle(void);
> >  #endif
> >  
> >  void __noreturn stop_this_cpu(void *dummy);
> > +void microcode_store_cpu_caps(struct cpuinfo_x86 *info);
> >  void microcode_check(struct cpuinfo_x86 *info);
> >  
> >  enum l1tf_mitigations {
> > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> > index b9c7529c920e..7c86c6fd07ae 100644
> > --- a/arch/x86/kernel/cpu/common.c
> > +++ b/arch/x86/kernel/cpu/common.c
> > @@ -2297,28 +2297,43 @@ void cpu_init_secondary(void)
> >  #endif
> >  
> >  #ifdef CONFIG_MICROCODE_LATE_LOADING
> > +
> > +void microcode_store_cpu_caps(struct cpuinfo_x86 *info)
> > +{
> > +	/* Reload CPUID max function as it might've changed. */
> > +	info->cpuid_level = cpuid_eax(0);
> > +
> > +	/*
> > +	 * Copy all capability leafs to pick up the synthetic ones so that
> > +	 * memcmp() below doesn't fail on that. The ones coming from CPUID will
> > +	 * get overwritten in get_cpu_cap().
> > +	 */
> > +	memcpy(info->x86_capability, &boot_cpu_data.x86_capability,
> > +	       sizeof(info->x86_capability));
> > +
> > +	get_cpu_cap(info);
> > +}
> > +
> >  /*
> >   * The microcode loader calls this upon late microcode load to recheck features,
> >   * only when microcode has been updated. Caller holds microcode_mutex and CPU
> >   * hotplug lock.
> >   */
> > -void microcode_check(struct cpuinfo_x86 *info)
> > +void microcode_check(struct cpuinfo_x86 *orig)
> >  {
> > -	perf_check_microcode();
> > +	struct cpuinfo_x86 info;
> 
> 'info' is kinda a throwaway name.  would this be better as:
> 
> 	prev_info / new_info
> 
> instead of:
> 
> 	orig / info
> 
> ?

Yes, that sounds better.

> 
> > -	/* Reload CPUID max function as it might've changed. */
> > -	info->cpuid_level = cpuid_eax(0);
> > +	perf_check_microcode();
> >  
> >  	/*
> >  	 * Copy all capability leafs to pick up the synthetic ones so that
> >  	 * memcmp() below doesn't fail on that. The ones coming from CPUID will
> >  	 * get overwritten in get_cpu_cap().
> >  	 */
> 
> This comment got copied to microcode_store_cpu_caps().  Does this
> instance still need to be here?

I think it still applies.. get_cpu_cap() copies all reported capabilities
and adds the synthetic ones too.

> 
> > -	memcpy(&info->x86_capability, &boot_cpu_data.x86_capability, sizeof(info->x86_capability));
> > -
> > -	get_cpu_cap(info);
> > +	microcode_store_cpu_caps(&info);
> >  
> > -	if (!memcmp(&info->x86_capability, &boot_cpu_data.x86_capability, sizeof(info->x86_capability)))
> > +	if (!memcmp(&info.x86_capability, &orig->x86_capability,
> > +		    sizeof(info.x86_capability)))
> >  		return;
> >  
> >  	pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
> > diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
> > index d86a4f910a6b..14d9031ed68a 100644
> > --- a/arch/x86/kernel/cpu/microcode/core.c
> > +++ b/arch/x86/kernel/cpu/microcode/core.c
> > @@ -447,6 +447,13 @@ static int microcode_reload_late(void)
> >  	atomic_set(&late_cpus_in,  0);
> >  	atomic_set(&late_cpus_out, 0);
> >  
> > +	/*
> > +	 * Take a snapshot before the microcode update, so we can compare
> > +	 * them after the update is successful to check for any bits
> > +	 * changed.
> > +	 */
> > +	microcode_store_cpu_caps(&info);
> 
> A "we" snuck in there.  How about this?
> 
> 	/*
> 	 * Take a snapshot before the microcode update.  This enables
> 	 * a later comparison to see any bits changed after an update.
> 	 */
> 
> I do think some better naming of 'info' here would be nice too.
> 'old_info' or 'prev_info' seem like good alternatives.

Sounds good. 

Cheers,
Ashok

  reply	other threads:[~2023-01-03 19:38 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-03 18:02 [PATCH v3 0/6] Some fixes and cleanups for microcode Ashok Raj
2023-01-03 18:02 ` [PATCH v3 1/6] x86/microcode: Add a parameter to microcode_check() to store CPU capabilities Ashok Raj
2023-01-04 18:21   ` Borislav Petkov
2023-01-03 18:02 ` [PATCH v3 2/6] x86/microcode/core: Take a snapshot before and after applying microcode Ashok Raj
2023-01-03 18:46   ` Dave Hansen
2023-01-03 19:37     ` Ashok Raj [this message]
2023-01-04 18:56   ` Borislav Petkov
2023-01-06 20:41     ` Ashok Raj
2023-01-03 18:02 ` [PATCH v3 3/6] x86/microcode: Display revisions only when update is successful Ashok Raj
2023-01-04 19:00   ` Borislav Petkov
2023-01-06 19:42     ` Ashok Raj
2023-01-06 19:54       ` Borislav Petkov
2023-01-06 20:29         ` Ashok Raj
2023-01-06 20:45           ` Borislav Petkov
2023-01-06 21:20             ` Ashok Raj
2023-01-07  9:36             ` Ingo Molnar
2023-01-06 21:35         ` Luck, Tony
2023-01-06 21:52           ` Borislav Petkov
2023-01-03 18:02 ` [PATCH v3 4/6] x86/microcode/intel: Use a plain revision argument for print_ucode_rev() Ashok Raj
2023-01-03 18:02 ` [PATCH v3 5/6] x86/microcode/intel: Print old and new rev during early boot Ashok Raj
2023-01-03 18:02 ` [PATCH v3 6/6] x86/microcode/intel: Print when early microcode loading fails Ashok Raj

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y7SEEtHdeKmPchJ0@a4bf019067fa.jf.intel.com \
    --to=ashok.raj@intel.com \
    --cc=alison.schofield@intel.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=reinette.chatre@intel.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox