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);
