All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86: Move microcode loading earlier
@ 2017-04-18 15:47 Ross Lagerwall
  2017-04-19 11:12 ` Andrew Cooper
  2017-04-19 14:02 ` Jan Beulich
  0 siblings, 2 replies; 4+ messages in thread
From: Ross Lagerwall @ 2017-04-18 15:47 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergey Dyasli, Andrew Cooper, Jan Beulich, Ross Lagerwall

Move microcode loading earlier for the boot CPU and secondary CPUs so
that it takes place before identify_cpu() is called for each CPU.
Without this, the detected features may be wrong if the new microcode
loading adjusts the feature bits. That could mean that some fixes (e.g.
d6e9f8d4f35d ("x86/vmx: fix vmentry failure with TSX bits in LBR"))
don't work as expected.

Previously during boot, the microcode loader was invoked for each
secondary CPU started and then again for each CPU as part of an
initcall. Simplify the code so that it is invoked exactly once for each
CPU during boot.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 xen/arch/x86/cpu/common.c       |   2 +
 xen/arch/x86/microcode.c        | 131 +++++++++++++++++-----------------------
 xen/arch/x86/microcode_amd.c    |   3 +-
 xen/arch/x86/microcode_intel.c  |   3 +-
 xen/arch/x86/setup.c            |   2 +
 xen/arch/x86/smpboot.c          |  33 +++++-----
 xen/include/asm-x86/processor.h |   4 ++
 xen/include/xen/smp.h           |   2 +
 8 files changed, 85 insertions(+), 95 deletions(-)

diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 9c44bbd..6c27008 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -252,6 +252,8 @@ static void __init early_cpu_detect(void)
 		if (hap_paddr_bits > PADDR_BITS)
 			hap_paddr_bits = PADDR_BITS;
 	}
+
+	initialize_cpu_data(0);
 }
 
 static void generic_identify(struct cpuinfo_x86 *c)
diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c
index 30a0806..bb2f431 100644
--- a/xen/arch/x86/microcode.c
+++ b/xen/arch/x86/microcode.c
@@ -43,7 +43,6 @@ static module_t __initdata ucode_mod;
 static void *(*__initdata ucode_mod_map)(const module_t *);
 static signed int __initdata ucode_mod_idx;
 static bool_t __initdata ucode_mod_forced;
-static cpumask_t __initdata init_mask;
 
 /*
  * If we scan the initramfs.cpio for the early microcode code
@@ -341,50 +340,23 @@ int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void) buf, unsigned long len)
     return continue_hypercall_on_cpu(info->cpu, do_microcode_update, info);
 }
 
-static void __init _do_microcode_update(unsigned long data)
-{
-    void *_data = (void *)data;
-    size_t len = ucode_blob.size ? ucode_blob.size : ucode_mod.mod_end;
-
-    microcode_update_cpu(_data, len);
-    cpumask_set_cpu(smp_processor_id(), &init_mask);
-}
-
 static int __init microcode_init(void)
 {
-    void *data;
-    static struct tasklet __initdata tasklet;
-    unsigned int cpu;
-
-    if ( !microcode_ops )
-        return 0;
-
-    if ( !ucode_mod.mod_end && !ucode_blob.size )
-        return 0;
-
-    data = ucode_blob.size ? ucode_blob.data : ucode_mod_map(&ucode_mod);
-
-    if ( !data )
-        return -ENOMEM;
-
-    if ( microcode_ops->start_update && microcode_ops->start_update() != 0 )
-        goto out;
-
-    softirq_tasklet_init(&tasklet, _do_microcode_update, (unsigned long)data);
-
-    for_each_online_cpu ( cpu )
+    /*
+     * At this point, all CPUs should have updated their microcode
+     * via the early_microcode_* paths so free the microcode blob.
+     */
+    if ( ucode_blob.size )
     {
-        tasklet_schedule_on_cpu(&tasklet, cpu);
-        do {
-            process_pending_softirqs();
-        } while ( !cpumask_test_cpu(cpu, &init_mask) );
+        xfree(ucode_blob.data);
+        ucode_blob.size = 0;
+        ucode_blob.data = NULL;
     }
-
-out:
-    if ( ucode_blob.size )
-        xfree(data);
-    else
+    else if ( ucode_mod.mod_end )
+    {
         ucode_mod_map(NULL);
+        ucode_mod.mod_end = 0;
+    }
 
     return 0;
 }
@@ -409,50 +381,55 @@ static struct notifier_block microcode_percpu_nfb = {
     .notifier_call = microcode_percpu_callback,
 };
 
-static int __init microcode_presmp_init(void)
+int __init early_microcode_update_cpu(bool_t start_update)
+{
+    int rc = 0;
+    void *data = NULL;
+    size_t len;
+
+    if ( ucode_blob.size )
+    {
+        len = ucode_blob.size;
+        data = ucode_blob.data;
+    }
+    else if ( ucode_mod.mod_end )
+    {
+        len = ucode_mod.mod_end;
+        data = ucode_mod_map(&ucode_mod);
+    }
+    if ( data )
+    {
+        if ( start_update && microcode_ops->start_update )
+            rc = microcode_ops->start_update();
+
+        if ( rc )
+            return rc;
+
+        return microcode_update_cpu(data, len);
+    }
+    else
+        return -ENOMEM;
+}
+
+int __init early_microcode_init(void)
 {
+    int rc;
+
+    rc = microcode_init_intel();
+    if ( rc )
+        return rc;
+
+    rc = microcode_init_amd();
+    if ( rc )
+        return rc;
+
     if ( microcode_ops )
     {
         if ( ucode_mod.mod_end || ucode_blob.size )
-        {
-            void *data;
-            size_t len;
-            int rc = 0;
-
-            if ( ucode_blob.size )
-            {
-                len = ucode_blob.size;
-                data = ucode_blob.data;
-            }
-            else
-            {
-                len = ucode_mod.mod_end;
-                data = ucode_mod_map(&ucode_mod);
-            }
-            if ( data )
-                rc = microcode_update_cpu(data, len);
-            else
-                rc = -ENOMEM;
-
-            if ( !ucode_blob.size )
-                ucode_mod_map(NULL);
-
-            if ( rc )
-            {
-                if ( ucode_blob.size )
-                {
-                    xfree(ucode_blob.data);
-                    ucode_blob.size = 0;
-                    ucode_blob.data = NULL;
-                }
-                else
-                    ucode_mod.mod_end = 0;
-            }
-        }
+            rc = early_microcode_update_cpu(true);
 
         register_cpu_notifier(&microcode_percpu_nfb);
     }
 
     return 0;
 }
-presmp_initcall(microcode_presmp_init);
diff --git a/xen/arch/x86/microcode_amd.c b/xen/arch/x86/microcode_amd.c
index 4759911..b54b0b9 100644
--- a/xen/arch/x86/microcode_amd.c
+++ b/xen/arch/x86/microcode_amd.c
@@ -627,10 +627,9 @@ static const struct microcode_ops microcode_amd_ops = {
     .start_update                     = start_update,
 };
 
-static __init int microcode_init_amd(void)
+int __init microcode_init_amd(void)
 {
     if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
         microcode_ops = &microcode_amd_ops;
     return 0;
 }
-presmp_initcall(microcode_init_amd);
diff --git a/xen/arch/x86/microcode_intel.c b/xen/arch/x86/microcode_intel.c
index ba3971a..c6b67e4 100644
--- a/xen/arch/x86/microcode_intel.c
+++ b/xen/arch/x86/microcode_intel.c
@@ -404,10 +404,9 @@ static const struct microcode_ops microcode_intel_ops = {
     .apply_microcode                  = apply_microcode,
 };
 
-static __init int microcode_init_intel(void)
+int __init microcode_init_intel(void)
 {
     if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
         microcode_ops = &microcode_intel_ops;
     return 0;
 }
-presmp_initcall(microcode_init_intel);
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index c3d99e9..f7b9278 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1461,6 +1461,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     timer_init();
 
+    early_microcode_init();
+
     identify_cpu(&boot_cpu_data);
 
     set_in_cr4(X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT);
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 82559ed..4e01c7b 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -83,22 +83,22 @@ static enum cpu_state {
 
 void *stack_base[NR_CPUS];
 
+void initialize_cpu_data(unsigned int cpu)
+{
+    *(cpu_data + cpu) = boot_cpu_data;
+}
+
 static void smp_store_cpu_info(int id)
 {
-    struct cpuinfo_x86 *c = cpu_data + id;
     unsigned int socket;
 
-    *c = boot_cpu_data;
-    if ( id != 0 )
-    {
-        identify_cpu(c);
+    identify_cpu(cpu_data + id);
 
-        socket = cpu_to_socket(id);
-        if ( !socket_cpumask[socket] )
-        {
-            socket_cpumask[socket] = secondary_socket_cpumask;
-            secondary_socket_cpumask = NULL;
-        }
+    socket = cpu_to_socket(id);
+    if ( !socket_cpumask[socket] )
+    {
+        socket_cpumask[socket] = secondary_socket_cpumask;
+        secondary_socket_cpumask = NULL;
     }
 }
 
@@ -332,6 +332,13 @@ void start_secondary(void *unused)
 
     cpu_init();
 
+    initialize_cpu_data(cpu);
+
+    if ( system_state <= SYS_STATE_smp_boot )
+        early_microcode_update_cpu(false);
+    else
+        microcode_resume_cpu(cpu);
+
     smp_callin();
 
     init_percpu_time();
@@ -364,8 +371,6 @@ void start_secondary(void *unused)
     local_irq_enable();
     mtrr_ap_init();
 
-    microcode_resume_cpu(cpu);
-
     wmb();
     startup_cpu_idle_loop();
 }
@@ -780,7 +785,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
     mtrr_aps_sync_begin();
 
     /* Setup boot CPU information */
-    smp_store_cpu_info(0); /* Final full version of the data */
+    initialize_cpu_data(0); /* Final full version of the data */
     print_cpu_info(0);
 
     boot_cpu_physical_apicid = get_apic_id();
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 75632d9..7762356 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -563,6 +563,10 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val);
 void microcode_set_module(unsigned int);
 int microcode_update(XEN_GUEST_HANDLE_PARAM(const_void), unsigned long len);
 int microcode_resume_cpu(unsigned int cpu);
+int early_microcode_update_cpu(bool_t start_update);
+int early_microcode_init(void);
+int microcode_init_intel(void);
+int microcode_init_amd(void);
 
 enum get_cpu_vendor {
     gcv_host,
diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h
index 6febb56..c55f57f 100644
--- a/xen/include/xen/smp.h
+++ b/xen/include/xen/smp.h
@@ -71,4 +71,6 @@ int alloc_cpu_id(void);
 
 extern void *stack_base[NR_CPUS];
 
+void initialize_cpu_data(unsigned int cpu);
+
 #endif /* __XEN_SMP_H__ */
-- 
2.7.4


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

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

* Re: [PATCH] x86: Move microcode loading earlier
  2017-04-18 15:47 [PATCH] x86: Move microcode loading earlier Ross Lagerwall
@ 2017-04-19 11:12 ` Andrew Cooper
  2017-04-19 11:29   ` Julien Grall
  2017-04-19 14:02 ` Jan Beulich
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Cooper @ 2017-04-19 11:12 UTC (permalink / raw)
  To: Ross Lagerwall, xen-devel; +Cc: Sergey Dyasli, Julien Grall, Jan Beulich

On 18/04/17 16:47, Ross Lagerwall wrote:
> Move microcode loading earlier for the boot CPU and secondary CPUs so
> that it takes place before identify_cpu() is called for each CPU.
> Without this, the detected features may be wrong if the new microcode
> loading adjusts the feature bits. That could mean that some fixes (e.g.
> d6e9f8d4f35d ("x86/vmx: fix vmentry failure with TSX bits in LBR"))
> don't work as expected.
>
> Previously during boot, the microcode loader was invoked for each
> secondary CPU started and then again for each CPU as part of an
> initcall. Simplify the code so that it is invoked exactly once for each
> CPU during boot.
>
> Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>

CC'ing Julien.  This should be taken in 4.9

This also resolves my LBR XTF test, so

Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>

Also, Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>, with 3
corrections (which I can fix on commit)

> @@ -409,50 +381,55 @@ static struct notifier_block microcode_percpu_nfb = {
>      .notifier_call = microcode_percpu_callback,
>  };
>  
> -static int __init microcode_presmp_init(void)
> +int __init early_microcode_update_cpu(bool_t start_update)

s/bool_t/bool/ throughout.

> diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
> index 82559ed..4e01c7b 100644
> --- a/xen/arch/x86/smpboot.c
> +++ b/xen/arch/x86/smpboot.c
> @@ -83,22 +83,22 @@ static enum cpu_state {
>  
>  void *stack_base[NR_CPUS];
>  
> +void initialize_cpu_data(unsigned int cpu)
> +{
> +    *(cpu_data + cpu) = boot_cpu_data;

cpu_data[cpu] = boot_cpu_data;

> +}
> +
>  static void smp_store_cpu_info(int id)
>  {
> -    struct cpuinfo_x86 *c = cpu_data + id;
>      unsigned int socket;
>  
> -    *c = boot_cpu_data;
> -    if ( id != 0 )
> -    {
> -        identify_cpu(c);
> +    identify_cpu(cpu_data + id);

&cpu_data[id]

~Andrew

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

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

* Re: [PATCH] x86: Move microcode loading earlier
  2017-04-19 11:12 ` Andrew Cooper
@ 2017-04-19 11:29   ` Julien Grall
  0 siblings, 0 replies; 4+ messages in thread
From: Julien Grall @ 2017-04-19 11:29 UTC (permalink / raw)
  To: Andrew Cooper, Ross Lagerwall, xen-devel; +Cc: Sergey Dyasli, Jan Beulich

Hi Andrew,

On 19/04/17 12:12, Andrew Cooper wrote:
> On 18/04/17 16:47, Ross Lagerwall wrote:
>> Move microcode loading earlier for the boot CPU and secondary CPUs so
>> that it takes place before identify_cpu() is called for each CPU.
>> Without this, the detected features may be wrong if the new microcode
>> loading adjusts the feature bits. That could mean that some fixes (e.g.
>> d6e9f8d4f35d ("x86/vmx: fix vmentry failure with TSX bits in LBR"))
>> don't work as expected.
>>
>> Previously during boot, the microcode loader was invoked for each
>> secondary CPU started and then again for each CPU as part of an
>> initcall. Simplify the code so that it is invoked exactly once for each
>> CPU during boot.
>>
>> Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
>
> CC'ing Julien.  This should be taken in 4.9
>
> This also resolves my LBR XTF test, so
>
> Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
>
> Also, Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>, with 3
> corrections (which I can fix on commit)

Release-acked-by: Julien Grall <julien.grall@arm.com>

Cheers,

>
>> @@ -409,50 +381,55 @@ static struct notifier_block microcode_percpu_nfb = {
>>      .notifier_call = microcode_percpu_callback,
>>  };
>>
>> -static int __init microcode_presmp_init(void)
>> +int __init early_microcode_update_cpu(bool_t start_update)
>
> s/bool_t/bool/ throughout.
>
>> diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
>> index 82559ed..4e01c7b 100644
>> --- a/xen/arch/x86/smpboot.c
>> +++ b/xen/arch/x86/smpboot.c
>> @@ -83,22 +83,22 @@ static enum cpu_state {
>>
>>  void *stack_base[NR_CPUS];
>>
>> +void initialize_cpu_data(unsigned int cpu)
>> +{
>> +    *(cpu_data + cpu) = boot_cpu_data;
>
> cpu_data[cpu] = boot_cpu_data;
>
>> +}
>> +
>>  static void smp_store_cpu_info(int id)
>>  {
>> -    struct cpuinfo_x86 *c = cpu_data + id;
>>      unsigned int socket;
>>
>> -    *c = boot_cpu_data;
>> -    if ( id != 0 )
>> -    {
>> -        identify_cpu(c);
>> +    identify_cpu(cpu_data + id);
>
> &cpu_data[id]
>
> ~Andrew
>

-- 
Julien Grall

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

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

* Re: [PATCH] x86: Move microcode loading earlier
  2017-04-18 15:47 [PATCH] x86: Move microcode loading earlier Ross Lagerwall
  2017-04-19 11:12 ` Andrew Cooper
@ 2017-04-19 14:02 ` Jan Beulich
  1 sibling, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2017-04-19 14:02 UTC (permalink / raw)
  To: Ross Lagerwall; +Cc: Andrew Cooper, xen-devel, Sergey Dyasli

>>> On 18.04.17 at 17:47, <ross.lagerwall@citrix.com> wrote:
> Move microcode loading earlier for the boot CPU and secondary CPUs so
> that it takes place before identify_cpu() is called for each CPU.
> Without this, the detected features may be wrong if the new microcode
> loading adjusts the feature bits. That could mean that some fixes (e.g.
> d6e9f8d4f35d ("x86/vmx: fix vmentry failure with TSX bits in LBR"))
> don't work as expected.
> 
> Previously during boot, the microcode loader was invoked for each
> secondary CPU started and then again for each CPU as part of an
> initcall. Simplify the code so that it is invoked exactly once for each
> CPU during boot.

The elimination of those pre-SMP initcalls makes it rather desirable to
also remove the respective ordering comment from x86/Makefile.

Jan


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

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

end of thread, other threads:[~2017-04-19 14:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-18 15:47 [PATCH] x86: Move microcode loading earlier Ross Lagerwall
2017-04-19 11:12 ` Andrew Cooper
2017-04-19 11:29   ` Julien Grall
2017-04-19 14:02 ` 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.