x86/microcode/amd: Extract current patch level read to a function
Pave the way for checking the current patch level of the microcode in a core. We want to be able to do stuff depending on the patch level - in this case decide whether to update or not. But that will be added in a later patch. Drop unused local var uci assignment, while at it. Integrate a fix for 32-bit and CONFIG_PARAVIRT from Takashi Iwai: Use native_rdmsr() in check_current_patch_level() because with CONFIG_PARAVIRT enabled and on 32-bit, where we run before paging has been enabled, we cannot deref pv_info yet. Or we could, but we'd need to access its physical address. This way of fixing it is simpler. See: https://bugzilla.suse.com/show_bug.cgi?id=943179 for the background. Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Borislav Petkov <bp@alien8.de> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Takashi Iwai <tiwai@suse.com>: Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tony Luck <tony.luck@intel.com> Link: http://lkml.kernel.org/r/1444641762-9437-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
committed by
Ingo Molnar
parent
fa20a2ed6f
commit
2eff73c0a1
@@ -76,4 +76,5 @@ static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
|
|||||||
void reload_ucode_amd(void) {}
|
void reload_ucode_amd(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern bool check_current_patch_level(u32 *rev);
|
||||||
#endif /* _ASM_X86_MICROCODE_AMD_H */
|
#endif /* _ASM_X86_MICROCODE_AMD_H */
|
||||||
|
|||||||
@@ -177,6 +177,25 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
|
|||||||
return patch_size;
|
return patch_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the current patch level on this CPU.
|
||||||
|
*
|
||||||
|
* @rev: Use it to return the patch level. It is set to 0 in the case of
|
||||||
|
* error.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* - true: if update should stop
|
||||||
|
* - false: otherwise
|
||||||
|
*/
|
||||||
|
bool check_current_patch_level(u32 *rev)
|
||||||
|
{
|
||||||
|
u32 dummy;
|
||||||
|
|
||||||
|
native_rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int __apply_microcode_amd(struct microcode_amd *mc_amd)
|
int __apply_microcode_amd(struct microcode_amd *mc_amd)
|
||||||
{
|
{
|
||||||
u32 rev, dummy;
|
u32 rev, dummy;
|
||||||
@@ -197,7 +216,7 @@ int apply_microcode_amd(int cpu)
|
|||||||
struct microcode_amd *mc_amd;
|
struct microcode_amd *mc_amd;
|
||||||
struct ucode_cpu_info *uci;
|
struct ucode_cpu_info *uci;
|
||||||
struct ucode_patch *p;
|
struct ucode_patch *p;
|
||||||
u32 rev, dummy;
|
u32 rev;
|
||||||
|
|
||||||
BUG_ON(raw_smp_processor_id() != cpu);
|
BUG_ON(raw_smp_processor_id() != cpu);
|
||||||
|
|
||||||
@@ -210,7 +229,8 @@ int apply_microcode_amd(int cpu)
|
|||||||
mc_amd = p->data;
|
mc_amd = p->data;
|
||||||
uci->mc = p->data;
|
uci->mc = p->data;
|
||||||
|
|
||||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
if (check_current_patch_level(&rev))
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* need to apply patch? */
|
/* need to apply patch? */
|
||||||
if (rev >= mc_amd->hdr.patch_id) {
|
if (rev >= mc_amd->hdr.patch_id) {
|
||||||
|
|||||||
@@ -196,9 +196,8 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find ucode and update if needed */
|
if (check_current_patch_level(&rev))
|
||||||
|
return;
|
||||||
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
|
|
||||||
|
|
||||||
while (left > 0) {
|
while (left > 0) {
|
||||||
struct microcode_amd *mc;
|
struct microcode_amd *mc;
|
||||||
@@ -319,7 +318,6 @@ static void __init get_bsp_sig(void)
|
|||||||
void load_ucode_amd_ap(void)
|
void load_ucode_amd_ap(void)
|
||||||
{
|
{
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
|
||||||
struct equiv_cpu_entry *eq;
|
struct equiv_cpu_entry *eq;
|
||||||
struct microcode_amd *mc;
|
struct microcode_amd *mc;
|
||||||
u32 rev, eax;
|
u32 rev, eax;
|
||||||
@@ -332,10 +330,8 @@ void load_ucode_amd_ap(void)
|
|||||||
if (!container)
|
if (!container)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
|
if (check_current_patch_level(&rev))
|
||||||
|
return;
|
||||||
uci->cpu_sig.rev = rev;
|
|
||||||
uci->cpu_sig.sig = eax;
|
|
||||||
|
|
||||||
eax = cpuid_eax(0x00000001);
|
eax = cpuid_eax(0x00000001);
|
||||||
eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ);
|
eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ);
|
||||||
@@ -424,9 +420,10 @@ int __init save_microcode_in_initrd_amd(void)
|
|||||||
void reload_ucode_amd(void)
|
void reload_ucode_amd(void)
|
||||||
{
|
{
|
||||||
struct microcode_amd *mc;
|
struct microcode_amd *mc;
|
||||||
u32 rev, eax;
|
u32 rev;
|
||||||
|
|
||||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
|
if (check_current_patch_level(&rev))
|
||||||
|
return;
|
||||||
|
|
||||||
mc = (struct microcode_amd *)amd_ucode_patch;
|
mc = (struct microcode_amd *)amd_ucode_patch;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user