[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging-4.12] x86: clear RDRAND CPUID bit on AMD family 15h/16h



commit aca68b9ca9a39e88f42a35cd9aae1ce5d08d6154
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Wed Jun 24 17:10:22 2020 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Jun 24 17:10:22 2020 +0200

    x86: clear RDRAND CPUID bit on AMD family 15h/16h
    
    Inspired by Linux commit c49a0a80137c7ca7d6ced4c812c9e07a949f6f24:
    
        There have been reports of RDRAND issues after resuming from suspend on
        some AMD family 15h and family 16h systems. This issue stems from a BIOS
        not performing the proper steps during resume to ensure RDRAND continues
        to function properly.
    
        Update the CPU initialization to clear the RDRAND CPUID bit for any 
family
        15h and 16h processor that supports RDRAND. If it is known that the 
family
        15h or family 16h system does not have an RDRAND resume issue or that 
the
        system will not be placed in suspend, the "cpuid=rdrand" kernel 
parameter
        can be used to stop the clearing of the RDRAND CPUID bit.
    
        Note, that clearing the RDRAND CPUID bit does not prevent a processor
        that normally supports the RDRAND instruction from executing it. So any
        code that determined the support based on family and model won't #UD.
    
    Warn if no explicit choice was given on affected hardware.
    
    Check RDRAND functions at boot as well as after S3 resume (the retry
    limit chosen is entirely arbitrary).
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    master commit: 93401e28a84b9dc5945f5d0bf5bce68e9d5ee121
    master date: 2020-05-27 09:49:37 +0200
---
 docs/misc/xen-command-line.pandoc |  5 ++++-
 xen/arch/x86/cpu/amd.c            | 21 +++++++++++++++++++++
 xen/arch/x86/cpu/common.c         | 27 +++++++++++++++++++++++++++
 xen/arch/x86/cpuid.c              |  2 ++
 xen/include/asm-x86/processor.h   |  1 +
 5 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/docs/misc/xen-command-line.pandoc 
b/docs/misc/xen-command-line.pandoc
index 7897da55ca..d7919f2ed4 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -492,7 +492,10 @@ The Speculation Control hardware features `srbds-ctrl`, 
`md-clear`, `ibrsb`,
 applicable.  They can all be ignored.
 
 `rdrand` and `rdseed` can be ignored, as a mitigation to XSA-320 /
-CVE-2020-0543.
+CVE-2020-0543.  The RDRAND feature is disabled by default on certain AMD
+systems, due to possible malfunctions after ACPI S3 suspend/resume.  `rdrand`
+may be used in its positive form to override Xen's default behaviour on these
+systems, and make the feature fully usable.
 
 ### cpuid_mask_cpu
 > `= fam_0f_rev_[cdefg] | fam_10_rev_[bc] | fam_11_rev_b`
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 7144717da7..eb48e29e17 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -3,6 +3,7 @@
 #include <xen/mm.h>
 #include <xen/smp.h>
 #include <xen/pci.h>
+#include <xen/warning.h>
 #include <asm/io.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
@@ -633,6 +634,26 @@ static void init_amd(struct cpuinfo_x86 *c)
                if (acpi_smi_cmd && (acpi_enable_value | acpi_disable_value))
                        amd_acpi_c1e_quirk = true;
                break;
+
+       case 0x15: case 0x16:
+               /*
+                * There are some Fam15/Fam16 systems where upon resume from S3
+                * firmware fails to re-setup properly functioning RDRAND.
+                * By the time we can spot the problem, it is too late to take
+                * action, and there is nothing Xen can do to repair the 
problem.
+                * Clear the feature unless force-enabled on the command line.
+                */
+               if (c == &boot_cpu_data &&
+                   cpu_has(c, X86_FEATURE_RDRAND) &&
+                   !is_forced_cpu_cap(X86_FEATURE_RDRAND)) {
+                       static const char __initconst text[] =
+                               "RDRAND may cease to work on this hardware upon 
resume from S3.\n"
+                               "Please choose an explicit cpuid={no-}rdrand 
setting.\n";
+
+                       setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+                       warning_add(text);
+               }
+               break;
        }
 
        display_cacheinfo(c);
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index f3a8c69020..9bd9e3e24e 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -10,6 +10,7 @@
 #include <asm/io.h>
 #include <asm/mpspec.h>
 #include <asm/apic.h>
+#include <asm/random.h>
 #include <mach_apic.h>
 #include <public/sysctl.h> /* for XEN_INVALID_{SOCKET,CORE}_ID */
 
@@ -94,6 +95,11 @@ void __init setup_force_cpu_cap(unsigned int cap)
        __set_bit(cap, boot_cpu_data.x86_capability);
 }
 
+bool __init is_forced_cpu_cap(unsigned int cap)
+{
+       return test_bit(cap, forced_caps);
+}
+
 static void default_init(struct cpuinfo_x86 * c)
 {
        /* Not much we can do here... */
@@ -497,6 +503,27 @@ void identify_cpu(struct cpuinfo_x86 *c)
        printk("\n");
 #endif
 
+       /*
+        * If RDRAND is available, make an attempt to check that it actually
+        * (still) works.
+        */
+       if (cpu_has(c, X86_FEATURE_RDRAND)) {
+               unsigned int prev = 0;
+
+               for (i = 0; i < 5; ++i)
+               {
+                       unsigned int cur = arch_get_random();
+
+                       if (prev && cur != prev)
+                               break;
+                       prev = cur;
+               }
+
+               if (i >= 5)
+                       printk(XENLOG_WARNING "CPU%u: RDRAND appears to not 
work\n",
+                              smp_processor_id());
+       }
+
        if (system_state == SYS_STATE_resume)
                return;
 
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index d07567c901..91faf02a2b 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -68,6 +68,8 @@ static int __init parse_xen_cpuid(const char *s)
         {
             if ( !val )
                 setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+            else if ( (cpuid_ecx(1) & cpufeat_mask(X86_FEATURE_RDRAND)) )
+                setup_force_cpu_cap(X86_FEATURE_RDRAND);
         }
         else if ( (val = parse_boolean("rdseed", s, ss)) >= 0 )
         {
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 1b52712180..c6f26a85b8 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -167,6 +167,7 @@ extern const struct x86_cpu_id *x86_match_cpu(const struct 
x86_cpu_id table[]);
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void setup_clear_cpu_cap(unsigned int);
 extern void setup_force_cpu_cap(unsigned int);
+extern bool is_forced_cpu_cap(unsigned int);
 extern void print_cpu_info(unsigned int cpu);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.12



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.