[4.15 & 4.14 stable 11/12] x86/microcode: Attempt late loading only when new microcode is present

2018-04-06 Thread Ashok Raj
From: Borislav Petkov 

commit 2613f36ed965d0e5a595a1d931fd3b480e82d6fd upstream

Return UCODE_NEW from the scanning functions to denote that new microcode
was found and only then attempt the expensive synchronization dance.

Reported-by: Emanuel Czirai 
Signed-off-by: Borislav Petkov 
Signed-off-by: Thomas Gleixner 
Tested-by: Emanuel Czirai 
Tested-by: Ashok Raj 
Tested-by: Tom Lendacky 
Cc: Tom Lendacky 
Cc: Asit K Mallick 
Cc: sta...@vger.kernel.org
Link: https://lkml.kernel.org/r/20180314183615.17629-1...@alien8.de
---
 arch/x86/include/asm/microcode.h  |  1 +
 arch/x86/kernel/cpu/microcode/amd.c   | 34 +-
 arch/x86/kernel/cpu/microcode/core.c  |  8 +++-
 arch/x86/kernel/cpu/microcode/intel.c |  4 +++-
 4 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 7fb1047..6cf0e4c 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -39,6 +39,7 @@ struct device;
 
 enum ucode_state {
UCODE_OK= 0,
+   UCODE_NEW,
UCODE_UPDATED,
UCODE_NFOUND,
UCODE_ERROR,
diff --git a/arch/x86/kernel/cpu/microcode/amd.c 
b/arch/x86/kernel/cpu/microcode/amd.c
index a998e1a..4817992 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -339,7 +339,7 @@ int __init save_microcode_in_initrd_amd(unsigned int 
cpuid_1_eax)
return -EINVAL;
 
ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, 
desc.size);
-   if (ret != UCODE_OK)
+   if (ret > UCODE_UPDATED)
return -EINVAL;
 
return 0;
@@ -683,27 +683,35 @@ static enum ucode_state __load_microcode_amd(u8 family, 
const u8 *data,
 static enum ucode_state
 load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
 {
+   struct ucode_patch *p;
enum ucode_state ret;
 
/* free old equiv table */
free_equiv_cpu_table();
 
ret = __load_microcode_amd(family, data, size);
-
-   if (ret != UCODE_OK)
+   if (ret != UCODE_OK) {
cleanup();
+   return ret;
+   }
 
-#ifdef CONFIG_X86_32
-   /* save BSP's matching patch for early load */
-   if (save) {
-   struct ucode_patch *p = find_patch(0);
-   if (p) {
-   memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
-   memcpy(amd_ucode_patch, p->data, min_t(u32, 
ksize(p->data),
-  PATCH_MAX_SIZE));
-   }
+   p = find_patch(0);
+   if (!p) {
+   return ret;
+   } else {
+   if (boot_cpu_data.microcode == p->patch_id)
+   return ret;
+
+   ret = UCODE_NEW;
}
-#endif
+
+   /* save BSP's matching patch for early load */
+   if (!save)
+   return ret;
+
+   memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
+   memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), 
PATCH_MAX_SIZE));
+
return ret;
 }
 
diff --git a/arch/x86/kernel/cpu/microcode/core.c 
b/arch/x86/kernel/cpu/microcode/core.c
index bde629e..e6d5caa 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -607,7 +607,7 @@ static ssize_t reload_store(struct device *dev,
return size;
 
tmp_ret = microcode_ops->request_microcode_fw(bsp, 
_pdev->dev, true);
-   if (tmp_ret != UCODE_OK)
+   if (tmp_ret != UCODE_NEW)
return size;
 
get_online_cpus();
@@ -691,10 +691,8 @@ static enum ucode_state microcode_init_cpu(int cpu, bool 
refresh_fw)
if (system_state != SYSTEM_RUNNING)
return UCODE_NFOUND;
 
-   ustate = microcode_ops->request_microcode_fw(cpu, _pdev->dev,
-refresh_fw);
-
-   if (ustate == UCODE_OK) {
+   ustate = microcode_ops->request_microcode_fw(cpu, _pdev->dev, 
refresh_fw);
+   if (ustate == UCODE_NEW) {
pr_debug("CPU%d updated upon init\n", cpu);
apply_microcode_on_target(cpu);
}
diff --git a/arch/x86/kernel/cpu/microcode/intel.c 
b/arch/x86/kernel/cpu/microcode/intel.c
index 2aded9d..32b8e57 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -862,6 +862,7 @@ static enum ucode_state generic_load_microcode(int cpu, 
void *data, size_t size,
unsigned int leftover = size;
unsigned int curr_mc_size = 0, new_mc_size = 0;
unsigned int csig, cpf;
+   enum ucode_state ret = UCODE_OK;
 
while (leftover) {
struct microcode_header_intel mc_header;

[4.15 & 4.14 stable 11/12] x86/microcode: Attempt late loading only when new microcode is present

2018-04-06 Thread Ashok Raj
From: Borislav Petkov 

commit 2613f36ed965d0e5a595a1d931fd3b480e82d6fd upstream

Return UCODE_NEW from the scanning functions to denote that new microcode
was found and only then attempt the expensive synchronization dance.

Reported-by: Emanuel Czirai 
Signed-off-by: Borislav Petkov 
Signed-off-by: Thomas Gleixner 
Tested-by: Emanuel Czirai 
Tested-by: Ashok Raj 
Tested-by: Tom Lendacky 
Cc: Tom Lendacky 
Cc: Asit K Mallick 
Cc: sta...@vger.kernel.org
Link: https://lkml.kernel.org/r/20180314183615.17629-1...@alien8.de
---
 arch/x86/include/asm/microcode.h  |  1 +
 arch/x86/kernel/cpu/microcode/amd.c   | 34 +-
 arch/x86/kernel/cpu/microcode/core.c  |  8 +++-
 arch/x86/kernel/cpu/microcode/intel.c |  4 +++-
 4 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 7fb1047..6cf0e4c 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -39,6 +39,7 @@ struct device;
 
 enum ucode_state {
UCODE_OK= 0,
+   UCODE_NEW,
UCODE_UPDATED,
UCODE_NFOUND,
UCODE_ERROR,
diff --git a/arch/x86/kernel/cpu/microcode/amd.c 
b/arch/x86/kernel/cpu/microcode/amd.c
index a998e1a..4817992 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -339,7 +339,7 @@ int __init save_microcode_in_initrd_amd(unsigned int 
cpuid_1_eax)
return -EINVAL;
 
ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, 
desc.size);
-   if (ret != UCODE_OK)
+   if (ret > UCODE_UPDATED)
return -EINVAL;
 
return 0;
@@ -683,27 +683,35 @@ static enum ucode_state __load_microcode_amd(u8 family, 
const u8 *data,
 static enum ucode_state
 load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
 {
+   struct ucode_patch *p;
enum ucode_state ret;
 
/* free old equiv table */
free_equiv_cpu_table();
 
ret = __load_microcode_amd(family, data, size);
-
-   if (ret != UCODE_OK)
+   if (ret != UCODE_OK) {
cleanup();
+   return ret;
+   }
 
-#ifdef CONFIG_X86_32
-   /* save BSP's matching patch for early load */
-   if (save) {
-   struct ucode_patch *p = find_patch(0);
-   if (p) {
-   memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
-   memcpy(amd_ucode_patch, p->data, min_t(u32, 
ksize(p->data),
-  PATCH_MAX_SIZE));
-   }
+   p = find_patch(0);
+   if (!p) {
+   return ret;
+   } else {
+   if (boot_cpu_data.microcode == p->patch_id)
+   return ret;
+
+   ret = UCODE_NEW;
}
-#endif
+
+   /* save BSP's matching patch for early load */
+   if (!save)
+   return ret;
+
+   memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
+   memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), 
PATCH_MAX_SIZE));
+
return ret;
 }
 
diff --git a/arch/x86/kernel/cpu/microcode/core.c 
b/arch/x86/kernel/cpu/microcode/core.c
index bde629e..e6d5caa 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -607,7 +607,7 @@ static ssize_t reload_store(struct device *dev,
return size;
 
tmp_ret = microcode_ops->request_microcode_fw(bsp, 
_pdev->dev, true);
-   if (tmp_ret != UCODE_OK)
+   if (tmp_ret != UCODE_NEW)
return size;
 
get_online_cpus();
@@ -691,10 +691,8 @@ static enum ucode_state microcode_init_cpu(int cpu, bool 
refresh_fw)
if (system_state != SYSTEM_RUNNING)
return UCODE_NFOUND;
 
-   ustate = microcode_ops->request_microcode_fw(cpu, _pdev->dev,
-refresh_fw);
-
-   if (ustate == UCODE_OK) {
+   ustate = microcode_ops->request_microcode_fw(cpu, _pdev->dev, 
refresh_fw);
+   if (ustate == UCODE_NEW) {
pr_debug("CPU%d updated upon init\n", cpu);
apply_microcode_on_target(cpu);
}
diff --git a/arch/x86/kernel/cpu/microcode/intel.c 
b/arch/x86/kernel/cpu/microcode/intel.c
index 2aded9d..32b8e57 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -862,6 +862,7 @@ static enum ucode_state generic_load_microcode(int cpu, 
void *data, size_t size,
unsigned int leftover = size;
unsigned int curr_mc_size = 0, new_mc_size = 0;
unsigned int csig, cpf;
+   enum ucode_state ret = UCODE_OK;
 
while (leftover) {
struct microcode_header_intel mc_header;
@@ -903,6 +904,7 @@ static enum ucode_state generic_load_microcode(int cpu, 
void *data, size_t size,
new_mc  = mc;
new_mc_size = mc_size;