All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT pull] efi/urgent for 5.3-rc5
@ 2019-08-18 11:34 Thomas Gleixner
  2019-08-18 11:34 ` [GIT pull] x86/urgent " Thomas Gleixner
  2019-08-18 16:55 ` [GIT pull] efi/urgent " pr-tracker-bot
  0 siblings, 2 replies; 23+ messages in thread
From: Thomas Gleixner @ 2019-08-18 11:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, x86

Linus,

please pull the latest efi-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git efi-urgent-for-linus

up to:  cbd32a1c56e3: Merge tag 'efi-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi into efi/urgent

A single fix for a EFI mixed mode regression caused by recent rework which
did not take the firmware bitwidth into account.

Thanks,

	tglx

------------------>
Hans de Goede (1):
      efi-stub: Fix get_efi_config_table on mixed-mode setups


 drivers/firmware/efi/libstub/efi-stub-helper.c | 38 ++++++++++++++++++--------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 1db780c0f07b..3caae7f2cf56 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -927,17 +927,33 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table_arg,
 	return status;
 }
 
+#define GET_EFI_CONFIG_TABLE(bits)					\
+static void *get_efi_config_table##bits(efi_system_table_t *_sys_table,	\
+					efi_guid_t guid)		\
+{									\
+	efi_system_table_##bits##_t *sys_table;				\
+	efi_config_table_##bits##_t *tables;				\
+	int i;								\
+									\
+	sys_table = (typeof(sys_table))_sys_table;			\
+	tables = (typeof(tables))(unsigned long)sys_table->tables;	\
+									\
+	for (i = 0; i < sys_table->nr_tables; i++) {			\
+		if (efi_guidcmp(tables[i].guid, guid) != 0)		\
+			continue;					\
+									\
+		return (void *)(unsigned long)tables[i].table;		\
+	}								\
+									\
+	return NULL;							\
+}
+GET_EFI_CONFIG_TABLE(32)
+GET_EFI_CONFIG_TABLE(64)
+
 void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 {
-	efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
-	int i;
-
-	for (i = 0; i < sys_table->nr_tables; i++) {
-		if (efi_guidcmp(tables[i].guid, guid) != 0)
-			continue;
-
-		return (void *)tables[i].table;
-	}
-
-	return NULL;
+	if (efi_is_64bit())
+		return get_efi_config_table64(sys_table, guid);
+	else
+		return get_efi_config_table32(sys_table, guid);
 }


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

* [GIT pull] x86/urgent for 5.3-rc5
  2019-08-18 11:34 [GIT pull] efi/urgent for 5.3-rc5 Thomas Gleixner
@ 2019-08-18 11:34 ` Thomas Gleixner
  2019-08-18 16:55   ` pr-tracker-bot
  2019-08-18 16:55 ` [GIT pull] efi/urgent " pr-tracker-bot
  1 sibling, 1 reply; 23+ messages in thread
From: Thomas Gleixner @ 2019-08-18 11:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, x86

Linus,

please pull the latest x86-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus

up to:  a90118c445cc: x86/boot: Save fields explicitly, zero out everything else

A set of fixes for x86:

 - Fix the inconsistent error handling in the umwait init code

 - Rework the boot param zeroing so gcc9 stops complaining about out of
   bound memset. The resulting source code is actually more sane to read
   than the smart solution we had

 - Maintainers update so Tony gets involved when Intel models are added

 - Some more fallthrough fixes

Thanks,

	tglx

------------------>
Borislav Petkov (1):
      x86/apic/32: Fix yet another implicit fallthrough warning

Fenghua Yu (1):
      x86/umwait: Fix error handling in umwait_init()

John Hubbard (1):
      x86/boot: Save fields explicitly, zero out everything else

Thomas Gleixner (1):
      x86/fpu/math-emu: Address fallthrough warnings

Tony Luck (1):
      MAINTAINERS, x86/CPU: Tony Luck will maintain asm/intel-family.h


 MAINTAINERS                            |  7 ++++
 arch/x86/include/asm/bootparam_utils.h | 63 ++++++++++++++++++++++++++--------
 arch/x86/kernel/apic/probe_32.c        |  3 +-
 arch/x86/kernel/cpu/umwait.c           | 39 ++++++++++++++++++++-
 arch/x86/math-emu/errors.c             |  5 +--
 arch/x86/math-emu/fpu_trig.c           |  2 +-
 6 files changed, 99 insertions(+), 20 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index e81e60bd7c26..f3a78403b47f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8064,6 +8064,13 @@ T:	git git://git.code.sf.net/p/intel-sas/isci
 S:	Supported
 F:	drivers/scsi/isci/
 
+INTEL CPU family model numbers
+M:	Tony Luck <tony.luck@intel.com>
+M:	x86@kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	arch/x86/include/asm/intel-family.h
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:	Jani Nikula <jani.nikula@linux.intel.com>
 M:	Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
index 101eb944f13c..f5e90a849bca 100644
--- a/arch/x86/include/asm/bootparam_utils.h
+++ b/arch/x86/include/asm/bootparam_utils.h
@@ -18,6 +18,20 @@
  * Note: efi_info is commonly left uninitialized, but that field has a
  * private magic, so it is better to leave it unchanged.
  */
+
+#define sizeof_mbr(type, member) ({ sizeof(((type *)0)->member); })
+
+#define BOOT_PARAM_PRESERVE(struct_member)				\
+	{								\
+		.start = offsetof(struct boot_params, struct_member),	\
+		.len   = sizeof_mbr(struct boot_params, struct_member),	\
+	}
+
+struct boot_params_to_save {
+	unsigned int start;
+	unsigned int len;
+};
+
 static void sanitize_boot_params(struct boot_params *boot_params)
 {
 	/* 
@@ -35,21 +49,40 @@ static void sanitize_boot_params(struct boot_params *boot_params)
 	 * problems again.
 	 */
 	if (boot_params->sentinel) {
-		/* fields in boot_params are left uninitialized, clear them */
-		boot_params->acpi_rsdp_addr = 0;
-		memset(&boot_params->ext_ramdisk_image, 0,
-		       (char *)&boot_params->efi_info -
-			(char *)&boot_params->ext_ramdisk_image);
-		memset(&boot_params->kbd_status, 0,
-		       (char *)&boot_params->hdr -
-		       (char *)&boot_params->kbd_status);
-		memset(&boot_params->_pad7[0], 0,
-		       (char *)&boot_params->edd_mbr_sig_buffer[0] -
-			(char *)&boot_params->_pad7[0]);
-		memset(&boot_params->_pad8[0], 0,
-		       (char *)&boot_params->eddbuf[0] -
-			(char *)&boot_params->_pad8[0]);
-		memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+		static struct boot_params scratch;
+		char *bp_base = (char *)boot_params;
+		char *save_base = (char *)&scratch;
+		int i;
+
+		const struct boot_params_to_save to_save[] = {
+			BOOT_PARAM_PRESERVE(screen_info),
+			BOOT_PARAM_PRESERVE(apm_bios_info),
+			BOOT_PARAM_PRESERVE(tboot_addr),
+			BOOT_PARAM_PRESERVE(ist_info),
+			BOOT_PARAM_PRESERVE(acpi_rsdp_addr),
+			BOOT_PARAM_PRESERVE(hd0_info),
+			BOOT_PARAM_PRESERVE(hd1_info),
+			BOOT_PARAM_PRESERVE(sys_desc_table),
+			BOOT_PARAM_PRESERVE(olpc_ofw_header),
+			BOOT_PARAM_PRESERVE(efi_info),
+			BOOT_PARAM_PRESERVE(alt_mem_k),
+			BOOT_PARAM_PRESERVE(scratch),
+			BOOT_PARAM_PRESERVE(e820_entries),
+			BOOT_PARAM_PRESERVE(eddbuf_entries),
+			BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
+			BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+			BOOT_PARAM_PRESERVE(e820_table),
+			BOOT_PARAM_PRESERVE(eddbuf),
+		};
+
+		memset(&scratch, 0, sizeof(scratch));
+
+		for (i = 0; i < ARRAY_SIZE(to_save); i++) {
+			memcpy(save_base + to_save[i].start,
+			       bp_base + to_save[i].start, to_save[i].len);
+		}
+
+		memcpy(boot_params, save_base, sizeof(*boot_params));
 	}
 }
 
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 1492799b8f43..ee2d91e382f1 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -184,7 +184,8 @@ void __init default_setup_apic_routing(void)
 				def_to_bigsmp = 0;
 				break;
 			}
-			/* If P4 and above fall through */
+			/* P4 and above */
+			/* fall through */
 		case X86_VENDOR_HYGON:
 		case X86_VENDOR_AMD:
 			def_to_bigsmp = 1;
diff --git a/arch/x86/kernel/cpu/umwait.c b/arch/x86/kernel/cpu/umwait.c
index 6a204e7336c1..32b4dc9030aa 100644
--- a/arch/x86/kernel/cpu/umwait.c
+++ b/arch/x86/kernel/cpu/umwait.c
@@ -17,6 +17,12 @@
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
+/*
+ * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
+ * hardware or BIOS before kernel boot.
+ */
+static u32 orig_umwait_control_cached __ro_after_init;
+
 /*
  * Serialize access to umwait_control_cached and IA32_UMWAIT_CONTROL MSR in
  * the sysfs write functions.
@@ -52,6 +58,23 @@ static int umwait_cpu_online(unsigned int cpu)
 	return 0;
 }
 
+/*
+ * The CPU hotplug callback sets the control MSR to the original control
+ * value.
+ */
+static int umwait_cpu_offline(unsigned int cpu)
+{
+	/*
+	 * This code is protected by the CPU hotplug already and
+	 * orig_umwait_control_cached is never changed after it caches
+	 * the original control MSR value in umwait_init(). So there
+	 * is no race condition here.
+	 */
+	wrmsr(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached, 0);
+
+	return 0;
+}
+
 /*
  * On resume, restore IA32_UMWAIT_CONTROL MSR on the boot processor which
  * is the only active CPU at this time. The MSR is set up on the APs via the
@@ -185,8 +208,22 @@ static int __init umwait_init(void)
 	if (!boot_cpu_has(X86_FEATURE_WAITPKG))
 		return -ENODEV;
 
+	/*
+	 * Cache the original control MSR value before the control MSR is
+	 * changed. This is the only place where orig_umwait_control_cached
+	 * is modified.
+	 */
+	rdmsrl(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
+
 	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait:online",
-				umwait_cpu_online, NULL);
+				umwait_cpu_online, umwait_cpu_offline);
+	if (ret < 0) {
+		/*
+		 * On failure, the control MSR on all CPUs has the
+		 * original control value.
+		 */
+		return ret;
+	}
 
 	register_syscore_ops(&umwait_syscore_ops);
 
diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c
index 6b468517ab71..73dc66d887f3 100644
--- a/arch/x86/math-emu/errors.c
+++ b/arch/x86/math-emu/errors.c
@@ -178,13 +178,15 @@ void FPU_printall(void)
 	for (i = 0; i < 8; i++) {
 		FPU_REG *r = &st(i);
 		u_char tagi = FPU_gettagi(i);
+
 		switch (tagi) {
 		case TAG_Empty:
 			continue;
-			break;
 		case TAG_Zero:
 		case TAG_Special:
+			/* Update tagi for the printk below */
 			tagi = FPU_Special(r);
+			/* fall through */
 		case TAG_Valid:
 			printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
 			       getsign(r) ? '-' : '+',
@@ -198,7 +200,6 @@ void FPU_printall(void)
 			printk("Whoops! Error in errors.c: tag%d is %d ", i,
 			       tagi);
 			continue;
-			break;
 		}
 		printk("%s\n", tag_desc[(int)(unsigned)tagi]);
 	}
diff --git a/arch/x86/math-emu/fpu_trig.c b/arch/x86/math-emu/fpu_trig.c
index 783c509f957a..127ea54122d7 100644
--- a/arch/x86/math-emu/fpu_trig.c
+++ b/arch/x86/math-emu/fpu_trig.c
@@ -1352,7 +1352,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
 		case TW_Denormal:
 			if (denormal_operand() < 0)
 				return;
-
+			/* fall through */
 		case TAG_Zero:
 		case TAG_Valid:
 			setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));


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

* Re: [GIT pull] efi/urgent for 5.3-rc5
  2019-08-18 11:34 [GIT pull] efi/urgent for 5.3-rc5 Thomas Gleixner
  2019-08-18 11:34 ` [GIT pull] x86/urgent " Thomas Gleixner
@ 2019-08-18 16:55 ` pr-tracker-bot
  1 sibling, 0 replies; 23+ messages in thread
From: pr-tracker-bot @ 2019-08-18 16:55 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Linus Torvalds, linux-kernel, x86

The pull request you sent on Sun, 18 Aug 2019 11:34:54 -0000:

> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git efi-urgent-for-linus

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/645c03aaca2bc02f5d5cc70804ca00b248b729dc

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-18 11:34 ` [GIT pull] x86/urgent " Thomas Gleixner
@ 2019-08-18 16:55   ` pr-tracker-bot
  0 siblings, 0 replies; 23+ messages in thread
From: pr-tracker-bot @ 2019-08-18 16:55 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Linus Torvalds, linux-kernel, x86

The pull request you sent on Sun, 18 Aug 2019 11:34:54 -0000:

> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/c332f3a70e7a094e4a60d68a2c4c6f051ed7f04d

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-28 15:20                             ` David Sterba
@ 2019-08-28 15:53                               ` David Sterba
  0 siblings, 0 replies; 23+ messages in thread
From: David Sterba @ 2019-08-28 15:53 UTC (permalink / raw)
  To: dsterba, Borislav Petkov, Linus Torvalds, Pu Wen,
	Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Wed, Aug 28, 2019 at 05:20:41PM +0200, David Sterba wrote:
> On Tue, Aug 27, 2019 at 07:39:55PM +0200, Borislav Petkov wrote:
> > @@ -42,5 +43,24 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
> >  			return;
> >  		}
> >  	}
> > +
> > +	/*
> > +	 * Stupid sanity-check whether RDRAND does *actually* generate
> > +	 * some at least random-looking data.
> > +	 */
> > +	prev = tmp;
> > +	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
> > +		if (rdrand_long(&tmp)) {
> > +			if (prev != tmp)
> > +				changed++;
> 
> You could do some sort of weak statistical test like
> 
> 		if (popcnt(prev ^ tmp) < BITS_PER_LONG / 3)
> 			bad++;
> 
> 		if (bad > TOO_BAD)
> 			WARN(...);
> 
> this should catch same value, increments you mentioned and possibly
> other trivial classes of not-so-random values.

So the average popcount seems to be a more reliable check as I don't
have a good estimate for TOO_BAD. Ie. calculate average popcount and if
it's less than third of bit width, consider it broken. The script below
can be used to demonstrate the behaviour on a good random generator.

---
#!/usr/bin/python3

import random

popsum = 0
popcount = 0

prev = random.randrange(0, 2**64)
for i in range(16):
    x = return random.randrange(0, 2**64)
    pop = bin(x ^ prev).count("1")
    popsum += pop
    popcount += 1
    print("PREV=%d X=%d popcnt=%d" % (prev, x, pop))
    prev = x

print("Average popcnt: %d" % (1.0 * popsum / popcount))
---
PREV=8900625479737950182 X=12846979731852325434 popcnt=32
PREV=12846979731852325434 X=8887925161619955047 popcnt=35
PREV=8887925161619955047 X=988349339658261072 popcnt=36
PREV=988349339658261072 X=431141664953398919 popcnt=32
PREV=431141664953398919 X=13830962168734488538 popcnt=33
PREV=13830962168734488538 X=16591763919535693884 popcnt=33
PREV=16591763919535693884 X=7388685098481568010 popcnt=22
PREV=7388685098481568010 X=3526579832640281911 popcnt=33
PREV=3526579832640281911 X=2069567414175453497 popcnt=27
PREV=2069567414175453497 X=5562304115464083982 popcnt=28
PREV=5562304115464083982 X=14604545499285704604 popcnt=31
PREV=14604545499285704604 X=10602551277613833090 popcnt=31
PREV=10602551277613833090 X=6431137842853826307 popcnt=32
PREV=6431137842853826307 X=16231642336281616741 popcnt=41
PREV=16231642336281616741 X=520921733225029500 popcnt=38
PREV=520921733225029500 X=12014110422974389822 popcnt=21
Average popcnt: 31

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-27 17:39                           ` Borislav Petkov
  2019-08-27 17:46                             ` Linus Torvalds
@ 2019-08-28 15:20                             ` David Sterba
  2019-08-28 15:53                               ` David Sterba
  1 sibling, 1 reply; 23+ messages in thread
From: David Sterba @ 2019-08-28 15:20 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Linus Torvalds, Pu Wen, Thomas Gleixner, Tom Lendacky,
	Linux List Kernel Mailing, the arch/x86 maintainers

On Tue, Aug 27, 2019 at 07:39:55PM +0200, Borislav Petkov wrote:
> @@ -42,5 +43,24 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
>  			return;
>  		}
>  	}
> +
> +	/*
> +	 * Stupid sanity-check whether RDRAND does *actually* generate
> +	 * some at least random-looking data.
> +	 */
> +	prev = tmp;
> +	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
> +		if (rdrand_long(&tmp)) {
> +			if (prev != tmp)
> +				changed++;

You could do some sort of weak statistical test like

		if (popcnt(prev ^ tmp) < BITS_PER_LONG / 3)
			bad++;

		if (bad > TOO_BAD)
			WARN(...);

this should catch same value, increments you mentioned and possibly
other trivial classes of not-so-random values.

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-27 17:46                             ` Linus Torvalds
@ 2019-08-27 17:59                               ` Borislav Petkov
  0 siblings, 0 replies; 23+ messages in thread
From: Borislav Petkov @ 2019-08-27 17:59 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Tue, Aug 27, 2019 at 10:46:42AM -0700, Linus Torvalds wrote:
> No hurry, and I don't care deeply when this goes in. It looks safe and
> harmless, so any time as far as I'm concerned - whatever is most
> convenient for people.
> 
> This is more of a "let's protect against any future issues" than
> anything critical right now.

Yeah.

> And I suspect it just means that next time somebody screws up rdrand,
> they'll screw it up to be a simple counter instead of just returning
> all-ones,

I'm reading this, and, for some reason, not even the slightest ounce of
surprise is materializing in me. I wonder why that is...

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-27 17:39                           ` Borislav Petkov
@ 2019-08-27 17:46                             ` Linus Torvalds
  2019-08-27 17:59                               ` Borislav Petkov
  2019-08-28 15:20                             ` David Sterba
  1 sibling, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-27 17:46 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Tue, Aug 27, 2019 at 10:40 AM Borislav Petkov <bp@suse.de> wrote:
>
> Do you want it this weekend, after some smoke testing on boxes or should
> I leave it a couple of weeks in tip until the merge window opens, and
> then queue it for 5.4 for longer exposure in linux-next?

No hurry, and I don't care deeply when this goes in. It looks safe and
harmless, so any time as far as I'm concerned - whatever is most
convenient for people.

This is more of a "let's protect against any future issues" than
anything critical right now.

And I suspect it just means that next time somebody screws up rdrand,
they'll screw it up to be a simple counter instead of just returning
all-ones, and we'll miss it anyway ;)

              Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-27 16:55                         ` Linus Torvalds
@ 2019-08-27 17:39                           ` Borislav Petkov
  2019-08-27 17:46                             ` Linus Torvalds
  2019-08-28 15:20                             ` David Sterba
  0 siblings, 2 replies; 23+ messages in thread
From: Borislav Petkov @ 2019-08-27 17:39 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Tue, Aug 27, 2019 at 09:55:08AM -0700, Linus Torvalds wrote:
> Side note: I'd suggest
> 
>         if (WARN_ON_ONCE(!changed))
>                 pr_emerg("RDRAND gives funky smelling output, might
> consider not using it by booting with \"nordrand\"");
> 
> instead.

Done, final result with a proper commit message below.

Do you want it this weekend, after some smoke testing on boxes or should
I leave it a couple of weeks in tip until the merge window opens, and
then queue it for 5.4 for longer exposure in linux-next?

Thx.

---
From: Borislav Petkov <bp@suse.de>
Date: Sun, 25 Aug 2019 22:50:18 +0200
Subject: [PATCH] x86/rdrand: Sanity-check RDRAND output

It turned out recently that on certain AMD F15h and F16h machines, due
to the BIOS dropping the ball after resume, yet again, RDRAND would not
function anymore:

  c49a0a80137c ("x86/CPU/AMD: Clear RDRAND CPUID bit on AMD family 15h/16h")

Add a silly test to the CPU bringup path, to sanity-check the random
data RDRAND returns and scream as loudly as possible if that returned
random data doesn't change.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Pu Wen <puwen@hygon.cn>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/CAHk-=wjWPDauemCmLTKbdMYFB0UveMszZpcrwoUkJRRWKrqaTw@mail.gmail.com
---
 arch/x86/kernel/cpu/rdrand.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
index 5c900f9527ff..c4be62058dd9 100644
--- a/arch/x86/kernel/cpu/rdrand.c
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -29,7 +29,8 @@ __setup("nordrand", x86_rdrand_setup);
 #ifdef CONFIG_ARCH_RANDOM
 void x86_init_rdrand(struct cpuinfo_x86 *c)
 {
-	unsigned long tmp;
+	unsigned int changed = 0;
+	unsigned long tmp, prev;
 	int i;
 
 	if (!cpu_has(c, X86_FEATURE_RDRAND))
@@ -42,5 +43,24 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
 			return;
 		}
 	}
+
+	/*
+	 * Stupid sanity-check whether RDRAND does *actually* generate
+	 * some at least random-looking data.
+	 */
+	prev = tmp;
+	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
+		if (rdrand_long(&tmp)) {
+			if (prev != tmp)
+				changed++;
+
+			prev = tmp;
+		}
+	}
+
+	if (WARN_ON_ONCE(!changed))
+		pr_emerg(
+"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
+
 }
 #endif
-- 
2.21.0

SUSE Linux GmbH, GF: Felix Imendörffer, Mary Higgins, Sri Rasiah, HRB 21284 (AG Nürnberg)
-- 

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-26 12:53                       ` Borislav Petkov
@ 2019-08-27 16:55                         ` Linus Torvalds
  2019-08-27 17:39                           ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-27 16:55 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Mon, Aug 26, 2019 at 5:53 AM Borislav Petkov <bp@suse.de> wrote:
>
> +       if (!changed) {
> +               pr_emerg(
> +"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
> +               WARN_ON_ONCE(1);
> +       }

Side note: I'd suggest

        if (WARN_ON_ONCE(!changed))
                pr_emerg("RDRAND gives funky smelling output, might
consider not using it by booting with \"nordrand\"");

instead.

Note that WARN_ON_ONCE() will only _warn_ once, but it always returns
the conditional.

So it's equivalent to your version ("always print, warn once") except for:

 (a) smaller
 (b) different order of warning and pr_emerg()
 (c) the WARN_ON_ONCE() also contains the proper "unlikely()", so it
generates better code

and I just try to encourage people to use that "if (WARN_ON())" format
for these kinds of "shouldn't happen, so warn and then do something".

Although usually the "do something" is just "return and refuse to do
anything further" rather than the additional printk.

               Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 20:17                     ` Borislav Petkov
@ 2019-08-26 12:53                       ` Borislav Petkov
  2019-08-27 16:55                         ` Linus Torvalds
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-26 12:53 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 10:17:23PM +0200, Borislav Petkov wrote:
> > I think WARN_ONCE() is good. It's big enough that it will show up in
> > dmesg if anybody looks, and if nobody looks I think distros still have
> > logging for things like that, don't they?
> 
> Probably. Lemme research that.

So there's a whole bunch of daemons doing desktop notifications along with a
desktop notifications spec, yadda yadda:

https://wiki.archlinux.org/index.php/Desktop_notifications

but installing an openSUSE Leap 15.1 in a guest and that is a default
desktop installation doesn't give me any notifications. I installed
notification-daemon and whatnot but nada.

Which means, that we cannot guarantee that every user would see it.
There might be installations which miss it.

So the only thing I can think of right now is to make that single line
pr_emerg() so that it atleast spews into the terminals when suspending:

linux-6qfo:~ # echo "suspend" > /sys/power/disk
linux-6qfo:~ # echo "mem" > /sys/power/state

<--- resume guest.

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.416145] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.423091] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.427426] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.434699] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.442587] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.449047] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.456328] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.462198] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.470120] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.477302] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.484605] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.490115] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.497508] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.505350] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

Message from syslogd@linux-6qfo at Aug 26 14:48:05 ...
 kernel:[   40.513336] RDRAND gives funky smelling output, might consider not using it by booting with "nordrand"

---

Assuming the user has at least a single terminal open. But someone might
have a better idea.

Current diff:

---
commit d46b23c4be1b4acae7d21c97be189131e200f6d0 (HEAD -> refs/heads/rc5+1-rdrand)
Author: Borislav Petkov <bp@suse.de>
Date:   Sun Aug 25 22:50:18 2019 +0200

    WIP

    Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Borislav Petkov <bp@suse.de>

diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
index 5c900f9527ff..b02d1ce91081 100644
--- a/arch/x86/kernel/cpu/rdrand.c
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -29,7 +29,8 @@ __setup("nordrand", x86_rdrand_setup);
 #ifdef CONFIG_ARCH_RANDOM
 void x86_init_rdrand(struct cpuinfo_x86 *c)
 {
-	unsigned long tmp;
+	unsigned int changed = 0;
+	unsigned long tmp, prev;
 	int i;
 
 	if (!cpu_has(c, X86_FEATURE_RDRAND))
@@ -42,5 +43,27 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
 			return;
 		}
 	}
+
+	/*
+	 * Stupid sanity-check whether RDRAND does *actually* generate
+	 * some at least random-looking data.
+	 */
+	prev = tmp;
+	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
+		if (rdrand_long(&tmp)) {
+			if (prev != tmp)
+				changed++;
+
+			prev = tmp;
+		}
+	}
+
+	if (!changed) {
+		pr_emerg(
+"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
+		WARN_ON_ONCE(1);
+	}
+
+
 }
 #endif
---

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 19:59                   ` Linus Torvalds
@ 2019-08-25 20:17                     ` Borislav Petkov
  2019-08-26 12:53                       ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-25 20:17 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 12:59:25PM -0700, Linus Torvalds wrote:
> I think WARN_ONCE() is good. It's big enough that it will show up in
> dmesg if anybody looks, and if nobody looks I think distros still have
> logging for things like that, don't they?

Probably. Lemme research that.

> Hopefully this never actually triggers in practice, thanks to rdrand
> being turned off on known-bad machines now, and Zen 2 being fixed.

Right. Here's v2, will do a proper patch tomorrow:

---
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
index 5c900f9527ff..00a9d13c0a92 100644
--- a/arch/x86/kernel/cpu/rdrand.c
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -29,7 +29,8 @@ __setup("nordrand", x86_rdrand_setup);
 #ifdef CONFIG_ARCH_RANDOM
 void x86_init_rdrand(struct cpuinfo_x86 *c)
 {
-	unsigned long tmp;
+	unsigned int changed = 0;
+	unsigned long tmp, prev;
 	int i;
 
 	if (!cpu_has(c, X86_FEATURE_RDRAND))
@@ -42,5 +43,24 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
 			return;
 		}
 	}
+
+	/*
+	 * Stupid sanity-check whether RDRAND does *actually* generate
+	 * some at least random-looking data.
+	 */
+	prev = tmp;
+	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
+		if (rdrand_long(&tmp)) {
+			if (prev != tmp)
+				changed++;
+
+			prev = tmp;
+		}
+	}
+
+	if (!changed)
+		WARN_ONCE(1,
+"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
+
 }
 #endif


-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 19:49                 ` Borislav Petkov
@ 2019-08-25 19:59                   ` Linus Torvalds
  2019-08-25 20:17                     ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-25 19:59 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 12:49 PM Borislav Petkov <bp@suse.de> wrote:
>
> We're really verbose, though. Dunno if we should make this a WARN_ONCE
> or we say that we really should be very loud with a non-functioning
> RDRAND...

I think WARN_ONCE() is good. It's big enough that it will show up in
dmesg if anybody looks, and if nobody looks I think distros still have
logging for things like that, don't they?

Hopefully this never actually triggers in practice, thanks to rdrand
being turned off on known-bad machines now, and Zen 2 being fixed.

               Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 19:35               ` Linus Torvalds
@ 2019-08-25 19:49                 ` Borislav Petkov
  2019-08-25 19:59                   ` Linus Torvalds
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-25 19:49 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 12:35:53PM -0700, Linus Torvalds wrote:
> You know what? The days of UP are long gone, and we really only want a
> one-time warning, so I think your thing is fine as-is.
> 
> It would be good to test with a known-bad setup, of course..

The trivial test by not incrementing the @changed variable looks like
this: http://ix.io/1Tsr

We're really verbose, though. Dunno if we should make this a WARN_ONCE
or we say that we really should be very loud with a non-functioning
RDRAND...

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 19:32             ` Borislav Petkov
@ 2019-08-25 19:35               ` Linus Torvalds
  2019-08-25 19:49                 ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-25 19:35 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 12:32 PM Borislav Petkov <bp@suse.de> wrote:
>
>
> and also on all the remaining 15 CPUs of the guest. Then, suspending to
> RAM and resuming right afterwards says:
>
> and the remaining 14(!). Yes, this doesn't run on the BSP during resume.
> I think the better thing to do would be to stick this in a CPUHP
> notifier...

You know what? The days of UP are long gone, and we really only want a
one-time warning, so I think your thing is fine as-is.

It would be good to test with a known-bad setup, of course..

                   Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 18:38           ` Linus Torvalds
@ 2019-08-25 19:32             ` Borislav Petkov
  2019-08-25 19:35               ` Linus Torvalds
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-25 19:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 11:38:50AM -0700, Linus Torvalds wrote:
> On Sun, Aug 25, 2019 at 11:29 AM Borislav Petkov <bp@suse.de> wrote:
> >
> > My lazy, sticky Sunday brain could come up only with this:
> 
> Looks reasonable, except I think this only runs at boot, right?
> 
> I _think_ the boot CPU is magical during suspend/resume, and doesn't
> do the full CPU bringup.
> 
> Although I guess this would still report it for the other CPU's? I
> didn't check if this gets done during CPU bringup of secondary CPU's.

So after adding a dump_stack() at the beginning of this function (yap,
I'm lazy) I see during boot:

[    0.230044] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.3.0-rc5+ #9
[    0.230759] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.1-1 04/01/2014
[    0.231690] Call Trace:
[    0.232097]  dump_stack+0x46/0x60
[    0.232496]  x86_init_rdrand+0xf/0xa1
[    0.232496]  identify_cpu+0x352/0x540
[    0.232496]  identify_boot_cpu+0xc/0x8f
[    0.232496]  check_bugs+0x28/0x8e4
[    0.232496]  ? __get_locked_pte+0x13e/0x1f0
[    0.232496]  start_kernel+0x4ae/0x4ca

and also on all the remaining 15 CPUs of the guest. Then, suspending to
RAM and resuming right afterwards says:

[   51.620230] Disabling non-boot CPUs ...
[   51.622745] smpboot: CPU 1 is now offline
[   51.627264] smpboot: CPU 2 is now offline
[   51.630581] smpboot: CPU 3 is now offline
[   51.634533] smpboot: CPU 4 is now offline
[   51.638715] smpboot: CPU 5 is now offline
[   51.642590] smpboot: CPU 6 is now offline
[   51.645890] smpboot: CPU 7 is now offline
[   51.649076] smpboot: CPU 8 is now offline
[   51.652362] smpboot: CPU 9 is now offline
[   51.655647] smpboot: CPU 10 is now offline
[   51.659061] smpboot: CPU 11 is now offline
[   51.662772] smpboot: CPU 12 is now offline
[   51.665863] smpboot: CPU 13 is now offline
[   51.667980] smpboot: CPU 14 is now offline
[   51.671644] smpboot: CPU 15 is now offline
[   51.675640] ACPI: Low-level resume complete
[   51.675640] PM: Restoring platform NVS memory
[   51.675640] Enabling non-boot CPUs ...
[   51.728674] x86: Booting SMP configuration:
[   51.729015] smpboot: Booting Node 0 Processor 1 APIC 0x1
[   51.625362] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.3.0-rc5+ #9
[   51.625362] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.1-1 04/01/2014
[   51.625362] Call Trace:
[   51.625362]  dump_stack+0x46/0x60
[   51.625362]  x86_init_rdrand+0xf/0xa1
[   51.625362]  identify_cpu+0x352/0x540
[   51.625362]  identify_secondary_cpu+0x13/0x80
[   51.625362]  smp_store_cpu_info+0x45/0x50
[   51.625362]  start_secondary+0x4f/0x180
[   51.625362]  secondary_startup_64+0xa4/0xb0
[   51.740833] CPU1 is up
...

and the remaining 14(!). Yes, this doesn't run on the BSP during resume.
I think the better thing to do would be to stick this in a CPUHP
notifier...

Btw:

Subject: Undelivered Mail Returned to Sender

...

<puwen@hygon.cn>: Host or domain name not found. Name service error for
    name=spam01.hygon.cn type=AAAA: Host found but no data record of requested
    type

hygon.cn domain doesn't even resolve from here. Oh boy.

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 18:29         ` Borislav Petkov
@ 2019-08-25 18:38           ` Linus Torvalds
  2019-08-25 19:32             ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-25 18:38 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Pu Wen, Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 11:29 AM Borislav Petkov <bp@suse.de> wrote:
>
> My lazy, sticky Sunday brain could come up only with this:

Looks reasonable, except I think this only runs at boot, right?

I _think_ the boot CPU is magical during suspend/resume, and doesn't
do the full CPU bringup.

Although I guess this would still report it for the other CPU's? I
didn't check if this gets done during CPU bringup of secondary CPU's.

               Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 17:37       ` Linus Torvalds
@ 2019-08-25 18:29         ` Borislav Petkov
  2019-08-25 18:38           ` Linus Torvalds
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-25 18:29 UTC (permalink / raw)
  To: Linus Torvalds, Pu Wen
  Cc: Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 10:37:47AM -0700, Linus Torvalds wrote:
> On Sun, Aug 25, 2019 at 10:30 AM Borislav Petkov <bp@suse.de> wrote:
> >
> > Should we do that somewhere in the early boot code by adding a WARN_ON()
> > or so and see who screams?
> 
> It might be a good idea, just to see if it ever happens (again).
> 
> It doesn't even have to be early boot. It's probably more important to
> let the user _know_, than it is to then disable the rdrand
> instruction.
> 
> Particularly since we might as well just do it in general, and in the
> general case we don't even know how to hide it in cpuid. So maybe just
> something like "read the rdrand value a few times, make sure it
> actually changes" at CPU bring-up (both boot and resume)
> 
> It sounds like a stupid test, but considering that AMD has had this
> particular bug now several times over at least three different
> generations, maybe it's not a stupid test after all.

My lazy, sticky Sunday brain could come up only with this:

---
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
index 5c900f9527ff..0130a4f4f836 100644
--- a/arch/x86/kernel/cpu/rdrand.c
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -29,7 +29,8 @@ __setup("nordrand", x86_rdrand_setup);
 #ifdef CONFIG_ARCH_RANDOM
 void x86_init_rdrand(struct cpuinfo_x86 *c)
 {
-	unsigned long tmp;
+	unsigned int changed = 0;
+	unsigned long tmp, prev;
 	int i;
 
 	if (!cpu_has(c, X86_FEATURE_RDRAND))
@@ -42,5 +43,24 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
 			return;
 		}
 	}
+
+	/*
+	 * Stupid sanity-check whether RDRAND does *actually* generate
+	 * some at least random-looking data.
+	 */
+	prev = tmp;
+	for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
+		if (rdrand_long(&tmp)) {
+			if (prev != tmp)
+				changed++;
+
+			prev = tmp;
+		}
+	}
+
+	if (!changed)
+		WARN(1,
+"RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
+
 }
 #endif

---

> Who knows what the Chinese CPU's that use the AMD core do? Hygon?
> Whatever. Did they get the firmware fixes?

Pu Wen?

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25  9:43 ` [GIT pull] x86/urgent " Thomas Gleixner
  2019-08-25 17:18   ` Linus Torvalds
@ 2019-08-25 17:40   ` pr-tracker-bot
  1 sibling, 0 replies; 23+ messages in thread
From: pr-tracker-bot @ 2019-08-25 17:40 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Linus Torvalds, linux-kernel, x86

The pull request you sent on Sun, 25 Aug 2019 09:43:00 -0000:

> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/146c3d3220e039b5d61bf810e0b42218eb020f39

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 17:30     ` Borislav Petkov
@ 2019-08-25 17:37       ` Linus Torvalds
  2019-08-25 18:29         ` Borislav Petkov
  0 siblings, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-25 17:37 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 10:30 AM Borislav Petkov <bp@suse.de> wrote:
>
> Should we do that somewhere in the early boot code by adding a WARN_ON()
> or so and see who screams?

It might be a good idea, just to see if it ever happens (again).

It doesn't even have to be early boot. It's probably more important to
let the user _know_, than it is to then disable the rdrand
instruction.

Particularly since we might as well just do it in general, and in the
general case we don't even know how to hide it in cpuid. So maybe just
something like "read the rdrand value a few times, make sure it
actually changes" at CPU bring-up (both boot and resume)

It sounds like a stupid test, but considering that AMD has had this
particular bug now several times over at least three different
generations, maybe it's not a stupid test after all.

Who knows what the Chinese CPU's that use the AMD core do? Hygon?
Whatever. Did they get the firmware fixes?

              Linus

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25 17:18   ` Linus Torvalds
@ 2019-08-25 17:30     ` Borislav Petkov
  2019-08-25 17:37       ` Linus Torvalds
  0 siblings, 1 reply; 23+ messages in thread
From: Borislav Petkov @ 2019-08-25 17:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Thomas Gleixner, Tom Lendacky, Linux List Kernel Mailing,
	the arch/x86 maintainers

On Sun, Aug 25, 2019 at 10:18:02AM -0700, Linus Torvalds wrote:
> Not doing the Zen 2 boot-time case? Everybody assumes that all
> firmware has been fixed?

My info is that all Zen has been taken care of with fw fixes.

> That one should be easy to verify since it happens at boot: just do
> "rdrand" twice, and if it returns all-ones both times, it's broken.

Should we do that somewhere in the early boot code by adding a WARN_ON()
or so and see who screams?

-- 
Regards/Gruss,
    Boris.

SUSE Software Solutions Germany GmbH, GF: Felix Imendörffer, HRB 247165, AG München

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

* Re: [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25  9:43 ` [GIT pull] x86/urgent " Thomas Gleixner
@ 2019-08-25 17:18   ` Linus Torvalds
  2019-08-25 17:30     ` Borislav Petkov
  2019-08-25 17:40   ` pr-tracker-bot
  1 sibling, 1 reply; 23+ messages in thread
From: Linus Torvalds @ 2019-08-25 17:18 UTC (permalink / raw)
  To: Thomas Gleixner, Tom Lendacky, Borislav Petkov
  Cc: Linux List Kernel Mailing, the arch/x86 maintainers

On Sun, Aug 25, 2019 at 2:45 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
>   - Clear the RDRAND CPUID bit on AMD family 15h and 16h CPUs which are
>     affected by broken firmware which does not initialize RDRAND correctly
>     after resume. Add a command line parameter to override this for machine
>     which either do not use suspend/resume or have a fixed
>     BIOS. Unfortunately there is no way to detect this on boot, so the only
>     safe decision is to turn it off by default.

Not doing the Zen 2 boot-time case? Everybody assumes that all
firmware has been fixed?

That one should be easy to verify since it happens at boot: just do
"rdrand" twice, and if it returns all-ones both times, it's broken.

              Linus

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

* [GIT pull] x86/urgent for 5.3-rc5
  2019-08-25  9:43 [GIT pull] irq/urgent " Thomas Gleixner
@ 2019-08-25  9:43 ` Thomas Gleixner
  2019-08-25 17:18   ` Linus Torvalds
  2019-08-25 17:40   ` pr-tracker-bot
  0 siblings, 2 replies; 23+ messages in thread
From: Thomas Gleixner @ 2019-08-25  9:43 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, x86

Linus,

please pull the latest x86-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus

up to:  b63f20a778c8: x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386

A few fixes for x86:

  - Fix a boot regression caused by the recent bootparam sanitizing change,
    which was escaped the attention of all people who reviewed that code.

  - Address a boot problem on machines with broken E820 tables caused by an
    underflow which ended up placing the trampoline start at physical
    address 0.
    
  - Handle machines which do not advertise a legacy timer of any form, but
    need calibration of the local APIC timer gracefully by making the
    calibration routine independent from the tick interrupt. Marked for
    stable as well as there seems to be quite some new laptops rolled out
    which expose this.

  - Clear the RDRAND CPUID bit on AMD family 15h and 16h CPUs which are
    affected by broken firmware which does not initialize RDRAND correctly
    after resume. Add a command line parameter to override this for machine
    which either do not use suspend/resume or have a fixed
    BIOS. Unfortunately there is no way to detect this on boot, so the only
    safe decision is to turn it off by default.

  - Prevent RFLAGS from being clobbers in CALL_NOSPEC on 32bit which caused
    fast KVM instruction emulation to break.

  - Explain the Intel CPU model naming convention so that the repeating
    discussions come to an end.

Thanks,

	tglx

------------------>
John Hubbard (1):
      x86/boot: Fix boot regression caused by bootparam sanitizing

Kirill A. Shutemov (1):
      x86/boot/compressed/64: Fix boot on machines with broken E820 table

Sean Christopherson (1):
      x86/retpoline: Don't clobber RFLAGS during CALL_NOSPEC on i386

Thomas Gleixner (1):
      x86/apic: Handle missing global clockevent gracefully

Tom Lendacky (1):
      x86/CPU/AMD: Clear RDRAND CPUID bit on AMD family 15h/16h

Tony Luck (1):
      x86/cpu: Explain Intel model naming convention


 Documentation/admin-guide/kernel-parameters.txt |  7 ++
 arch/x86/boot/compressed/pgtable_64.c           | 13 +++-
 arch/x86/include/asm/bootparam_utils.h          |  2 +-
 arch/x86/include/asm/intel-family.h             | 15 +++++
 arch/x86/include/asm/msr-index.h                |  1 +
 arch/x86/include/asm/nospec-branch.h            |  2 +-
 arch/x86/kernel/apic/apic.c                     | 68 ++++++++++++++-----
 arch/x86/kernel/cpu/amd.c                       | 66 +++++++++++++++++++
 arch/x86/power/cpu.c                            | 86 +++++++++++++++++++++----
 9 files changed, 227 insertions(+), 33 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 47d981a86e2f..4c1971960afa 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4090,6 +4090,13 @@
 			Run specified binary instead of /init from the ramdisk,
 			used for early userspace startup. See initrd.
 
+	rdrand=		[X86]
+			force - Override the decision by the kernel to hide the
+				advertisement of RDRAND support (this affects
+				certain AMD processors because of buggy BIOS
+				support, specifically around the suspend/resume
+				path).
+
 	rdt=		[HW,X86,RDT]
 			Turn on/off individual RDT features. List is:
 			cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index 5f2d03067ae5..2faddeb0398a 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
 
 	/* Find the first usable memory region under bios_start. */
 	for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+		unsigned long new;
+
 		entry = &boot_params->e820_table[i];
 
 		/* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
 
 		/* Adjust bios_start to the end of the entry if needed. */
 		if (bios_start > entry->addr + entry->size)
-			bios_start = entry->addr + entry->size;
+			new = entry->addr + entry->size;
 
 		/* Keep bios_start page-aligned. */
-		bios_start = round_down(bios_start, PAGE_SIZE);
+		new = round_down(new, PAGE_SIZE);
 
 		/* Skip the entry if it's too small. */
-		if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+		if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
 			continue;
 
+		/* Protect against underflow. */
+		if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+			break;
+
+		bios_start = new;
 		break;
 	}
 
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
index f5e90a849bca..9e5f3c722c33 100644
--- a/arch/x86/include/asm/bootparam_utils.h
+++ b/arch/x86/include/asm/bootparam_utils.h
@@ -59,7 +59,6 @@ static void sanitize_boot_params(struct boot_params *boot_params)
 			BOOT_PARAM_PRESERVE(apm_bios_info),
 			BOOT_PARAM_PRESERVE(tboot_addr),
 			BOOT_PARAM_PRESERVE(ist_info),
-			BOOT_PARAM_PRESERVE(acpi_rsdp_addr),
 			BOOT_PARAM_PRESERVE(hd0_info),
 			BOOT_PARAM_PRESERVE(hd1_info),
 			BOOT_PARAM_PRESERVE(sys_desc_table),
@@ -71,6 +70,7 @@ static void sanitize_boot_params(struct boot_params *boot_params)
 			BOOT_PARAM_PRESERVE(eddbuf_entries),
 			BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
 			BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+			BOOT_PARAM_PRESERVE(hdr),
 			BOOT_PARAM_PRESERVE(e820_table),
 			BOOT_PARAM_PRESERVE(eddbuf),
 		};
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
index 0278aa66ef62..fe7c205233f1 100644
--- a/arch/x86/include/asm/intel-family.h
+++ b/arch/x86/include/asm/intel-family.h
@@ -11,6 +11,21 @@
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
  * that group keep the CPUID for the variants sorted by model number.
+ *
+ * The defined symbol names have the following form:
+ *	INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF}
+ * where:
+ * OPTFAMILY	Describes the family of CPUs that this belongs to. Default
+ *		is assumed to be "_CORE" (and should be omitted). Other values
+ *		currently in use are _ATOM and _XEON_PHI
+ * MICROARCH	Is the code name for the micro-architecture for this core.
+ *		N.B. Not the platform name.
+ * OPTDIFF	If needed, a short string to differentiate by market segment.
+ *		Exact strings here will vary over time. _DESKTOP, _MOBILE, and
+ *		_X (short for Xeon server) should be used when they are
+ *		appropriate.
+ *
+ * The #define line may optionally include a comment including platform names.
  */
 
 #define INTEL_FAM6_CORE_YONAH		0x0E
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 6b4fc2788078..271d837d69a8 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -381,6 +381,7 @@
 #define MSR_AMD64_PATCH_LEVEL		0x0000008b
 #define MSR_AMD64_TSC_RATIO		0xc0000104
 #define MSR_AMD64_NB_CFG		0xc001001f
+#define MSR_AMD64_CPUID_FN_1		0xc0011004
 #define MSR_AMD64_PATCH_LOADER		0xc0010020
 #define MSR_AMD64_OSVW_ID_LENGTH	0xc0010140
 #define MSR_AMD64_OSVW_STATUS		0xc0010141
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 109f974f9835..80bc209c0708 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -192,7 +192,7 @@
 	"    	lfence;\n"					\
 	"       jmp    902b;\n"					\
 	"       .align 16\n"					\
-	"903:	addl   $4, %%esp;\n"				\
+	"903:	lea    4(%%esp), %%esp;\n"			\
 	"       pushl  %[thunk_target];\n"			\
 	"       ret;\n"						\
 	"       .align 16\n"					\
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f5291362da1a..aa5495d0f478 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -722,7 +722,7 @@ static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
 static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
 
 /*
- * Temporary interrupt handler.
+ * Temporary interrupt handler and polled calibration function.
  */
 static void __init lapic_cal_handler(struct clock_event_device *dev)
 {
@@ -851,7 +851,8 @@ bool __init apic_needs_pit(void)
 static int __init calibrate_APIC_clock(void)
 {
 	struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
-	void (*real_handler)(struct clock_event_device *dev);
+	u64 tsc_perj = 0, tsc_start = 0;
+	unsigned long jif_start;
 	unsigned long deltaj;
 	long delta, deltatsc;
 	int pm_referenced = 0;
@@ -878,28 +879,64 @@ static int __init calibrate_APIC_clock(void)
 	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
 		    "calibrating APIC timer ...\n");
 
+	/*
+	 * There are platforms w/o global clockevent devices. Instead of
+	 * making the calibration conditional on that, use a polling based
+	 * approach everywhere.
+	 */
 	local_irq_disable();
 
-	/* Replace the global interrupt handler */
-	real_handler = global_clock_event->event_handler;
-	global_clock_event->event_handler = lapic_cal_handler;
-
 	/*
 	 * Setup the APIC counter to maximum. There is no way the lapic
 	 * can underflow in the 100ms detection time frame
 	 */
 	__setup_APIC_LVTT(0xffffffff, 0, 0);
 
-	/* Let the interrupts run */
+	/*
+	 * Methods to terminate the calibration loop:
+	 *  1) Global clockevent if available (jiffies)
+	 *  2) TSC if available and frequency is known
+	 */
+	jif_start = READ_ONCE(jiffies);
+
+	if (tsc_khz) {
+		tsc_start = rdtsc();
+		tsc_perj = div_u64((u64)tsc_khz * 1000, HZ);
+	}
+
+	/*
+	 * Enable interrupts so the tick can fire, if a global
+	 * clockevent device is available
+	 */
 	local_irq_enable();
 
-	while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
-		cpu_relax();
+	while (lapic_cal_loops <= LAPIC_CAL_LOOPS) {
+		/* Wait for a tick to elapse */
+		while (1) {
+			if (tsc_khz) {
+				u64 tsc_now = rdtsc();
+				if ((tsc_now - tsc_start) >= tsc_perj) {
+					tsc_start += tsc_perj;
+					break;
+				}
+			} else {
+				unsigned long jif_now = READ_ONCE(jiffies);
 
-	local_irq_disable();
+				if (time_after(jif_now, jif_start)) {
+					jif_start = jif_now;
+					break;
+				}
+			}
+			cpu_relax();
+		}
 
-	/* Restore the real event handler */
-	global_clock_event->event_handler = real_handler;
+		/* Invoke the calibration routine */
+		local_irq_disable();
+		lapic_cal_handler(NULL);
+		local_irq_enable();
+	}
+
+	local_irq_disable();
 
 	/* Build delta t1-t2 as apic timer counts down */
 	delta = lapic_cal_t1 - lapic_cal_t2;
@@ -943,10 +980,11 @@ static int __init calibrate_APIC_clock(void)
 	levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
 
 	/*
-	 * PM timer calibration failed or not turned on
-	 * so lets try APIC timer based calibration
+	 * PM timer calibration failed or not turned on so lets try APIC
+	 * timer based calibration, if a global clockevent device is
+	 * available.
 	 */
-	if (!pm_referenced) {
+	if (!pm_referenced && global_clock_event) {
 		apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
 
 		/*
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 8d4e50428b68..68c363c341bf 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -804,6 +804,64 @@ static void init_amd_ln(struct cpuinfo_x86 *c)
 	msr_set_bit(MSR_AMD64_DE_CFG, 31);
 }
 
+static bool rdrand_force;
+
+static int __init rdrand_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "force"))
+		rdrand_force = true;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+early_param("rdrand", rdrand_cmdline);
+
+static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c)
+{
+	/*
+	 * Saving of the MSR used to hide the RDRAND support during
+	 * suspend/resume is done by arch/x86/power/cpu.c, which is
+	 * dependent on CONFIG_PM_SLEEP.
+	 */
+	if (!IS_ENABLED(CONFIG_PM_SLEEP))
+		return;
+
+	/*
+	 * The nordrand option can clear X86_FEATURE_RDRAND, so check for
+	 * RDRAND support using the CPUID function directly.
+	 */
+	if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force)
+		return;
+
+	msr_clear_bit(MSR_AMD64_CPUID_FN_1, 62);
+
+	/*
+	 * Verify that the CPUID change has occurred in case the kernel is
+	 * running virtualized and the hypervisor doesn't support the MSR.
+	 */
+	if (cpuid_ecx(1) & BIT(30)) {
+		pr_info_once("BIOS may not properly restore RDRAND after suspend, but hypervisor does not support hiding RDRAND via CPUID.\n");
+		return;
+	}
+
+	clear_cpu_cap(c, X86_FEATURE_RDRAND);
+	pr_info_once("BIOS may not properly restore RDRAND after suspend, hiding RDRAND via CPUID. Use rdrand=force to reenable.\n");
+}
+
+static void init_amd_jg(struct cpuinfo_x86 *c)
+{
+	/*
+	 * Some BIOS implementations do not restore proper RDRAND support
+	 * across suspend and resume. Check on whether to hide the RDRAND
+	 * instruction support via CPUID.
+	 */
+	clear_rdrand_cpuid_bit(c);
+}
+
 static void init_amd_bd(struct cpuinfo_x86 *c)
 {
 	u64 value;
@@ -818,6 +876,13 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
 			wrmsrl_safe(MSR_F15H_IC_CFG, value);
 		}
 	}
+
+	/*
+	 * Some BIOS implementations do not restore proper RDRAND support
+	 * across suspend and resume. Check on whether to hide the RDRAND
+	 * instruction support via CPUID.
+	 */
+	clear_rdrand_cpuid_bit(c);
 }
 
 static void init_amd_zn(struct cpuinfo_x86 *c)
@@ -860,6 +925,7 @@ static void init_amd(struct cpuinfo_x86 *c)
 	case 0x10: init_amd_gh(c); break;
 	case 0x12: init_amd_ln(c); break;
 	case 0x15: init_amd_bd(c); break;
+	case 0x16: init_amd_jg(c); break;
 	case 0x17: init_amd_zn(c); break;
 	}
 
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 24b079e94bc2..c9ef6a7a4a1a 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/tboot.h>
+#include <linux/dmi.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -23,7 +24,7 @@
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
 #include <asm/mmu_context.h>
-#include <linux/dmi.h>
+#include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -397,15 +398,14 @@ static int __init bsp_pm_check_init(void)
 
 core_initcall(bsp_pm_check_init);
 
-static int msr_init_context(const u32 *msr_id, const int total_num)
+static int msr_build_context(const u32 *msr_id, const int num)
 {
-	int i = 0;
+	struct saved_msrs *saved_msrs = &saved_context.saved_msrs;
 	struct saved_msr *msr_array;
+	int total_num;
+	int i, j;
 
-	if (saved_context.saved_msrs.array || saved_context.saved_msrs.num > 0) {
-		pr_err("x86/pm: MSR quirk already applied, please check your DMI match table.\n");
-		return -EINVAL;
-	}
+	total_num = saved_msrs->num + num;
 
 	msr_array = kmalloc_array(total_num, sizeof(struct saved_msr), GFP_KERNEL);
 	if (!msr_array) {
@@ -413,19 +413,30 @@ static int msr_init_context(const u32 *msr_id, const int total_num)
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < total_num; i++) {
-		msr_array[i].info.msr_no	= msr_id[i];
+	if (saved_msrs->array) {
+		/*
+		 * Multiple callbacks can invoke this function, so copy any
+		 * MSR save requests from previous invocations.
+		 */
+		memcpy(msr_array, saved_msrs->array,
+		       sizeof(struct saved_msr) * saved_msrs->num);
+
+		kfree(saved_msrs->array);
+	}
+
+	for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
+		msr_array[i].info.msr_no	= msr_id[j];
 		msr_array[i].valid		= false;
 		msr_array[i].info.reg.q		= 0;
 	}
-	saved_context.saved_msrs.num	= total_num;
-	saved_context.saved_msrs.array	= msr_array;
+	saved_msrs->num   = total_num;
+	saved_msrs->array = msr_array;
 
 	return 0;
 }
 
 /*
- * The following section is a quirk framework for problematic BIOSen:
+ * The following sections are a quirk framework for problematic BIOSen:
  * Sometimes MSRs are modified by the BIOSen after suspended to
  * RAM, this might cause unexpected behavior after wakeup.
  * Thus we save/restore these specified MSRs across suspend/resume
@@ -440,7 +451,7 @@ static int msr_initialize_bdw(const struct dmi_system_id *d)
 	u32 bdw_msr_id[] = { MSR_IA32_THERM_CONTROL };
 
 	pr_info("x86/pm: %s detected, MSR saving is needed during suspending.\n", d->ident);
-	return msr_init_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
+	return msr_build_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
 }
 
 static const struct dmi_system_id msr_save_dmi_table[] = {
@@ -455,9 +466,58 @@ static const struct dmi_system_id msr_save_dmi_table[] = {
 	{}
 };
 
+static int msr_save_cpuid_features(const struct x86_cpu_id *c)
+{
+	u32 cpuid_msr_id[] = {
+		MSR_AMD64_CPUID_FN_1,
+	};
+
+	pr_info("x86/pm: family %#hx cpu detected, MSR saving is needed during suspending.\n",
+		c->family);
+
+	return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
+}
+
+static const struct x86_cpu_id msr_save_cpu_table[] = {
+	{
+		.vendor = X86_VENDOR_AMD,
+		.family = 0x15,
+		.model = X86_MODEL_ANY,
+		.feature = X86_FEATURE_ANY,
+		.driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+	},
+	{
+		.vendor = X86_VENDOR_AMD,
+		.family = 0x16,
+		.model = X86_MODEL_ANY,
+		.feature = X86_FEATURE_ANY,
+		.driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+	},
+	{}
+};
+
+typedef int (*pm_cpu_match_t)(const struct x86_cpu_id *);
+static int pm_cpu_check(const struct x86_cpu_id *c)
+{
+	const struct x86_cpu_id *m;
+	int ret = 0;
+
+	m = x86_match_cpu(msr_save_cpu_table);
+	if (m) {
+		pm_cpu_match_t fn;
+
+		fn = (pm_cpu_match_t)m->driver_data;
+		ret = fn(m);
+	}
+
+	return ret;
+}
+
 static int pm_check_save_msr(void)
 {
 	dmi_check_system(msr_save_dmi_table);
+	pm_cpu_check(msr_save_cpu_table);
+
 	return 0;
 }
 



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

end of thread, other threads:[~2019-08-28 15:53 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-18 11:34 [GIT pull] efi/urgent for 5.3-rc5 Thomas Gleixner
2019-08-18 11:34 ` [GIT pull] x86/urgent " Thomas Gleixner
2019-08-18 16:55   ` pr-tracker-bot
2019-08-18 16:55 ` [GIT pull] efi/urgent " pr-tracker-bot
2019-08-25  9:43 [GIT pull] irq/urgent " Thomas Gleixner
2019-08-25  9:43 ` [GIT pull] x86/urgent " Thomas Gleixner
2019-08-25 17:18   ` Linus Torvalds
2019-08-25 17:30     ` Borislav Petkov
2019-08-25 17:37       ` Linus Torvalds
2019-08-25 18:29         ` Borislav Petkov
2019-08-25 18:38           ` Linus Torvalds
2019-08-25 19:32             ` Borislav Petkov
2019-08-25 19:35               ` Linus Torvalds
2019-08-25 19:49                 ` Borislav Petkov
2019-08-25 19:59                   ` Linus Torvalds
2019-08-25 20:17                     ` Borislav Petkov
2019-08-26 12:53                       ` Borislav Petkov
2019-08-27 16:55                         ` Linus Torvalds
2019-08-27 17:39                           ` Borislav Petkov
2019-08-27 17:46                             ` Linus Torvalds
2019-08-27 17:59                               ` Borislav Petkov
2019-08-28 15:20                             ` David Sterba
2019-08-28 15:53                               ` David Sterba
2019-08-25 17:40   ` pr-tracker-bot

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.