|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 06/10] x86/ucode: Enforce invariant about module selection
On 28/10/2024 1:56 pm, Jan Beulich wrote:
> On 28.10.2024 10:18, Andrew Cooper wrote:
>> The work to add the `ucode=nmi` cmdline option left a subtle corner case.
>> Both scan and an explicit index could be selected, and we could really find a
>> CPIO archive and explicit microcode file.
>>
>> Worse, because the if/else chains for processing ucode_{blob,mod} are
>> opposite
>> ways around in early_microcode_load() and microcode_init_cache(), we can
>> genuinely perform early microcode loading from the CPIO archive, then cache
>> from the explicit file.
>>
>> Therefore, enforce that only one selection method can be active.
> Question is - is this really the best of all possible behaviors? One may want
> to use one approach as the fallback for the other, e.g. preferably use what
> the CPIO has, but fall back to something pre-installed on the boot or EFI
> partition.
It is unfortunate behaviour.
I've seen explicit complains about it on the archlinux forums; putting a
CPIO fragment in EFI's ucode= argument and getting confused as to why it
doesn't work.
However, it is (reasonably) necessary to dis-enagle this path, and we
currently document it as "undefined behaviour".
I think that we should re-evaluate the behaviour, after the rest of the
boot cleanup is done and we have an easier time reasoning about what is
what.
>> @@ -139,12 +148,16 @@ static int __init cf_check parse_ucode(const char *s)
>> else if ( !ucode_mod_forced ) /* Not forced by EFI */
>> {
>> if ( (val = parse_boolean("scan", s, ss)) >= 0 )
>> - ucode_scan = val;
>> + {
>> + opt_scan = val;
>> + opt_mod_idx = 0;
>> + }
>> else
>> {
>> const char *q;
>>
>> - ucode_mod_idx = simple_strtol(s, &q, 0);
>> + opt_scan = false;
>> + opt_mod_idx = simple_strtol(s, &q, 0);
>> if ( q != ss )
>> rc = -EINVAL;
>> }
> I think this latter part rather wants to be
>
> opt_mod_idx = simple_strtol(s, &q, 0);
> if ( q != ss )
> {
> opt_mod_idx = 0;
> rc = -EINVAL;
> }
> else
> opt_scan = false;
>
> to prevent a malformed ucode= to clobber an earlier wellformed ucode=scan.
> (There are limits to this of course, as an out-of-range value would still
> invalidate the "scan" request.)
Fine. I'm not overly fussed. We don't make any pretence that erroneous
cmdline settings are handled nicely.
>
>> @@ -817,17 +830,42 @@ static int __init early_microcode_load(struct
>> boot_info *bi)
>> const void *data = NULL;
>> size_t size;
>> struct microcode_patch *patch;
>> + int idx = opt_mod_idx;
>> +
>> + /*
>> + * Cmdline parsing ensures this invariant holds, so that we don't end up
>> + * trying to mix multiple ways of finding the microcode.
>> + */
>> + ASSERT(idx == 0 || !opt_scan);
>>
>> - if ( ucode_mod_idx < 0 )
>> - ucode_mod_idx += bi->nr_modules;
>> - if ( ucode_mod_idx <= 0 || ucode_mod_idx >= bi->nr_modules ||
>> - !__test_and_clear_bit(ucode_mod_idx, bi->module_map) )
>> - goto scan;
>> - ucode_mod = *bi->mods[ucode_mod_idx].mod;
>> - scan:
> Oh, the goto and label are going away here anyway. Never mind the comment on
> the earlier patch then.
Thanks, and yes.
I did play with the order quite a lot. The first iteration did clean
this up as part of merging into early_microcode_load(), but it turned
into a mess.
This way around (straight fold in the previous patch, rework here given
the invariant) was the cleanest I came up with.
~Andrew
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |