All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
@ 2015-07-01 20:14 Borislav Petkov
  2015-07-01 20:14 ` [PATCH 1/2] x86/microcode/amd: Extract current patch level read to a function Borislav Petkov
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Borislav Petkov @ 2015-07-01 20:14 UTC (permalink / raw)
  To: LKML; +Cc: Aravind Gopalakrishnan, X86 ML

From: Borislav Petkov <bp@suse.de>

Certain patch levels supplied by the BIOS should not be upgraded and
overwritten by the microcode loader because doing so leaves the system
dead in the water.

The two below provide for filtering out those levels and avoiding the
update, thereby making those patch levels final.

Borislav Petkov (2):
  x86/microcode/amd: Extract current patch level read to a function
  x86/microcode/amd: Do not overwrite final patch levels

 arch/x86/include/asm/microcode_amd.h      |  1 +
 arch/x86/kernel/cpu/microcode/amd.c       | 52 +++++++++++++++++++++++++++++--
 arch/x86/kernel/cpu/microcode/amd_early.c | 24 ++++++++------
 3 files changed, 65 insertions(+), 12 deletions(-)

-- 
2.3.5


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] x86/microcode/amd: Extract current patch level read to a function
  2015-07-01 20:14 [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels Borislav Petkov
@ 2015-07-01 20:14 ` Borislav Petkov
  2015-07-01 20:14 ` [PATCH 2/2] x86/microcode/amd: Do not overwrite final patch levels Borislav Petkov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Borislav Petkov @ 2015-07-01 20:14 UTC (permalink / raw)
  To: LKML; +Cc: Aravind Gopalakrishnan, X86 ML

From: Borislav Petkov <bp@suse.de>

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; here we do not introduce any functionality change.

Drop unused local var uci assignment, while at it.

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/include/asm/microcode_amd.h      |  1 +
 arch/x86/kernel/cpu/microcode/amd.c       | 24 ++++++++++++++++++++++--
 arch/x86/kernel/cpu/microcode/amd_early.c | 17 +++++++----------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index ac6d328977a6..9b214e10d499 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -76,4 +76,5 @@ static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
 void reload_ucode_amd(void) {}
 #endif
 
+extern bool check_current_patch_level(u32 *rev);
 #endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 12829c3ced3c..59a36125bf7f 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -177,6 +177,25 @@ static unsigned int verify_patch_size(u8 family, u32 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;
+
+	rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
+
+	return false;
+}
+
 int __apply_microcode_amd(struct microcode_amd *mc_amd)
 {
 	u32 rev, dummy;
@@ -197,7 +216,7 @@ int apply_microcode_amd(int cpu)
 	struct microcode_amd *mc_amd;
 	struct ucode_cpu_info *uci;
 	struct ucode_patch *p;
-	u32 rev, dummy;
+	u32 rev;
 
 	BUG_ON(raw_smp_processor_id() != cpu);
 
@@ -210,7 +229,8 @@ int apply_microcode_amd(int cpu)
 	mc_amd  = 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? */
 	if (rev >= mc_amd->hdr.patch_id) {
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
index e8a215a9a345..abb90097582f 100644
--- a/arch/x86/kernel/cpu/microcode/amd_early.c
+++ b/arch/x86/kernel/cpu/microcode/amd_early.c
@@ -196,9 +196,8 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
 		return;
 	}
 
-	/* find ucode and update if needed */
-
-	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
+	if (check_current_patch_level(&rev))
+		return;
 
 	while (left > 0) {
 		struct microcode_amd *mc;
@@ -319,7 +318,6 @@ static void __init get_bsp_sig(void)
 void load_ucode_amd_ap(void)
 {
 	unsigned int cpu = smp_processor_id();
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	struct equiv_cpu_entry *eq;
 	struct microcode_amd *mc;
 	u32 rev, eax;
@@ -332,10 +330,8 @@ void load_ucode_amd_ap(void)
 	if (!container)
 		return;
 
-	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
-
-	uci->cpu_sig.rev = rev;
-	uci->cpu_sig.sig = eax;
+	if (check_current_patch_level(&rev))
+		return;
 
 	eax = cpuid_eax(0x00000001);
 	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)
 {
 	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;
 
-- 
2.3.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] x86/microcode/amd: Do not overwrite final patch levels
  2015-07-01 20:14 [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels Borislav Petkov
  2015-07-01 20:14 ` [PATCH 1/2] x86/microcode/amd: Extract current patch level read to a function Borislav Petkov
@ 2015-07-01 20:14 ` Borislav Petkov
  2015-07-09 15:03 ` [PATCH 0/2] x86/microcode/amd: Do not overwrite specific " Henrique de Moraes Holschuh
  2016-03-26 23:31 ` Henrique de Moraes Holschuh
  3 siblings, 0 replies; 13+ messages in thread
From: Borislav Petkov @ 2015-07-01 20:14 UTC (permalink / raw)
  To: LKML; +Cc: Aravind Gopalakrishnan, X86 ML

From: Borislav Petkov <bp@suse.de>

A certain number of patch levels of applied microcode should not be
overwritten by the microcode loader, otherwise bad things will happen.

Check those and abort update if the current core has one of those final
patch levels applied by the BIOS. 32-bit needs special handling, of
course.

See https://bugzilla.suse.com/show_bug.cgi?id=913996 for more info.

Tested-by: Peter Kirchgeßner <pkirchgessner@t-online.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/include/asm/microcode_amd.h      |  2 +-
 arch/x86/kernel/cpu/microcode/amd.c       | 38 +++++++++++++++++++++++++++----
 arch/x86/kernel/cpu/microcode/amd_early.c | 13 ++++++++---
 3 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 9b214e10d499..d3e86cfd08fe 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -76,5 +76,5 @@ static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
 void reload_ucode_amd(void) {}
 #endif
 
-extern bool check_current_patch_level(u32 *rev);
+extern bool check_current_patch_level(u32 *rev, bool early);
 #endif /* _ASM_X86_MICROCODE_AMD_H */
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 59a36125bf7f..c7d2415b8a24 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -178,6 +178,16 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
 }
 
 /*
+ * Those patch levels cannot be updated to newer ones and thus should be final.
+ */
+static u32 final_levels[] = {
+	0x01000098,
+	0x0100009f,
+	0x010000af,
+	0, /* T-101 terminator */
+};
+
+/*
  * 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
@@ -187,13 +197,31 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
  *  - true: if update should stop
  *  - false: otherwise
  */
-bool check_current_patch_level(u32 *rev)
+bool check_current_patch_level(u32 *rev, bool early)
 {
-	u32 dummy;
+	u32 lvl, dummy, i;
+	bool ret = false;
+	u32 *levels;
+
+	rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy);
+
+	if (IS_ENABLED(CONFIG_X86_32) && early)
+		levels = (u32 *)__pa_nodebug(&final_levels);
+	else
+		levels = final_levels;
+
+	for (i = 0; levels[i]; i++) {
+		if (lvl == levels[i]) {
+			lvl = 0;
+			ret = true;
+			break;
+		}
+	}
 
-	rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
+	if (rev)
+		*rev = lvl;
 
-	return false;
+	return ret;
 }
 
 int __apply_microcode_amd(struct microcode_amd *mc_amd)
@@ -229,7 +257,7 @@ int apply_microcode_amd(int cpu)
 	mc_amd  = p->data;
 	uci->mc = p->data;
 
-	if (check_current_patch_level(&rev))
+	if (check_current_patch_level(&rev, false))
 		return -1;
 
 	/* need to apply patch? */
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c
index abb90097582f..a54a47b9d8ea 100644
--- a/arch/x86/kernel/cpu/microcode/amd_early.c
+++ b/arch/x86/kernel/cpu/microcode/amd_early.c
@@ -196,7 +196,7 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
 		return;
 	}
 
-	if (check_current_patch_level(&rev))
+	if (check_current_patch_level(&rev, true))
 		return;
 
 	while (left > 0) {
@@ -330,7 +330,10 @@ void load_ucode_amd_ap(void)
 	if (!container)
 		return;
 
-	if (check_current_patch_level(&rev))
+	/*
+	 * 64-bit runs with paging enabled, thus early==false.
+	 */
+	if (check_current_patch_level(&rev, false))
 		return;
 
 	eax = cpuid_eax(0x00000001);
@@ -422,7 +425,11 @@ void reload_ucode_amd(void)
 	struct microcode_amd *mc;
 	u32 rev;
 
-	if (check_current_patch_level(&rev))
+	/*
+	 * early==false because this is a syscore ->resume path and by
+	 * that time paging is long enabled.
+	 */
+	if (check_current_patch_level(&rev, false))
 		return;
 
 	mc = (struct microcode_amd *)amd_ucode_patch;
-- 
2.3.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2015-07-01 20:14 [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels Borislav Petkov
  2015-07-01 20:14 ` [PATCH 1/2] x86/microcode/amd: Extract current patch level read to a function Borislav Petkov
  2015-07-01 20:14 ` [PATCH 2/2] x86/microcode/amd: Do not overwrite final patch levels Borislav Petkov
@ 2015-07-09 15:03 ` Henrique de Moraes Holschuh
  2015-07-10 10:11   ` Borislav Petkov
  2016-03-26 23:31 ` Henrique de Moraes Holschuh
  3 siblings, 1 reply; 13+ messages in thread
From: Henrique de Moraes Holschuh @ 2015-07-09 15:03 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: LKML, Aravind Gopalakrishnan, X86 ML

On Wed, 01 Jul 2015, Borislav Petkov wrote:
> Certain patch levels supplied by the BIOS should not be upgraded and
> overwritten by the microcode loader because doing so leaves the system
> dead in the water.
> 
> The two below provide for filtering out those levels and avoiding the
> update, thereby making those patch levels final.

Is there any way to notify the user that 'processor microcode updates are
not available on this system except through a firmware update' ?

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2015-07-09 15:03 ` [PATCH 0/2] x86/microcode/amd: Do not overwrite specific " Henrique de Moraes Holschuh
@ 2015-07-10 10:11   ` Borislav Petkov
  2015-07-10 15:12     ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 13+ messages in thread
From: Borislav Petkov @ 2015-07-10 10:11 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: LKML, Aravind Gopalakrishnan, X86 ML

On Thu, Jul 09, 2015 at 12:03:41PM -0300, Henrique de Moraes Holschuh wrote:
> Is there any way to notify the user that 'processor microcode updates
> are not available on this system except through a firmware update' ?

What for?

Those microcode patch levels are final and shouldn't be upgraded at all.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2015-07-10 10:11   ` Borislav Petkov
@ 2015-07-10 15:12     ` Henrique de Moraes Holschuh
  0 siblings, 0 replies; 13+ messages in thread
From: Henrique de Moraes Holschuh @ 2015-07-10 15:12 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: LKML, Aravind Gopalakrishnan, X86 ML

On Fri, 10 Jul 2015, Borislav Petkov wrote:
> On Thu, Jul 09, 2015 at 12:03:41PM -0300, Henrique de Moraes Holschuh wrote:
> > Is there any way to notify the user that 'processor microcode updates
> > are not available on this system except through a firmware update' ?
> 
> What for?
> 
> Those microcode patch levels are final and shouldn't be upgraded at all.

Yes, I understand that the operating system is not to attempt to update any
microcode that is listed as 'final'.

However, if that requirement exists because a microcode update applied by
the operating system would interact badly with the current firmware (or
microcode), the user could still get newer microcode (and better features,
errata workarounds, etc) through a full firmware (BIOS/EFI) update.

OTOH, if this is a 'microcode updates newer than the 'final' version exist
only to support changed hardware designs', and thus a board that already
works with 'final' should never need newer microcode, it would be nice to
know that fact.

Anyway, the code does not look like what I would expect if it is the later
case ("updates past 'final' exist only to support for changed hardware
design): it blacklists updates from 'final' to anything else, but it still
allows microcode with a version that is less than 'final' to be updated to
something that is higher than 'final', etc.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2015-07-01 20:14 [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels Borislav Petkov
                   ` (2 preceding siblings ...)
  2015-07-09 15:03 ` [PATCH 0/2] x86/microcode/amd: Do not overwrite specific " Henrique de Moraes Holschuh
@ 2016-03-26 23:31 ` Henrique de Moraes Holschuh
  2016-03-27  8:31   ` Borislav Petkov
  3 siblings, 1 reply; 13+ messages in thread
From: Henrique de Moraes Holschuh @ 2016-03-26 23:31 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: LKML, X86 ML

On Wed, 01 Jul 2015, Borislav Petkov wrote:
> Certain patch levels supplied by the BIOS should not be upgraded and
> overwritten by the microcode loader because doing so leaves the system
> dead in the water.
> 
> The two below provide for filtering out those levels and avoiding the
> update, thereby making those patch levels final.
> 
> Borislav Petkov (2):
>   x86/microcode/amd: Extract current patch level read to a function
>   x86/microcode/amd: Do not overwrite final patch levels

This patchset looks like it is pretty much a requirement for any distro that
ships AMD microcode updates...  Maybe the two commits should be sent to
-stable, now that they have seen lots of testing in mainline 4.4.x as well
as SuSE kernels?

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-03-26 23:31 ` Henrique de Moraes Holschuh
@ 2016-03-27  8:31   ` Borislav Petkov
  2016-03-27 12:32     ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 13+ messages in thread
From: Borislav Petkov @ 2016-03-27  8:31 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: LKML, X86 ML

On Sat, Mar 26, 2016 at 08:31:57PM -0300, Henrique de Moraes Holschuh wrote:
> This patchset looks like it is pretty much a requirement for any distro that
> ships AMD microcode updates...  Maybe the two commits should be sent to
> -stable, now that they have seen lots of testing in mainline 4.4.x as well
> as SuSE kernels?

I wouldn't say lots... :)

Do you have any specific bug report(s) or similar in mind? Or is it more
of a "it would be wise to backport" sentiment?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-03-27  8:31   ` Borislav Petkov
@ 2016-03-27 12:32     ` Henrique de Moraes Holschuh
  2016-03-27 15:47       ` Borislav Petkov
  0 siblings, 1 reply; 13+ messages in thread
From: Henrique de Moraes Holschuh @ 2016-03-27 12:32 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: LKML, X86 ML

On Sun, 27 Mar 2016, Borislav Petkov wrote:
> On Sat, Mar 26, 2016 at 08:31:57PM -0300, Henrique de Moraes Holschuh wrote:
> > This patchset looks like it is pretty much a requirement for any distro that
> > ships AMD microcode updates...  Maybe the two commits should be sent to
> > -stable, now that they have seen lots of testing in mainline 4.4.x as well
> > as SuSE kernels?
> 
> I wouldn't say lots... :)
> 
> Do you have any specific bug report(s) or similar in mind? Or is it more
> of a "it would be wise to backport" sentiment?

Well, a Google search shows that microcodes 0x100098 and 0x100009f are not
that rare.  IMHO, it is a pretty safe bet that both Debian and Ubuntu have
some users of those microcodes.  Users who will have their systems rendered
unbootable (until we teach them about the dis_ucode_ldr parameter to the
kernel) if they ever install the amd64-microcode package in a kernel that
doesn't have this patchset.

So, it is really a bit of both: I had several "it doesn't work" type of
reports for both AMD and Intel over the years, and most often people won't
come back to the initial bug report, if they even go that far as to report a
bug in the first place: they just remove the microcode update packages and
disapear...  so, I wouldn't know if any were due to this specific issue
except by luck.

But I do assume there are at least 20 users having trouble that will never
report it for each single bug report I get, and it is likely to be a lot
more :-(

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-03-27 12:32     ` Henrique de Moraes Holschuh
@ 2016-03-27 15:47       ` Borislav Petkov
  2016-05-02 15:30         ` Borislav Petkov
  0 siblings, 1 reply; 13+ messages in thread
From: Borislav Petkov @ 2016-03-27 15:47 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: LKML, X86 ML

On Sun, Mar 27, 2016 at 09:32:18AM -0300, Henrique de Moraes Holschuh wrote:
> So, it is really a bit of both: I had several "it doesn't work" type of
> reports for both AMD and Intel over the years, and most often people won't
> come back to the initial bug report,

Can you CC me on stuff like that too, please.

But yeah, unfortunately, bug reporters disappear and it is kinda hard to
debug an issue then. Which is sad. :-\

But ok. I'll put it on my TODO, will get to it eventually. Unless you
beat me to it... :)

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-03-27 15:47       ` Borislav Petkov
@ 2016-05-02 15:30         ` Borislav Petkov
  2016-05-06 12:43           ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 13+ messages in thread
From: Borislav Petkov @ 2016-05-02 15:30 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: LKML, X86 ML

[-- Attachment #1: Type: text/plain, Size: 367 bytes --]

On Sun, Mar 27, 2016 at 05:47:48PM +0200, Borislav Petkov wrote:
> But ok. I'll put it on my TODO, will get to it eventually. Unless you
> beat me to it... :)

Ok, I'm attaching the backports for 3.2. Care to give them a run too,
just in case? Seem to work here on my test box...

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

[-- Attachment #2: 0001-x86-microcode-amd-Extract-current-patch-level-read-t.patch --]
[-- Type: text/x-diff, Size: 3373 bytes --]

>From 2eff73c0a11f19ff082a566e3429fbaaca7b8e7b Mon Sep 17 00:00:00 2001
From: Borislav Petkov <bp@suse.de>
Date: Mon, 12 Oct 2015 11:22:41 +0200
Subject: [PATCH] x86/microcode/amd: Extract current patch level read to a
 function

Commit 2eff73c0a11f19ff082a566e3429fbaaca7b8e7b upstream.

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>
---
 arch/x86/include/asm/microcode.h      |  1 +
 arch/x86/kernel/microcode_amd.c       | 24 ++++++++++++++++++++++--
 3 files changed, 30 insertions(+), 12 deletions(-)

Index: linux/arch/x86/include/asm/microcode.h
===================================================================
--- linux.orig/arch/x86/include/asm/microcode.h	2016-05-02 12:20:08.364728800 +0200
+++ linux/arch/x86/include/asm/microcode.h	2016-05-02 12:20:31.944728581 +0200
@@ -61,4 +61,5 @@ static inline struct microcode_ops * __i
 }
 #endif
 
+extern bool check_current_patch_level(u32 *rev);
 #endif /* _ASM_X86_MICROCODE_H */
Index: linux/arch/x86/kernel/microcode_amd.c
===================================================================
--- linux.orig/arch/x86/kernel/microcode_amd.c	2016-05-02 12:20:08.364728800 +0200
+++ linux/arch/x86/kernel/microcode_amd.c	2016-05-02 12:24:35.768726320 +0200
@@ -123,13 +123,32 @@ static int get_matching_microcode(int cp
 	return 1;
 }
 
+/*
+ * 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;
+
+	rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
+
+	return false;
+}
+
 static int apply_microcode_amd(int cpu)
 {
-	u32 rev, dummy;
 	int cpu_num = raw_smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 	struct microcode_amd *mc_amd = uci->mc;
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	u32 dummy, rev;
 
 	/* We should bind the task to the CPU */
 	BUG_ON(cpu_num != cpu);
@@ -137,6 +156,9 @@ static int apply_microcode_amd(int cpu)
 	if (mc_amd == NULL)
 		return 0;
 
+	if (check_current_patch_level(&rev))
+		return -1;
+
 	wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
 	/* get patch id after patching */
 	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);

[-- Attachment #3: 0002-x86-microcode-amd-Do-not-overwrite-final-patch-level.patch --]
[-- Type: text/x-diff, Size: 3591 bytes --]

>From 0399f73299f1b7e04de329050f7111b362b7eeb5 Mon Sep 17 00:00:00 2001
From: Borislav Petkov <bp@suse.de>
Date: Mon, 12 Oct 2015 11:22:42 +0200
Subject: [PATCH] x86/microcode/amd: Do not overwrite final patch levels
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Commit 0399f73299f1b7e04de329050f7111b362b7eeb5 upstream.

A certain number of patch levels of applied microcode should not
be overwritten by the microcode loader, otherwise bad things
will happen.

Check those and abort update if the current core has one of
those final patch levels applied by the BIOS. 32-bit needs
special handling, of course.

See https://bugzilla.suse.com/show_bug.cgi?id=913996 for more
info.

Tested-by: Peter Kirchgeßner <pkirchgessner@t-online.de>
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: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Link: http://lkml.kernel.org/r/1444641762-9437-7-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/microcode.h      |  2 +-
 arch/x86/kernel/cpu/microcode/amd.c       | 38 +++++++++++++++++++++++++++----
 arch/x86/kernel/cpu/microcode/amd_early.c | 13 ++++++++---
 3 files changed, 44 insertions(+), 9 deletions(-)

Index: linux/arch/x86/include/asm/microcode.h
===================================================================
--- linux.orig/arch/x86/include/asm/microcode.h	2016-05-02 13:40:48.980683909 +0200
+++ linux/arch/x86/include/asm/microcode.h	2016-05-02 13:40:48.976683909 +0200
@@ -61,5 +61,5 @@ static inline struct microcode_ops * __i
 }
 #endif
 
-extern bool check_current_patch_level(u32 *rev);
+extern bool check_current_patch_level(u32 *rev, bool early);
 #endif /* _ASM_X86_MICROCODE_H */
Index: linux/arch/x86/kernel/microcode_amd.c
===================================================================
--- linux.orig/arch/x86/kernel/microcode_amd.c	2016-05-02 13:40:48.980683909 +0200
+++ linux/arch/x86/kernel/microcode_amd.c	2016-05-02 13:56:56.688674935 +0200
@@ -124,6 +124,16 @@ static int get_matching_microcode(int cp
 }
 
 /*
+ * Those patch levels cannot be updated to newer ones and thus should be final.
+ */
+static u32 final_levels[] = {
+	0x01000098,
+	0x0100009f,
+	0x010000af,
+	0, /* T-101 terminator */
+};
+
+/*
  * 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
@@ -133,13 +143,33 @@ static int get_matching_microcode(int cp
  *  - true: if update should stop
  *  - false: otherwise
  */
-bool check_current_patch_level(u32 *rev)
+bool check_current_patch_level(u32 *rev, bool early)
 {
-	u32 dummy;
+	u32 lvl, dummy, i;
+	bool ret = false;
+	u32 *levels;
+
+	rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy);
+
+#ifdef CONFIG_X86_32
+	if (early)
+		levels = (u32 *)__pa_nodebug(&final_levels);
+	else
+#endif
+		levels = final_levels;
+
+	for (i = 0; levels[i]; i++) {
+		if (lvl == levels[i]) {
+			lvl = 0;
+			ret = true;
+			break;
+		}
+	}
 
-	rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy);
+	if (rev)
+		*rev = lvl;
 
-	return false;
+	return ret;
 }
 
 static int apply_microcode_amd(int cpu)
@@ -156,7 +186,7 @@ static int apply_microcode_amd(int cpu)
 	if (mc_amd == NULL)
 		return 0;
 
-	if (check_current_patch_level(&rev))
+	if (check_current_patch_level(&rev, false))
 		return -1;
 
 	wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-05-02 15:30         ` Borislav Petkov
@ 2016-05-06 12:43           ` Henrique de Moraes Holschuh
  2016-05-06 13:23             ` Borislav Petkov
  0 siblings, 1 reply; 13+ messages in thread
From: Henrique de Moraes Holschuh @ 2016-05-06 12:43 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: LKML, X86 ML

On Mon, May 2, 2016, at 12:30, Borislav Petkov wrote:
> On Sun, Mar 27, 2016 at 05:47:48PM +0200, Borislav Petkov wrote:
> > But ok. I'll put it on my TODO, will get to it eventually. Unless you
> > beat me to it... :)
> 
> Ok, I'm attaching the backports for 3.2. Care to give them a run too,
> just in case? Seem to work here on my test box...

Unfortunately, I don't have any AMD boxes on hand to runtime-test them,
which would be the reason why I didn't try backporting these on my own
:-(

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels
  2016-05-06 12:43           ` Henrique de Moraes Holschuh
@ 2016-05-06 13:23             ` Borislav Petkov
  0 siblings, 0 replies; 13+ messages in thread
From: Borislav Petkov @ 2016-05-06 13:23 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: LKML, X86 ML

On Fri, May 06, 2016 at 09:43:47AM -0300, Henrique de Moraes Holschuh wrote:
> Unfortunately, I don't have any AMD boxes on hand to runtime-test them,
> which would be the reason why I didn't try backporting these on my own
> :-(

Ok, no probs. I'll send them to stable.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-05-06 13:23 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-01 20:14 [PATCH 0/2] x86/microcode/amd: Do not overwrite specific patch levels Borislav Petkov
2015-07-01 20:14 ` [PATCH 1/2] x86/microcode/amd: Extract current patch level read to a function Borislav Petkov
2015-07-01 20:14 ` [PATCH 2/2] x86/microcode/amd: Do not overwrite final patch levels Borislav Petkov
2015-07-09 15:03 ` [PATCH 0/2] x86/microcode/amd: Do not overwrite specific " Henrique de Moraes Holschuh
2015-07-10 10:11   ` Borislav Petkov
2015-07-10 15:12     ` Henrique de Moraes Holschuh
2016-03-26 23:31 ` Henrique de Moraes Holschuh
2016-03-27  8:31   ` Borislav Petkov
2016-03-27 12:32     ` Henrique de Moraes Holschuh
2016-03-27 15:47       ` Borislav Petkov
2016-05-02 15:30         ` Borislav Petkov
2016-05-06 12:43           ` Henrique de Moraes Holschuh
2016-05-06 13:23             ` Borislav Petkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.