All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode
@ 2019-11-22 16:47 Sergey Dyasli
  2019-11-25  2:22 ` Chao Gao
  0 siblings, 1 reply; 3+ messages in thread
From: Sergey Dyasli @ 2019-11-22 16:47 UTC (permalink / raw)
  To: xen-devel
  Cc: Juergen Gross, Sergey Dyasli, Andrew Cooper, Jan Beulich,
	Chao Gao, Roger Pau Monné

Currently if a user tries to live-load the same or older ucode revision
than CPU already has, he will get a single message in Xen log like:

    (XEN) 128 cores are to update their microcode

No actual ucode loading will happen and this situation can be quite
confusing. Fix this by starting ucode update only when the provided
ucode revision is higher than the currently cached one (if any).
This is based on the property that if microcode_cache exists, all CPUs
in the system should have at least that ucode revision.

Additionally, print a user friendly message if no newer ucode can be
found in the provided blob. This also requires ignoring -ENODATA in
AMD-side code, otherwise the message given to the user is:

    (XEN) Parsing microcode blob error -61

Which actually means that a ucode blob was parsed fine, but no matching
ucode was found.

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
---
v1 --> v2:
- compare provided ucode with the currently cached one

CC: Jan Beulich <jbeulich@suse.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Chao Gao <chao.gao@intel.com>
CC: Juergen Gross <jgross@suse.com>
---
 xen/arch/x86/microcode.c        | 12 ++++++++++--
 xen/arch/x86/microcode_amd.c    | 14 ++++++++++----
 xen/arch/x86/microcode_intel.c  | 12 +++++++++---
 xen/include/asm-x86/microcode.h |  3 ++-
 4 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c
index 65d1f41e7c..dcd2c3ff77 100644
--- a/xen/arch/x86/microcode.c
+++ b/xen/arch/x86/microcode.c
@@ -266,10 +266,16 @@ static const struct microcode_patch *nmi_patch = ZERO_BLOCK_PTR;
  */
 static struct microcode_patch *parse_blob(const char *buf, size_t len)
 {
+    struct microcode_patch *ret = NULL;
+
     if ( likely(!microcode_ops->collect_cpu_info(&this_cpu(cpu_sig))) )
-        return microcode_ops->cpu_request_microcode(buf, len);
+    {
+        spin_lock(&microcode_mutex);
+        ret = microcode_ops->cpu_request_microcode(buf, len, microcode_cache);
+        spin_unlock(&microcode_mutex);
+    }
 
-    return NULL;
+    return ret;
 }
 
 void microcode_free_patch(struct microcode_patch *microcode_patch)
@@ -641,6 +647,8 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len)
     if ( !patch )
     {
         ret = -ENOENT;
+        printk(XENLOG_WARNING "microcode: couldn't find any newer revision in "
+                              "the provided blob!\n");
         goto put;
     }
 
diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c
index 1e52f7f49a..cf63aff009 100644
--- a/xen/arch/x86/microcode_amd.c
+++ b/xen/arch/x86/microcode_amd.c
@@ -419,10 +419,11 @@ static bool_t check_final_patch_levels(unsigned int cpu)
 }
 
 static struct microcode_patch *cpu_request_microcode(const void *buf,
-                                                     size_t bufsize)
+                                            size_t bufsize,
+                                            const struct microcode_patch *cache)
 {
     struct microcode_amd *mc_amd;
-    struct microcode_header_amd *saved = NULL;
+    struct microcode_header_amd *saved = NULL, *cached = NULL;
     struct microcode_patch *patch = NULL;
     size_t offset = 0, saved_size = 0;
     int error = 0;
@@ -507,6 +508,9 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
         goto out;
     }
 
+    if ( cache && cache->mc_amd && cache->mc_amd->mpb )
+        cached = cache->mc_amd->mpb;
+
     /*
      * It's possible the data file has multiple matching ucode,
      * lets keep searching till the latest version
@@ -516,9 +520,11 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
     {
         /*
          * If the new ucode covers current CPU, compare ucodes and store the
-         * one with higher revision.
+         * one with higher revision. It must also be higher than currently
+         * cached revision.
          */
         if ( (microcode_fits(mc_amd) != MIS_UCODE) &&
+             (!cached || (compare_header(mc_amd->mpb, cached) == NEW_UCODE)) &&
              (!saved || (compare_header(mc_amd->mpb, saved) == NEW_UCODE)) )
         {
             xfree(saved);
@@ -576,7 +582,7 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
         free_patch(mc_amd);
 
   out:
-    if ( error && !patch )
+    if ( error && error != -ENODATA && !patch )
         patch = ERR_PTR(error);
 
     return patch;
diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c
index 9f66057aad..a82dd0e701 100644
--- a/xen/arch/x86/microcode_intel.c
+++ b/xen/arch/x86/microcode_intel.c
@@ -357,13 +357,17 @@ static long get_next_ucode_from_buffer(struct microcode_intel **mc,
 }
 
 static struct microcode_patch *cpu_request_microcode(const void *buf,
-                                                     size_t size)
+                                            size_t size,
+                                            const struct microcode_patch *cache)
 {
     long offset = 0;
     int error = 0;
-    struct microcode_intel *mc, *saved = NULL;
+    struct microcode_intel *mc, *saved = NULL, *cached = NULL;
     struct microcode_patch *patch = NULL;
 
+    if ( cache && cache->mc_intel )
+        cached = cache->mc_intel;
+
     while ( (offset = get_next_ucode_from_buffer(&mc, buf, size, offset)) > 0 )
     {
         error = microcode_sanity_check(mc);
@@ -375,9 +379,11 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
 
         /*
          * If the new update covers current CPU, compare updates and store the
-         * one with higher revision.
+         * one with higher revision. It must also be higher than currently
+         * cached revision.
          */
         if ( (microcode_update_match(&mc->hdr) != MIS_UCODE) &&
+             (!cached || (mc->hdr.rev > cached->hdr.rev)) &&
              (!saved || (mc->hdr.rev > saved->hdr.rev)) )
         {
             xfree(saved);
diff --git a/xen/include/asm-x86/microcode.h b/xen/include/asm-x86/microcode.h
index 7d5a1f8e8a..3dbb99cb88 100644
--- a/xen/include/asm-x86/microcode.h
+++ b/xen/include/asm-x86/microcode.h
@@ -21,7 +21,8 @@ struct microcode_patch {
 
 struct microcode_ops {
     struct microcode_patch *(*cpu_request_microcode)(const void *buf,
-                                                     size_t size);
+                                           size_t size,
+                                           const struct microcode_patch *cache);
     int (*collect_cpu_info)(struct cpu_signature *csig);
     int (*apply_microcode)(const struct microcode_patch *patch);
     int (*start_update)(void);
-- 
2.17.1


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

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

* Re: [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode
  2019-11-22 16:47 [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode Sergey Dyasli
@ 2019-11-25  2:22 ` Chao Gao
  2019-11-25 13:19   ` Jan Beulich
  0 siblings, 1 reply; 3+ messages in thread
From: Chao Gao @ 2019-11-25  2:22 UTC (permalink / raw)
  To: Sergey Dyasli
  Cc: Juergen Gross, Andrew Cooper, Roger Pau Monné,
	Jan Beulich, xen-devel

On Fri, Nov 22, 2019 at 04:47:23PM +0000, Sergey Dyasli wrote:
>Currently if a user tries to live-load the same or older ucode revision
>than CPU already has, he will get a single message in Xen log like:
>
>    (XEN) 128 cores are to update their microcode
>
>No actual ucode loading will happen and this situation can be quite
>confusing. Fix this by starting ucode update only when the provided
>ucode revision is higher than the currently cached one (if any).
>This is based on the property that if microcode_cache exists, all CPUs
>in the system should have at least that ucode revision.
>
>Additionally, print a user friendly message if no newer ucode can be
>found in the provided blob. This also requires ignoring -ENODATA in
>AMD-side code, otherwise the message given to the user is:
>
>    (XEN) Parsing microcode blob error -61
>
>Which actually means that a ucode blob was parsed fine, but no matching
>ucode was found.
>
>Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>

Reviewed-by: Chao Gao <chao.gao@intel.com>

I wonder whether it is better to put the comparison ...

>---
>v1 --> v2:
>- compare provided ucode with the currently cached one
>
>CC: Jan Beulich <jbeulich@suse.com>
>CC: Andrew Cooper <andrew.cooper3@citrix.com>
>CC: Roger Pau Monné <roger.pau@citrix.com>
>CC: Chao Gao <chao.gao@intel.com>
>CC: Juergen Gross <jgross@suse.com>
>---
> xen/arch/x86/microcode.c        | 12 ++++++++++--
> xen/arch/x86/microcode_amd.c    | 14 ++++++++++----
> xen/arch/x86/microcode_intel.c  | 12 +++++++++---
> xen/include/asm-x86/microcode.h |  3 ++-
> 4 files changed, 31 insertions(+), 10 deletions(-)
>
>diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c
>index 65d1f41e7c..dcd2c3ff77 100644
>--- a/xen/arch/x86/microcode.c
>+++ b/xen/arch/x86/microcode.c
>@@ -266,10 +266,16 @@ static const struct microcode_patch *nmi_patch = ZERO_BLOCK_PTR;
>  */
> static struct microcode_patch *parse_blob(const char *buf, size_t len)
> {
>+    struct microcode_patch *ret = NULL;
>+
>     if ( likely(!microcode_ops->collect_cpu_info(&this_cpu(cpu_sig))) )
>-        return microcode_ops->cpu_request_microcode(buf, len);
>+    {
>+        spin_lock(&microcode_mutex);
>+        ret = microcode_ops->cpu_request_microcode(buf, len, microcode_cache);
>+        spin_unlock(&microcode_mutex);
>+    }
> 
>-    return NULL;
>+    return ret;
> }
> 
> void microcode_free_patch(struct microcode_patch *microcode_patch)
>@@ -641,6 +647,8 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len)
>     if ( !patch )
>     {
>         ret = -ENOENT;
>+        printk(XENLOG_WARNING "microcode: couldn't find any newer revision in "
>+                              "the provided blob!\n");
>         goto put;
>     }

... after this if(). Then you needn't modify any vendor-specific code.

Thanks
Chao

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

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

* Re: [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode
  2019-11-25  2:22 ` Chao Gao
@ 2019-11-25 13:19   ` Jan Beulich
  0 siblings, 0 replies; 3+ messages in thread
From: Jan Beulich @ 2019-11-25 13:19 UTC (permalink / raw)
  To: Sergey Dyasli
  Cc: Juergen Gross, Andrew Cooper, Roger Pau Monné, xen-devel, Chao Gao

On 25.11.2019 03:22, Chao Gao wrote:
> On Fri, Nov 22, 2019 at 04:47:23PM +0000, Sergey Dyasli wrote:
>> Currently if a user tries to live-load the same or older ucode revision
>> than CPU already has, he will get a single message in Xen log like:
>>
>>    (XEN) 128 cores are to update their microcode
>>
>> No actual ucode loading will happen and this situation can be quite
>> confusing. Fix this by starting ucode update only when the provided
>> ucode revision is higher than the currently cached one (if any).
>> This is based on the property that if microcode_cache exists, all CPUs
>> in the system should have at least that ucode revision.
>>
>> Additionally, print a user friendly message if no newer ucode can be
>> found in the provided blob. This also requires ignoring -ENODATA in
>> AMD-side code, otherwise the message given to the user is:
>>
>>    (XEN) Parsing microcode blob error -61
>>
>> Which actually means that a ucode blob was parsed fine, but no matching
>> ucode was found.
>>
>> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
> 
> Reviewed-by: Chao Gao <chao.gao@intel.com>
> 
> I wonder whether it is better to put the comparison ...
> 
>> @@ -641,6 +647,8 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len)
>>     if ( !patch )
>>     {
>>         ret = -ENOENT;
>> +        printk(XENLOG_WARNING "microcode: couldn't find any newer revision in "
>> +                              "the provided blob!\n");
>>         goto put;
>>     }
> 
> ... after this if(). Then you needn't modify any vendor-specific code.

Yeah, this would seem to allow reducing code churn by quite a bit.

Also I think the AMD side -ENODATA ignoring would better go into
this

    if ( error )
    {
        xfree(mc_amd->equiv_cpu_table);
        xfree(mc_amd);
        goto out;
    }

block in cpu_request_microcode(), thus allowing potential future
unrelated -EONDATA to not also get ignored.

Jan

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

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

end of thread, other threads:[~2019-11-25 13:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-22 16:47 [Xen-devel] [PATCH v2 for 4.13] x86/microcode: refuse to load the same revision ucode Sergey Dyasli
2019-11-25  2:22 ` Chao Gao
2019-11-25 13:19   ` Jan Beulich

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.