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

[Xen-devel] [PATCH v1 2/2] microcode: reject late ucode loading if any core is parked



If a core with all of its thread being parked, late ucode loading
which currently only loads ucode on online threads would lead to
differing ucode revisions in the system. In general, keeping ucode
revision consistent would be less error-prone. To this end, if there
is a parked thread doesn't have an online sibling thread, late ucode
loading is rejected.

Two threads are on the same core or computing unit iff they have
the same phys_proc_id and cpu_core_id/compute_unit_id. Based on
phys_proc_id and cpu_core_id/compute_unit_id, an unique core id
is generated for each thread. And use a bitmap to reduce the
number of comparison.

Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx>
---
Changes:
 - traverse the new parked cpu bitmap to find a parked core. It avoids
 access uninitialized cpu_data of a hot-added CPU.
 - use bitmap_empty() rather than find_first_bit() to check whether a
 bitmap is empty.
---
 xen/arch/x86/microcode.c        | 63 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/processor.h |  1 +
 2 files changed, 64 insertions(+)

diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c
index 65d1f41..dcc8e4b 100644
--- a/xen/arch/x86/microcode.c
+++ b/xen/arch/x86/microcode.c
@@ -584,6 +584,51 @@ static int do_microcode_update(void *patch)
     return ret;
 }
 
+static unsigned int unique_core_id(unsigned int cpu, unsigned int socket_shift)
+{
+    unsigned int core_id = cpu_to_cu(cpu);
+
+    if ( core_id == INVALID_CUID )
+        core_id = cpu_to_core(cpu);
+
+    return (cpu_to_socket(cpu) << socket_shift) + core_id;
+}
+
+static int has_parked_core(void)
+{
+    int ret;
+    unsigned int cpu, max_bits, core_width;
+    unsigned int max_sockets = 1, max_cores = 1;
+    unsigned long *bitmap;
+
+    if ( !park_offline_cpus )
+        return 0;
+
+    for_each_parked_cpu(cpu)
+    {
+        /* Note that cpu_to_socket() get an ID starting from 0. */
+        max_sockets = max(max_sockets, cpu_to_socket(cpu) + 1);
+        max_cores = max(max_cores, cpu_data[cpu].x86_max_cores);
+    }
+
+    core_width = fls(max_cores);
+    max_bits = max_sockets << core_width;
+    bitmap = xzalloc_array(unsigned long, BITS_TO_LONGS(max_bits));
+    if ( !bitmap )
+        return -ENOMEM;
+
+    for_each_parked_cpu(cpu)
+        __set_bit(unique_core_id(cpu, core_width), bitmap);
+
+    for_each_online_cpu(cpu)
+        __clear_bit(unique_core_id(cpu, core_width), bitmap);
+
+    ret = !bitmap_empty(bitmap, max_bits);
+    xfree(bitmap);
+
+    return ret;
+}
+
 int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len)
 {
     int ret;
@@ -629,6 +674,24 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) 
buf, unsigned long len)
         return -EPERM;
     }
 
+    /*
+     * If there is a core with all of its threads parked, late loading may
+     * cause differing ucode revisions in the system. Refuse this operation.
+     */
+    ret = has_parked_core();
+    if ( ret )
+    {
+        if ( ret > 0 )
+        {
+            printk(XENLOG_WARNING
+                   "Aborted: found a parked core (parked CPU bitmap: %*pbl)\n",
+                   CPUMASK_PR(cpu_parked_map));
+            ret = -EPERM;
+        }
+        xfree(buffer);
+        goto put;
+    }
+
     patch = parse_blob(buffer, len);
     xfree(buffer);
     if ( IS_ERR(patch) )
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 557f9b6..f8a9e93 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -171,6 +171,7 @@ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 
*c);
 
 #define cpu_to_core(_cpu)   (cpu_data[_cpu].cpu_core_id)
 #define cpu_to_socket(_cpu) (cpu_data[_cpu].phys_proc_id)
+#define cpu_to_cu(_cpu)     (cpu_data[_cpu].compute_unit_id)
 
 unsigned int apicid_to_socket(unsigned int);
 
-- 
1.8.3.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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