]> xenbits.xensource.com Git - xen.git/commitdiff
x86: possibly bring up all CPUs even if not all are supposed to be used
authorJan Beulich <JBeulich@suse.com>
Thu, 19 Jul 2018 10:32:06 +0000 (04:32 -0600)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 19 Jul 2018 12:43:33 +0000 (13:43 +0100)
Reportedly Intel CPUs which can't broadcast #MC to all targeted
cores/threads because some have CR4.MCE clear will shut down. Therefore
we want to keep CR4.MCE enabled when offlining a CPU, and we need to
bring up all CPUs in order to be able to set CR4.MCE in the first place.

The use of clear_in_cr4() in cpu_mcheck_disable() was ill advised
anyway, and to avoid future similar mistakes I'm removing clear_in_cr4()
altogether right here.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
xen/arch/x86/cpu/common.c
xen/arch/x86/cpu/mcheck/mce_intel.c
xen/arch/x86/mpparse.c
xen/arch/x86/setup.c
xen/include/asm-x86/processor.h

index 6570c2d9dcba8792154d5ff410e7564dbd3934a7..4d768d4ff6467d6e451800b3280d967591cefb77 100644 (file)
@@ -13,6 +13,7 @@
 #include <public/sysctl.h> /* for XEN_INVALID_{SOCKET,CORE}_ID */
 
 #include "cpu.h"
+#include "mcheck/x86_mca.h"
 
 bool_t opt_arat = 1;
 boolean_param("arat", opt_arat);
@@ -343,6 +344,9 @@ static void __init early_cpu_detect(void)
                        hap_paddr_bits = PADDR_BITS;
        }
 
+       if (c->x86_vendor != X86_VENDOR_AMD)
+               park_offline_cpus = opt_mce;
+
        initialize_cpu_data(0);
 }
 
index e5dd956a24592096f015b3eebbb6b02b7f9cb764..4474a34e347fc93103c2f3dd6bd9d7b0d8940b62 100644 (file)
@@ -636,8 +636,6 @@ static void clear_cmci(void)
 
 static void cpu_mcheck_disable(void)
 {
-    clear_in_cr4(X86_CR4_MCE);
-
     if ( cmci_support && opt_mce )
         clear_cmci();
 }
index 49140e46f0375053b84ee1c1a25651d47cf9f266..f3f6d48668d649537dedb05fcc6d2af0c9fc5aba 100644 (file)
@@ -68,19 +68,26 @@ physid_mask_t phys_cpu_present_map;
 
 void __init set_nr_cpu_ids(unsigned int max_cpus)
 {
+       unsigned int tot_cpus = num_processors + disabled_cpus;
+
        if (!max_cpus)
-               max_cpus = num_processors + disabled_cpus;
+               max_cpus = tot_cpus;
        if (max_cpus > NR_CPUS)
                max_cpus = NR_CPUS;
        else if (!max_cpus)
                max_cpus = 1;
        printk(XENLOG_INFO "SMP: Allowing %u CPUs (%d hotplug CPUs)\n",
               max_cpus, max_t(int, max_cpus - num_processors, 0));
-       nr_cpu_ids = max_cpus;
+
+       if (!park_offline_cpus)
+               tot_cpus = max_cpus;
+       nr_cpu_ids = min(tot_cpus, NR_CPUS + 0u);
+       if (park_offline_cpus && nr_cpu_ids < num_processors)
+               printk(XENLOG_WARNING "SMP: Cannot bring up %u further CPUs\n",
+                      num_processors - nr_cpu_ids);
 
 #ifndef nr_cpumask_bits
-       nr_cpumask_bits = (max_cpus + (BITS_PER_LONG - 1)) &
-                         ~(BITS_PER_LONG - 1);
+       nr_cpumask_bits = ROUNDUP(nr_cpu_ids, BITS_PER_LONG);
        printk(XENLOG_DEBUG "NR_CPUS:%u nr_cpumask_bits:%u\n",
               NR_CPUS, nr_cpumask_bits);
 #endif
index 8690535aa71c8eeb0aa463b232131df37c9e6940..dfaf8065492d0d37fe1eeb4f0296a7c976237f8c 100644 (file)
@@ -665,7 +665,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 {
     char *memmap_type = NULL;
     char *cmdline, *kextra, *loader;
-    unsigned int initrdidx;
+    unsigned int initrdidx, num_parked = 0;
     multiboot_info_t *mbi;
     module_t *mod;
     unsigned long nr_pages, raw_max_page, modules_headroom, *module_map;
@@ -1512,7 +1512,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     else
     {
         set_nr_cpu_ids(max_cpus);
-        max_cpus = nr_cpu_ids;
+        if ( !max_cpus )
+            max_cpus = nr_cpu_ids;
     }
 
     if ( xen_guest )
@@ -1635,16 +1636,27 @@ void __init noreturn __start_xen(unsigned long mbi_p)
             /* Set up node_to_cpumask based on cpu_to_node[]. */
             numa_add_cpu(i);
 
-            if ( (num_online_cpus() < max_cpus) && !cpu_online(i) )
+            if ( (park_offline_cpus || num_online_cpus() < max_cpus) &&
+                 !cpu_online(i) )
             {
                 int ret = cpu_up(i);
                 if ( ret != 0 )
                     printk("Failed to bring up CPU %u (error %d)\n", i, ret);
+                else if ( num_online_cpus() > max_cpus )
+                {
+                    ret = cpu_down(i);
+                    if ( !ret )
+                        ++num_parked;
+                    else
+                        printk("Could not re-offline CPU%u (%d)\n", i, ret);
+                }
             }
         }
     }
 
     printk("Brought up %ld CPUs\n", (long)num_online_cpus());
+    if ( num_parked )
+        printk(XENLOG_INFO "Parked %u CPUs\n", num_parked);
     smp_cpus_done();
 
     do_initcalls();
index ac1577c61ed2afa91f85b58a6afe993a10602e1d..a16680234447485a8fd39c2de6b25d0bc55d8bb8 100644 (file)
@@ -342,12 +342,6 @@ static always_inline void set_in_cr4 (unsigned long mask)
     write_cr4(read_cr4() | mask);
 }
 
-static always_inline void clear_in_cr4 (unsigned long mask)
-{
-    mmu_cr4_features &= ~mask;
-    write_cr4(read_cr4() & ~mask);
-}
-
 static inline unsigned int read_pkru(void)
 {
     unsigned int pkru;