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

[PATCH 1/2] x86/ucode: allow cpu_request_microcode() to skip memory allocation


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx>
  • Date: Thu, 8 Dec 2022 13:26:38 +0000
  • Authentication-results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Sergey Dyasli <sergey.dyasli@xxxxxxxxxx>
  • Delivery-date: Thu, 08 Dec 2022 13:26:50 +0000
  • Ironport-data: A9a23:joPi/aAzYZ8/yhVW/yLjw5YqxClBgxIJ4kV8jS/XYbTApG8jg2MAm mIdUWCGOfiIYTGnfNEga9yz/EhXupHUn9ZiQQY4rX1jcSlH+JHPbTi7wuUcHAvJd5GeExg3h yk6QoOdRCzhZiaE/n9BCpC48T8nk/nNHuCnYAL9EngZbRd+Tys8gg5Ulec8g4p56fC0GArIs t7pyyHlEAbNNwVcbyRFtcpvlDs15K6o4WlA7gRnDRx2lAS2e0c9Xcp3yZ6ZdxMUcqEMdsamS uDKyq2O/2+x13/B3fv8z94X2mVTKlLjFVDmZkh+AsBOsTAbzsAG6Y4pNeJ0VKtio27hc+ada jl6ncfYpQ8BZsUgkQmGOvVSO3kW0aZuoNcrLZUj2CA6IoKvn3bEmp1T4E8K0YIw4sVcHjge3 PchAXNSdDeSt8+KxYmLVbw57igjBJGD0II3v3hhyXfSDOo8QICFSKLPjTNa9G5u3IYUR6+YP pdHL2o0BPjDS0Qn1lM/E58kk+q5wHXueiZcqXqepLYt4niVxwt0uFToGIqKJILWGpQP9qqej kDK1n/BLzoxDt2WzWag8zGRm7b+jDyuDer+E5Xnr6U30TV/3Fc7Fxk+RVa95/6jhSaWS99Zb kAZ5Ccqhawz71CwCMnwWQWip3yJtQJaXMBfe8U44gyQzqvf4y6CG3MJCDVGbbQbWNQeHGJwk AXTxpWwWGIp4Ob9pW+hGqm8tRCZJnFFBGQ7TGxbVywU0/TfpboDkUeaJjp8K5KdgtrwEDD25 jmFqikimrke5fI2O7WHEUPv2Gz1+MWQJuIhzkCOBz/+sFslDGKwT9bwgWU3+8qsO2pworOpm HEf0/aT4+kVZX1mvHzcGb5ddF1FChvsDdE9vbKNN8N5n9hO0yT5FWy13N2ZDBkBDyr8UWW1C HI/QCsIjHOpAFOkbLVsf6W6ANkwwK7rGLzND66LNoYVMsAqLVXZpEmCgHJ8OEi0wSARfVwXY 8/HIa5A815FYUiY8NZGb7hEiuJ6rszP7WjSWYr633yaPUm2PRaopUM+GALWNIgRtfrUyDg5B v4Db6NmPT0DCryhCsQWmKZPRW03wY8TXMyt95QNKLfcSuekcUl4Y8LsLXoaU9QNt8xoei3gp xlRhmcwJILDuED6
  • Ironport-hdrordr: A9a23:Jq2DjKy/i1XwqTZQno+fKrPw1r1zdoMgy1knxilNoHxuH/BwWf rPoB17726RtN91YhsdcL+7V5VoLUmzyXcX2/h1AV7BZniEhILAFugLgbcKqweKJ8SUzJ8+6U 4PSclD4N2bNykGsS75ijPIb+rJFrO8gd+VbeS19QYScelzAZsQiDuQkmygYzZLrA8tP+teKL OsovBpihCHYnotYsGyFhA+LpL+T42iruOeXfYebSRXkDWzsQ==
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

This is a preparatory step in order to do earlier microcode loading on
the boot CPU when the domain heap has not been initialized yet and
xmalloc still unavailable.

Add make_copy argument which will allow to load microcode directly from
the blob bypassing microcode_cache. Add const qualifiers where required.

Signed-off-by: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx>
---
 xen/arch/x86/cpu/microcode/amd.c     | 17 +++++++++++------
 xen/arch/x86/cpu/microcode/core.c    | 18 +++++++++---------
 xen/arch/x86/cpu/microcode/intel.c   | 17 +++++++++++------
 xen/arch/x86/cpu/microcode/private.h | 18 ++++++++++++------
 4 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c
index 8195707ee1..d4df3c4806 100644
--- a/xen/arch/x86/cpu/microcode/amd.c
+++ b/xen/arch/x86/cpu/microcode/amd.c
@@ -299,11 +299,11 @@ static int scan_equiv_cpu_table(const struct 
container_equiv_table *et)
     return -ESRCH;
 }
 
-static struct microcode_patch *cf_check cpu_request_microcode(
-    const void *buf, size_t size)
+static const struct microcode_patch *cf_check cpu_request_microcode(
+    const void *buf, size_t size, bool make_copy)
 {
     const struct microcode_patch *saved = NULL;
-    struct microcode_patch *patch = NULL;
+    const struct microcode_patch *patch = NULL;
     size_t saved_size = 0;
     int error = 0;
 
@@ -411,9 +411,14 @@ static struct microcode_patch *cf_check 
cpu_request_microcode(
 
     if ( saved )
     {
-        patch = xmemdup_bytes(saved, saved_size);
-        if ( !patch )
-            error = -ENOMEM;
+        if ( make_copy )
+        {
+            patch = xmemdup_bytes(saved, saved_size);
+            if ( !patch )
+                error = -ENOMEM;
+        }
+        else
+            patch = saved;
     }
 
     if ( error && !patch )
diff --git a/xen/arch/x86/cpu/microcode/core.c 
b/xen/arch/x86/cpu/microcode/core.c
index 452a7ca773..924a2bd7b5 100644
--- a/xen/arch/x86/cpu/microcode/core.c
+++ b/xen/arch/x86/cpu/microcode/core.c
@@ -99,7 +99,7 @@ static bool ucode_in_nmi = true;
 bool __read_mostly opt_ucode_allow_same;
 
 /* Protected by microcode_mutex */
-static struct microcode_patch *microcode_cache;
+static const struct microcode_patch *microcode_cache;
 
 void __init microcode_set_module(unsigned int idx)
 {
@@ -240,20 +240,20 @@ static const struct microcode_patch *nmi_patch = 
ZERO_BLOCK_PTR;
  * patch is found and an error occurs during the parsing process. Otherwise
  * return NULL.
  */
-static struct microcode_patch *parse_blob(const char *buf, size_t len)
+static const struct microcode_patch *parse_blob(const char *buf, size_t len)
 {
     alternative_vcall(ucode_ops.collect_cpu_info);
 
-    return alternative_call(ucode_ops.cpu_request_microcode, buf, len);
+    return alternative_call(ucode_ops.cpu_request_microcode, buf, len, true);
 }
 
-static void microcode_free_patch(struct microcode_patch *patch)
+static void microcode_free_patch(const struct microcode_patch *patch)
 {
-    xfree(patch);
+    xfree((void *)patch);
 }
 
 /* Return true if cache gets updated. Otherwise, return false */
-static bool microcode_update_cache(struct microcode_patch *patch)
+static bool microcode_update_cache(const struct microcode_patch *patch)
 {
     ASSERT(spin_is_locked(&microcode_mutex));
 
@@ -565,7 +565,7 @@ static long cf_check microcode_update_helper(void *data)
     int ret;
     struct ucode_buf *buffer = data;
     unsigned int cpu, updated;
-    struct microcode_patch *patch;
+    const struct microcode_patch *patch;
 
     /* cpu_online_map must not change during update */
     if ( !get_cpu_maps() )
@@ -648,7 +648,7 @@ static long cf_check microcode_update_helper(void *data)
      *   this requirement can be relaxed in the future. Right now, this is
      *   conservative and good.
      */
-    ret = stop_machine_run(do_microcode_update, patch, NR_CPUS);
+    ret = stop_machine_run(do_microcode_update, (void *)patch, NR_CPUS);
 
     updated = atomic_read(&cpu_updated);
     if ( updated > 0 )
@@ -738,7 +738,7 @@ static int __init early_microcode_update_cpu(void)
     int rc = 0;
     const void *data = NULL;
     size_t len;
-    struct microcode_patch *patch;
+    const struct microcode_patch *patch;
 
     if ( ucode_blob.size )
     {
diff --git a/xen/arch/x86/cpu/microcode/intel.c 
b/xen/arch/x86/cpu/microcode/intel.c
index f5ba6d76d7..017f37e43d 100644
--- a/xen/arch/x86/cpu/microcode/intel.c
+++ b/xen/arch/x86/cpu/microcode/intel.c
@@ -323,12 +323,12 @@ static int cf_check apply_microcode(const struct 
microcode_patch *patch)
     return 0;
 }
 
-static struct microcode_patch *cf_check cpu_request_microcode(
-    const void *buf, size_t size)
+static const struct microcode_patch *cf_check cpu_request_microcode(
+    const void *buf, size_t size, bool make_copy)
 {
     int error = 0;
     const struct microcode_patch *saved = NULL;
-    struct microcode_patch *patch = NULL;
+    const struct microcode_patch *patch = NULL;
 
     while ( size )
     {
@@ -364,10 +364,15 @@ static struct microcode_patch *cf_check 
cpu_request_microcode(
 
     if ( saved )
     {
-        patch = xmemdup_bytes(saved, get_totalsize(saved));
+        if ( make_copy )
+        {
+            patch = xmemdup_bytes(saved, get_totalsize(saved));
 
-        if ( !patch )
-            error = -ENOMEM;
+            if ( !patch )
+                error = -ENOMEM;
+        }
+        else
+            patch = saved;
     }
 
     if ( error && !patch )
diff --git a/xen/arch/x86/cpu/microcode/private.h 
b/xen/arch/x86/cpu/microcode/private.h
index c085a10268..98657d39c3 100644
--- a/xen/arch/x86/cpu/microcode/private.h
+++ b/xen/arch/x86/cpu/microcode/private.h
@@ -23,16 +23,22 @@ struct microcode_ops {
      * older that what is running in the CPU.  This is a feature, to better
      * cope with corner cases from buggy firmware.)
      *
-     * If one is found, allocate and return a struct microcode_patch
-     * encapsulating the appropriate microcode patch.  Does not alias the
-     * original buffer.  Must be suitable to be freed with a single xfree().
+     * If one is found, behaviour depends on the make_copy argument:
+     *
+     *     true: allocate and return a struct microcode_patch encapsulating
+     *           the appropriate microcode patch.  Does not alias the original
+     *           buffer.  Must be suitable to be freed with a single xfree().
+     *
+     *    false: return a pointer to the patch within the original buffer.
+     *           This is useful for early microcode loading when xmalloc might
+     *           not be available yet.
      *
      * If one is not found, (nothing matches the current CPU), return NULL.
      * Also may return ERR_PTR(-err), e.g. bad container, out of memory.
      */
-    struct microcode_patch *(*cpu_request_microcode)(const void *buf,
-                                                     size_t size);
-
+    const struct microcode_patch *(*cpu_request_microcode)(const void *buf,
+                                                           size_t size,
+                                                           bool make_copy);
     /*
      * Obtain microcode-relevant details for the current CPU.  Results in
      * per_cpu(cpu_sig).
-- 
2.17.1




 


Rackspace

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