Hi Andre, On 5/3/19 11:33 AM, Andre Przywara wrote: > On Fri, 26 Apr 2019 17:37:47 +0200 > Auger Eric <eric.auger@xxxxxxxxxx> wrote: > > Hi, > >> Hi Andre, >> >> On 4/15/19 4:03 PM, Steven Price wrote: >>> On 15/04/2019 12:15, Andre Przywara wrote: >>>> Recent commits added the explicit notion of "Not affected" to the state >>>> of the Spectre v2 (aka. BP_HARDENING) workaround, where we just had >>>> "needed" and "unknown" before. >>>> >>>> Export this knowledge to the rest of the kernel and enhance the existing >>>> kvm_arm_harden_branch_predictor() to report this new state as well. >>>> Export this new state to guests when they use KVM's firmware interface >>>> emulation. >>>> >>>> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> >>>> --- >>>> arch/arm/include/asm/kvm_host.h | 12 +++++++++--- >>>> arch/arm64/include/asm/cpufeature.h | 6 ++++++ >>>> arch/arm64/include/asm/kvm_host.h | 16 ++++++++++++++-- >>>> arch/arm64/kernel/cpu_errata.c | 23 ++++++++++++++++++----- >>>> virt/kvm/arm/psci.c | 10 +++++++++- >>>> 5 files changed, 56 insertions(+), 11 deletions(-) >>>> >>>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h >>>> index 770d73257ad9..836479e4b340 100644 >>>> --- a/arch/arm/include/asm/kvm_host.h >>>> +++ b/arch/arm/include/asm/kvm_host.h >>>> @@ -364,7 +364,11 @@ static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {} >>>> static inline void kvm_arm_vhe_guest_enter(void) {} >>>> static inline void kvm_arm_vhe_guest_exit(void) {} >>>> >>>> -static inline bool kvm_arm_harden_branch_predictor(void) >>>> +#define KVM_BP_HARDEN_UNKNOWN -1 >>>> +#define KVM_BP_HARDEN_NEEDED 0 >>>> +#define KVM_BP_HARDEN_MITIGATED 1 >>> >>> I find the naming here a little confusing - it's not really clear what >>> "mitigated" means (see below). > > That's indeed slightly confusing, but was modelled after the SSBD > workaround below, which reads: > #define KVM_SSBD_UNKNOWN -1 > #define KVM_SSBD_FORCE_DISABLE 0 > #define KVM_SSBD_KERNEL 1 > #define KVM_SSBD_FORCE_ENABLE 2 > #define KVM_SSBD_MITIGATED 3 > > I changed the naming (for this and the other derived definitions) to: > #define KVM_BP_HARDEN_UNKNOWN -1 > #define KVM_BP_HARDEN_WA_NEEDED 0 > #define KVM_BP_HARDEN_NOT_REQUIRED 1 > >>> >>>> + >>>> +static inline int kvm_arm_harden_branch_predictor(void) >>>> { >>>> switch(read_cpuid_part()) { >>>> #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR >>>> @@ -372,10 +376,12 @@ static inline bool kvm_arm_harden_branch_predictor(void) >>>> case ARM_CPU_PART_CORTEX_A12: >>>> case ARM_CPU_PART_CORTEX_A15: >>>> case ARM_CPU_PART_CORTEX_A17: >>>> - return true; >>>> + return KVM_BP_HARDEN_NEEDED; >>>> #endif >>>> + case ARM_CPU_PART_CORTEX_A7: >>>> + return KVM_BP_HARDEN_MITIGATED; >>>> default: >>>> - return false; >>>> + return KVM_BP_HARDEN_UNKNOWN; >>>> } >>>> } >>>> >>>> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h >>>> index 6ccdc97e5d6a..3c5b25c1bda1 100644 >>>> --- a/arch/arm64/include/asm/cpufeature.h >>>> +++ b/arch/arm64/include/asm/cpufeature.h >>>> @@ -622,6 +622,12 @@ static inline bool system_uses_irq_prio_masking(void) >>>> cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING); >>>> } >>>> >>>> +#define ARM64_BP_HARDEN_UNKNOWN -1 >>>> +#define ARM64_BP_HARDEN_NEEDED 0 >>>> +#define ARM64_BP_HARDEN_MITIGATED 1 >>>> + >>>> +int get_spectre_v2_workaround_state(void); >>>> + >>>> #define ARM64_SSBD_UNKNOWN -1 >>>> #define ARM64_SSBD_FORCE_DISABLE 0 >>>> #define ARM64_SSBD_KERNEL 1 >>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h >>>> index a01fe087e022..bf9a59b7d1ce 100644 >>>> --- a/arch/arm64/include/asm/kvm_host.h >>>> +++ b/arch/arm64/include/asm/kvm_host.h >>>> @@ -555,9 +555,21 @@ static inline void kvm_arm_vhe_guest_exit(void) >>>> isb(); >>>> } >>>> >>>> -static inline bool kvm_arm_harden_branch_predictor(void) >>>> +#define KVM_BP_HARDEN_UNKNOWN -1 >>>> +#define KVM_BP_HARDEN_NEEDED 0 >>>> +#define KVM_BP_HARDEN_MITIGATED 1 >>>> + >>>> +static inline int kvm_arm_harden_branch_predictor(void) >>>> { >>>> - return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); >>>> + switch (get_spectre_v2_workaround_state()) { >>>> + case ARM64_BP_HARDEN_NEEDED: >>>> + return KVM_BP_HARDEN_NEEDED; >>>> + case ARM64_BP_HARDEN_MITIGATED: >>>> + return KVM_BP_HARDEN_MITIGATED; >>>> + case ARM64_BP_HARDEN_UNKNOWN: >>>> + default: >>>> + return KVM_BP_HARDEN_UNKNOWN; >>>> + } >>>> } >>>> >>>> #define KVM_SSBD_UNKNOWN -1 >>>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c >>>> index a1f3188c7be0..7fa23ab09d4e 100644 >>>> --- a/arch/arm64/kernel/cpu_errata.c >>>> +++ b/arch/arm64/kernel/cpu_errata.c >>>> @@ -555,6 +555,17 @@ cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) >>>> static bool __hardenbp_enab = true; >>>> static bool __spectrev2_safe = true; >>>> >>>> +int get_spectre_v2_workaround_state(void) >>>> +{ >>>> + if (__spectrev2_safe) >>>> + return ARM64_BP_HARDEN_MITIGATED; >>>> + >>>> + if (!__hardenbp_enab) >>>> + return ARM64_BP_HARDEN_UNKNOWN; >>>> + >>>> + return ARM64_BP_HARDEN_NEEDED; >>>> +} >>>> + >>>> /* >>>> * List of CPUs that do not need any Spectre-v2 mitigation at all. >>>> */ >>>> @@ -834,13 +845,15 @@ ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, >>>> ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, >>>> char *buf) >>>> { >>>> - if (__spectrev2_safe) >>>> + switch (get_spectre_v2_workaround_state()) { >>>> + case ARM64_BP_HARDEN_MITIGATED: >>>> return sprintf(buf, "Not affected\n"); >>> >>> Here "mitigated" means "not affected". >>> >>>> - >>>> - if (__hardenbp_enab) >>>> + case ARM64_BP_HARDEN_NEEDED: >>>> return sprintf(buf, "Mitigation: Branch predictor hardening\n"); >>> >>> And "harden needed" means mitigated. >>> >>>> - >>>> - return sprintf(buf, "Vulnerable\n"); >>>> + case ARM64_BP_HARDEN_UNKNOWN: >>>> + default: >>>> + return sprintf(buf, "Vulnerable\n"); >>>> + } >>>> } >>>> >>>> ssize_t cpu_show_spec_store_bypass(struct device *dev, >>>> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c >>>> index 34d08ee63747..1da53e0e38f7 100644 >>>> --- a/virt/kvm/arm/psci.c >>>> +++ b/virt/kvm/arm/psci.c >>>> @@ -412,8 +412,16 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) >>>> feature = smccc_get_arg1(vcpu); >>>> switch(feature) { >>>> case ARM_SMCCC_ARCH_WORKAROUND_1: >>>> - if (kvm_arm_harden_branch_predictor()) >>>> + switch (kvm_arm_harden_branch_predictor()) { >>>> + case KVM_BP_HARDEN_UNKNOWN: >>>> + break; >>>> + case KVM_BP_HARDEN_NEEDED: >>>> val = SMCCC_RET_SUCCESS; >>>> + break; >>>> + case KVM_BP_HARDEN_MITIGATED: >>>> + val = SMCCC_RET_NOT_REQUIRED; >>> >>> Would KVM_BP_HARDEN_NOT_REQUIRED be a more logical name? >> I tend to agree with Steven's comment >> >> But then why not also choosing the same terminology for the uapi: >> KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_UNAFFECTED? > > You mean using ..._NOT_REQUIRED here? yes sorry. > Makes sense, as "unaffected" is different from "not required", and we > cannot guarantee the first. > >> For the same case we seem to have 3 different terminologies. But maybe I >> miss something. >> >> In the uapi doc, in case the workaround is not needed do we actually >> care to mention the wa is supported? > > I think yes, as it's important to know that a guest could call into the > "firmware", regardless of the effect. OK Thanks Eric > > Cheers, > Andre. > >> Thanks >> >> Eric >>> >>> Steve >>> >>>> + break; >>>> + } >>>> break; >>>> case ARM_SMCCC_ARCH_WORKAROUND_2: >>>> switch (kvm_arm_have_ssbd()) { >>>> >>> >