Re: [PATCH v1 Part2 3/5] x86/microcode: Add a generic mechanism to declare support for minrev

From: Thomas Gleixner
Date: Thu Jan 19 2023 - 19:15:14 EST


Ashok!

On Fri, Jan 13 2023 at 09:29, Ashok Raj wrote:
> Intel microcode adds some meta-data to report a minimum required revision
> before this new microcode can be safely late loaded. There are no generic

s/this new microcode/a new microcode revision/

Changelogs are not restricted by twitter posting rules.

> mechanism to declare support for all vendors.
>
> Add generic support to microcode core to declare such support, this allows
> late-loading to be permitted in those architectures that report support
> for safe late loading.
>
> Late loading has added support for
>
> - New images declaring a required minimum base version before a late-load
> is performed.
>
> Tainting only happens on architectures that don't support minimum required
> version reporting.
>
> Add a new variable in microcode_ops to allow an architecture to declare
> support for safe microcode late loading.
> @@ -487,13 +488,22 @@ static ssize_t reload_store(struct device *dev,
> if (ret)
> goto put;
>
> + safe_late_load = microcode_ops->safe_late_load;
> +
> + /*
> + * If safe loading indication isn't present, bail out.
> + */
> + if (!safe_late_load) {
> + pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
> + pr_err("You should switch to early loading, if possible.\n");
> + ret = -EINVAL;
> + goto put;
> + }
> +
> tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev);
> if (tmp_ret != UCODE_NEW)
> goto put;
>
> - pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
> - pr_err("You should switch to early loading, if possible.\n");
> -

Why are you not moving the pr_err()s right away (in 1/5) to the place
where you move it now?

> mutex_lock(&microcode_mutex);
> ret = microcode_reload_late();
> mutex_unlock(&microcode_mutex);
> @@ -501,11 +511,16 @@ static ssize_t reload_store(struct device *dev,
> put:
> cpus_read_unlock();
>
> + /*
> + * Only taint if a successful load and vendor doesn't support
> + * safe_late_load
> + */
> + if (!(ret && safe_late_load))
> + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);

The resulting code is undecodable garbage. Whats worse is that the
existing logic in this code is broken already.

#1
ssize_t ret = 0;

This 'ret = 0' assignment is pointless as ret is immediately overwritten
by the next line:

ret = kstrtoul(buf, 0, &val);
if (ret)
return ret;

if (val != 1)
return size;

Now this is really useful. If the value is invalid, i.e. it causes the
function to abort immediately it returns 'size' which means the write
was successful. Oh well.

Now lets look at a few lines further down:

#2

ssize_t ret = 0;
...
ret = check_online_cpus();
if (ret)
goto put;
...
put:
...
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
...
return ret;

Why are we tainting the kernel when there was absolutely ZERO action
done here? All what check_online_cpus() figured out was that not enough
CPUs were online, right? That justfies a error return, but the taint is
bogus, no?

The next bogosity is:

ssize_t ret = 0;
...
tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev);
if (tmp_ret != UCODE_NEW)
goto put;
...
put:
...
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);

if (ret == 0)
ret = size;

return ret;

IOW, the microcode request can fail for whatever reason and the return
value is unconditionally 'size' which means the write to the sysfs file
is successfull.

#3

Not to talk about the completely broken error handling in the actual
microcode loading case in __reload_late()::wait_for_siblings code path.

Maybe more #...

How does any of this make sense and allows sensible scripting of this
interface?

Surely you spent several orders of magnitude more time to stare at this
code than I did during this review, no?

Now instead of noticing and fixing any of this nonsense you are duct
taping this whole safe_late_load handling into that mess to make it even
more incomprehensible.

If you expected an alternative patch here, then I have to disappoint
you.

I'm not presenting you the proper solution this time on a silver tablet
because I'm in the process of taming my 'let me fix this for you' reflex
to prepare for my retirement some years down the road.

But you should have enough hints to fix all of this for real, right?

Thanks,

tglx