x86 ucode: add S3 microcode update
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 22 Jan 2009 11:17:48 +0000 (11:17 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 22 Jan 2009 11:17:48 +0000 (11:17 +0000)
When wakeup from S3, use per cpu microcode image to update cpu
microcode.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
xen/arch/x86/acpi/power.c
xen/arch/x86/microcode.c
xen/arch/x86/microcode_amd.c
xen/arch/x86/microcode_intel.c
xen/arch/x86/smpboot.c
xen/include/asm-x86/microcode.h
xen/include/asm-x86/processor.h

index ccad2ea5eea5c1e828424caa1f364a7a6d94c5b0..fce2163ffc3468f619abb7c31fdee3c5e1c12e49 100644 (file)
@@ -221,6 +221,7 @@ static int enter_state(u32 state)
 
  enable_cpu:
     cpufreq_add_cpu(0);
+    microcode_resume_cpu(0);
     enable_nonboot_cpus();
     thaw_domains();
     spin_unlock(&pm_lock);
index 80526a61031d7ae3fc54e4638dc9af51525fab0a..ebad6ef11d694fed6717b79e5cf8793bb0099867 100644 (file)
@@ -86,14 +86,15 @@ int microcode_resume_cpu(int cpu)
         return err;
     }
 
-    if ( memcmp(&nsig, &uci->cpu_sig, sizeof(nsig)) )
+    if ( microcode_ops->microcode_resume_match(cpu, &nsig) )
+    {
+        return microcode_ops->apply_microcode(cpu);
+    }
+    else
     {
         microcode_fini_cpu(cpu);
-        /* Should we look for a new ucode here? */
         return -EIO;
     }
-
-    return microcode_ops->apply_microcode(cpu);
 }
 
 static int microcode_update_cpu(const void *buf, size_t size)
index 730dce0a0bc2f3a2edf8a49f554c43dd93ec35cc..77053c258df53aebf5ffebd258c0516dc75cf0dd 100644 (file)
@@ -318,7 +318,13 @@ out:
     return error;
 }
 
+static int microcode_resume_match(int cpu, struct cpu_signature *nsig)
+{
+    return 0;
+}
+
 static struct microcode_ops microcode_amd_ops = {
+    .microcode_resume_match           = microcode_resume_match,
     .cpu_request_microcode            = cpu_request_microcode,
     .collect_cpu_info                 = collect_cpu_info,
     .apply_microcode                  = apply_microcode,
index c93df509adb06b2eaea64d18245add6506eaa425..7d8657ff2ffa10e35c8ebd7035a16a55553ff889 100644 (file)
@@ -360,7 +360,16 @@ static int cpu_request_microcode(int cpu, const void *buf, size_t size)
     return error;
 }
 
+static int microcode_resume_match(int cpu, struct cpu_signature *nsig)
+{
+    struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+    return (sigmatch(nsig->sig, uci->cpu_sig.sig, nsig->pf, uci->cpu_sig.pf) &&
+            (uci->cpu_sig.rev > nsig->rev));
+}
+
 static struct microcode_ops microcode_intel_ops = {
+    .microcode_resume_match           = microcode_resume_match,
     .cpu_request_microcode            = cpu_request_microcode,
     .collect_cpu_info                 = collect_cpu_info,
     .apply_microcode                  = apply_microcode,
index 8eae62196cc9a36bb113ba9c109646313b8abd95..a77d406f46a8eb496f8caf280facb19b54c93d54 100644 (file)
@@ -525,6 +525,8 @@ void __devinit start_secondary(void *unused)
        /* We can take interrupts now: we're officially "up". */
        local_irq_enable();
 
+       microcode_resume_cpu(cpu);
+
        wmb();
        startup_cpu_idle_loop();
 }
index 57582cfa91e543f0ee3807f2bda09dc9aeaf299e..980da227dcd8d31d0a24e656092c25dd50f1bb47 100644 (file)
@@ -5,6 +5,7 @@ struct cpu_signature;
 struct ucode_cpu_info;
 
 struct microcode_ops {
+    int (*microcode_resume_match)(int cpu, struct cpu_signature *nsig);
     int (*cpu_request_microcode)(int cpu, const void *buf, size_t size);
     int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
     int (*apply_microcode)(int cpu);
index d218e50d4f5fb51e087557723a1246aad3cdc1b0..d9af37aba204ee9220edde4bc6ba5550c3c3aea7 100644 (file)
@@ -553,6 +553,7 @@ int wrmsr_hypervisor_regs(
     uint32_t idx, uint32_t eax, uint32_t edx);
 
 int microcode_update(XEN_GUEST_HANDLE(const_void), unsigned long len);
+int microcode_resume_cpu(int cpu);
 
 #endif /* !__ASSEMBLY__ */