Hi Stefano,
On 05/29/2018 11:34 PM, Stefano Stabellini wrote:
On Tue, 29 May 2018, Julien Grall wrote:
On 25/05/18 21:51, Stefano Stabellini wrote:
On Thu, 24 May 2018, Julien Grall wrote:
On 23/05/18 23:34, Stefano Stabellini wrote:
On Tue, 22 May 2018, Julien Grall >>>>
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
ARM_SMCCC_ARCH_WORKAROUND_2_FID, &res);
- if ( (int)res.a0 != 0 )
- supported = false;
- if ( supported )
- this_cpu(ssbd_callback_required) = 1;
+ switch ( (int)res.a0 )
Please introduce this switch in the previous patch. But it makes sense
to add the ssbd_state variable in this patch.
Well, that's not going to make the diff simpler here as the switch will be
different. So I would keep the patch like that.
The split is a bit iffy to me, but if you don't want to change it, I can
live with it anyway.
I don't think the other way will help. But I will do it.
Thank you
+ {
+ case ARM_SMCCC_NOT_SUPPORTED:
+ ssbd_state = ARM_SSBD_UNKNOWN;
+ return false;
+
+ case ARM_SMCCC_NOT_REQUIRED:
+ ssbd_state = ARM_SSBD_MITIGATED;
+ return false;
+
+ case ARM_SMCCC_SUCCESS:
+ required = true;
+ break;
+
+ case 1: /* Mitigation not required on this CPU. */
+ required = false;
+ break;
This should "return false".
It is perfectly fine to continue as it is safe to execute
ARCH_WORKAROUND_2 on
that CPU.
This is the case where mitigation is not required but issuing the SMCCC
is safe. Instead of returning immediately, we go through the next
switch:
1) if ARM_SSBD_FORCE_DISABLE, we make the SMCCC
2) if ARM_SSBD_RUNTIME, we do nothing
3) if ARM_SSBD_FORCE_ENABLE, we make the SMCCC
What is the desired outcome for this situation? Obviously, continuing for
case 2) is pointless, we might as well return immediately. For 1) and 3)
is the intention that the SMCCC will actually have an effect even if the
mitigation is not required?
While the SMCCC call in 1) and 3) will do nothing for those CPUs, you will
still print a warning message if the user choose to force enable/disable the
mitigation.
Printing warnings could be a good idea. However, I think we should do
the same thing for "1" and for "ARM_SMCCC_NOT_REQUIRED", and maybe even
for "ARM_SMCCC_NOT_SUPPORTED": printing warnings for all or for none.
I also noticed that if the first SMCCC returns "1" and we continue, in
case ssbd_state == ARM_SSBD_FORCE_ENABLE, "required" gets changed to
"true". Do we want to let the user force-enable the mitigation even
when it will do nothing? I am not really sure, probably not? In any case
I would prefer if we kept the same behavior across "1" and
"ARM_SMCCC_NOT_REQUIRED".
I don't think it is right ot expect the same behavior for "1"and
"ARM_SMCCC_NOT_REQUIRED". There are majors difference between those 2
and ARM_SMCCC_NOT_SUPPORTED.
From the spec ARM DEN 0070A section 2.2.5:
- If your firmware does not support the call, ARM_SMCCC_NOT_SUPPORTED
will be returned for *all* CPUs. This will happen on current firmwares.
- If your firmware has mitigation permanently disabled/enabled for
*all* CPUs, ARM_SMCCC_NOT_REQUIRED will be returned.
- If one of the CPUs in the platform require dynamic mitigation, the
call will return 0 for them. The others CPUs will return 1.
Printing a warning for the first two will likely scare the user because
it is going to be printed on most of the current platforms.
Printing a warning for the last one makes sense because you know that
one of the CPU may be affected. That CPU may be bring up later on. So
you offer a print in similar place in the logs whatever the platform is.
+
+ default:
+ ASSERT_UNREACHABLE();
+ return false;
+ }
+
+ switch ( ssbd_state )
+ {
+ case ARM_SSBD_FORCE_DISABLE:
+ {
+ static bool once = true;
+
+ if ( once )
+ printk("%s disabled from command-line\n", entry->desc);
+ once = false;
+
+ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
+ required = false;
+
+ break;
+ }
+
+ case ARM_SSBD_RUNTIME:
+ if ( required )
+ {
+ this_cpu(ssbd_callback_required) = 1;
We have the ARM_SSBD bit, the ssbd_state variable and
ssbd_callback_required. Both ARM_SSBD and ssbd_state are shared across
cores while ssbd_callback_required is per-cpu. Does
ssbd_callback_required really need to be per-cpu? > Do we need both
variables? For instance, we could just return ssbd_state ==
ARM_SSBD_RUNTIME instead of this_cpu(ssbd_callback_required)?
Let me start with because a guest vCPU may run on any pCPU, you always
have to
tell the guest the mitigation is required for all vCPUs.
By default, Linux is calling the workaround at entry from EL0 to enable it
and
at exit to EL0 to disable it. The workaround will first trap in EL2 and
then
get forwarded to EL3.
You can imagine that the trap to EL2 and then EL3 has a cost. If the
workaround is not necessary, then you can reduce that cost by avoiding to
trap
at EL3. As you can have a platform with heterogenous CPUs, you need that
workaround per-CPU.
The ARM_SSBD feature bit is useful in order to put shortcut in place using
alternative (see check_workaround_ssbd). So on platform where the
mitigation
is not required, all the new code is nearly a NOP.
The ssbd_state is used in various place to know what is the global state
of
the mitigation:
- To initialize the vCPU state for the mitigation
- To report the guest what is the state of the mitigation using SMCCC
So all those variables have a specific purposes and cannot really be
replaced
by another way.
Good explanation. Please add something like this to one of the commit
messages. Please also consider the following suggestion.
Wouldn't it make sense to remove ssbd_callback_required and make
ssbd_state a per-cpu variable? The Xen command line option would remain
the same, global, but it would initialize the value of ssbd_state on all
cpus. Then, has_ssbd_mitigation would further modify ssbd_state on a
specific cpu to ARM_SSBD_UNKNOWN (if ARM_SMCCC_NOT_SUPPORTED),
ARM_SSBD_MITIGATED (if ARM_SMCCC_NOT_REQUIRED"), etc. In the common
case, the CPUs that need the workaround will have ssbd_state set to
ARM_SSBD_RUNTIME, and the others will have ARM_SSBD_UNKNOWN or
ARM_SSBD_MITIGATED, or maybe a new value ARM_SSBD_UNNECESSARY. It looks
like it would still be simple to check on ssbd_state from assembly as
well, it can still be done with one instruction, we just need to make
sure to assign integer values to the enum, such as:
ARM_SSBD_UNKNOWN = 0,
ARM_SSBD_FORCE_DISABLE = 1,
etc.
As I said in my previous e-mail, we need to know the global state of the
mitigation. This is because a vCPU may move from a affected CPU to a
non-affected one. Therefore we need to inform the same on every vCPU (i.e
mitigated, dynamic...).
All right, but if the SMCCC(ARM_SMCCC_ARCH_FEATURES_FID,
ARM_SMCCC_ARCH_WORKAROUND_2_FID) returns ARM_SMCCC_SUCCESS on cpu0 and
ARM_SMCCC_NOT_REQUIRED on cpu1, the result will be that ssbd_state is
set to ARM_SSBD_MITIGATED for all cpus. Which is not what we want?
>
It doesn't look like the vsmc would return the right value anymore.
One solution would be that has_ssbd_mitigation is not allowed to set
ssbd_state to ARM_SSBD_UNKNOWN or ARM_SSBD_MITIGATED if previously, or
afterwards, the SMCCC returns ARM_SMCCC_SUCCESS. In other words,
ARM_SMCCC_SUCCESS trumps any other return values.
There seem to be a misunderstanding of the spec. If
ARM_SMCCC_NOT_REQUIRED is returned on one CPU, it will also be returned
for all the others. It means that *all* CPUs have the mitigations
permanently enabled/disabled.
Cheers,
--
Julien Grall
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel