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

Re: [Xen-devel] [PATCH v12] microcode: rendezvous CPUs in NMI handler and load ucode



On 27.09.2019 18:12, Chao Gao wrote:
> @@ -105,23 +110,40 @@ void __init microcode_set_module(unsigned int idx)
>  }
>  
>  /*
> - * The format is '[<integer>|scan]'. Both options are optional.
> - * If the EFI has forced which of the multiboot payloads is to be used,
> - * no parsing will be attempted.
> + * The format is '[<integer>|scan=<bool>, nmi=<bool>]'. Both options are
> + * optional. If the EFI has forced which of the multiboot payloads is to be
> + * used, only nmi=<bool> is parsed.
>   */
>  static int __init parse_ucode(const char *s)
>  {
> -    const char *q = NULL;
> +    const char *ss;
> +    int val, rc = 0;
>  
> -    if ( ucode_mod_forced ) /* Forced by EFI */
> -       return 0;
> +    do {
> +        ss = strchr(s, ',');
> +        if ( !ss )
> +            ss = strchr(s, '\0');
>  
> -    if ( !strncmp(s, "scan", 4) )
> -        ucode_scan = 1;
> -    else
> -        ucode_mod_idx = simple_strtol(s, &q, 0);
> +        if ( (val = parse_boolean("nmi", s, ss)) >= 0 )
> +            ucode_in_nmi = val;
> +        else if ( !ucode_mod_forced ) /* Not forced by EFI */
> +        {
> +            if ( (val = parse_boolean("scan", s, ss)) >= 0 )
> +                ucode_scan = val;
> +            else
> +            {
> +                const char *q = NULL;

I don't think the initializer is needed here.

>  static int primary_thread_fn(const struct microcode_patch *patch)
>  {
> -    int ret = 0;
> -
>      if ( !wait_for_state(LOADING_CALLIN) )
>          return -EBUSY;
>  
> -    cpumask_set_cpu(smp_processor_id(), &cpu_callin_map);
> +    if ( ucode_in_nmi )
> +    {
> +        self_nmi();
>  
> -    if ( !wait_for_state(LOADING_ENTER) )
> -        return -EBUSY;
> +        /*
> +         * Wait for ucode loading is done in case that the NMI does not 
> arrive
> +         * synchronously, which may lead to a not-yet-updated error is 
> returned
> +         * below.
> +         */
> +        if ( unlikely(!wait_for_state(LOADING_EXIT)) )
> +            ASSERT_UNREACHABLE();
>  
> -    ret = microcode_ops->apply_microcode(patch);
> -    if ( !ret )
> -        atomic_inc(&cpu_updated);
> -    atomic_inc(&cpu_out);
> +        return this_cpu(loading_err);
> +    }
>  
> -    return ret;
> +    return primary_thread_work(patch);
>  }

A remark on the code structure - the overall amount of indentation
would have been less if you negated the if() expression.

> @@ -405,6 +489,10 @@ static int control_thread_fn(const struct 
> microcode_patch *patch)
>       */
>      watchdog_disable();
>  
> +    nmi_patch = patch;
> +    smp_wmb();
> +    saved_nmi_callback = set_nmi_callback(microcode_nmi_callback);
> +
>      /* Allow threads to call in */
>      set_state(LOADING_CALLIN);

Seeing the blank line you keep here after watchdog_disable(), ...

> @@ -455,6 +552,9 @@ static int control_thread_fn(const struct microcode_patch 
> *patch)
>      /* Mark loading is done to unblock other threads */
>      set_state(LOADING_EXIT);
>  
> +    set_nmi_callback(saved_nmi_callback);
> +    smp_wmb();
> +    nmi_patch = ZERO_BLOCK_PTR;
>      watchdog_enable();

... for consistency there would better have been one left ahead of
watchdog_enable() here as well.

Preferably with at least the first and last items taken care of
(which ought to be easy enough to do while committing)
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>

Jan

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

 


Rackspace

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