|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v11 7/7] microcode: reject late ucode loading if any core is parked
On 26.09.2019 15:53, Chao Gao wrote:
> If a core with all of its thread being parked, late ucode loading
> which currently only loads ucode on online threads would lead to
> differing ucode revisions in the system. In general, keeping ucode
> revision consistent would be less error-prone. To this end, if there
> is a parked thread doesn't have an online sibling thread, late ucode
> loading is rejected.
>
> Two threads are on the same core or computing unit iff they have
> the same phys_proc_id and cpu_core_id/compute_unit_id. Based on
> phys_proc_id and cpu_core_id/compute_unit_id, an unique core id
> is generated for each thread. And use a bitmap to reduce the
> number of comparison.
>
> Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx>
> ---
> Alternatively, we can mask the thread id off apicid and use it
> as the unique core id. It needs to introduce new field in cpuinfo_x86
> to record the mask for thread id. So I don't take this way.
It feels a little odd that you introduce a "custom" ID, but it
should be fine without going this alternative route. (You
wouldn't need a new field though, I think, as we've got the
x86_num_siblings one already.)
What I continue to be unconvinced of is for the chosen approach
to be better than briefly unparking a thread on each core, as
previously suggested.
> --- a/xen/arch/x86/microcode.c
> +++ b/xen/arch/x86/microcode.c
> @@ -573,6 +573,64 @@ static int do_microcode_update(void *patch)
> return ret;
> }
>
> +static unsigned int unique_core_id(unsigned int cpu, unsigned int
> socket_shift)
> +{
> + unsigned int core_id = cpu_to_cu(cpu);
> +
> + if ( core_id == INVALID_CUID )
> + core_id = cpu_to_core(cpu);
> +
> + return (cpu_to_socket(cpu) << socket_shift) + core_id;
> +}
> +
> +static int has_parked_core(void)
> +{
> + int ret = 0;
I don't think you need the initializer here.
> + if ( park_offline_cpus )
if ( !park_offline_cpus )
return 0;
would allow one level less of indentation of the main part of
the function body.
> + {
> + unsigned int cpu, max_bits, core_width;
> + unsigned int max_sockets = 1, max_cores = 1;
> + struct cpuinfo_x86 *c = cpu_data;
> + unsigned long *bitmap;
> +
> + for_each_present_cpu(cpu)
> + {
> + if ( x86_cpu_to_apicid[cpu] == BAD_APICID )
> + continue;
> +
> + /* Note that cpu_to_socket() get an ID starting from 0. */
> + if ( cpu_to_socket(cpu) + 1 > max_sockets )
Instead of "+ 1", why not >= ?
> + max_sockets = cpu_to_socket(cpu) + 1;
> +
> + if ( c[cpu].x86_max_cores > max_cores )
> + max_cores = c[cpu].x86_max_cores;
What guarantees .x86_max_cores to be valid? Onlining a hot-added
CPU is a two step process afaict, XENPF_cpu_hotadd followed by
XENPF_cpu_online. In between the CPU would be marked present
(and cpu_add() would also have filled x86_cpu_to_apicid[cpu]),
but cpu_data[cpu] wouldn't have been filled yet afaict. This
also makes the results of the cpu_to_*() unreliable that you use
in unique_core_id().
However, if we assume sufficient similarity between CPU
packages (as you've done elsewhere in this series iirc), this
may not be an actual problem. But it wants mentioning in a code
comment, I think. Plus at the very least you depend on the used
cpu_data[] fields to not contain unduly large values (and hence
you e.g. depend on cpu_data[] not gaining an initializer,
setting the three fields of interest to their INVALID_* values,
as currently done by identify_cpu()).
> + }
> +
> + core_width = fls(max_cores);
> + max_bits = max_sockets << core_width;
> + bitmap = xzalloc_array(unsigned long, BITS_TO_LONGS(max_bits));
> + if ( !bitmap )
> + return -ENOMEM;
> +
> + for_each_present_cpu(cpu)
> + {
> + if ( cpu_online(cpu) || x86_cpu_to_apicid[cpu] == BAD_APICID )
> + continue;
> +
> + __set_bit(unique_core_id(cpu, core_width), bitmap);
> + }
> +
> + for_each_online_cpu(cpu)
> + __clear_bit(unique_core_id(cpu, core_width), bitmap);
> +
> + ret = (find_first_bit(bitmap, max_bits) < max_bits);
I think bitmap_empty() would be a cheaper operation for the purpose
you have, especially if further up you rounded up max_bits to a
multiple of BITS_PER_LONG.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |