diff mbox series

KVM: PPC: Book3S: Add capabilities for Meltdown/Spectre workarounds

Message ID 20180109044815.GA19326@fergus.ozlabs.ibm.com (mailing list archive)
State Superseded
Headers show
Series KVM: PPC: Book3S: Add capabilities for Meltdown/Spectre workarounds | expand

Commit Message

Paul Mackerras Jan. 9, 2018, 4:48 a.m. UTC
This adds three new capabilities that give userspace information about
the underlying machine's level of vulnerability to the Meltdown and
Spectre attacks, and what instructions the hardware implements to
assist software to work around the vulnerabilities.

Each capability is a tri-state, where 0 indicates that the machine is
vulnerable and no workarounds are implement, 1 indicates that the
machine is vulnerable but workaround assist instructions are
available, and 2 indicates that the machine is not vulnerable.

The capabilities are:

KVM_CAP_PPC_SAFE_CACHE reports the vulnerability of the machine to
attacks based on using speculative loads to data in L1 cache which
should not be addressable.  The workaround provided by hardware is an
instruction to invalidate the entire L1 data cache.

KVM_CAP_PPC_SAFE_BOUNDS_CHECK reports the vulnerability of the machine
to attacks based on using speculative loads behind mispredicted bounds
checks.  The workaround provided by hardware is an instruction that
acts as a speculation barrier.

KVM_CAP_PPC_SAFE_INDIRECT_BRANCH reports the vulnerability of the
machine to attacks based on poisoning the indirect branch predictor.
No workaround that requires software changes is provided; the current
hardware fix is to prevent speculation past indirect branches.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
---
Note: This patch depends on the patch "powerpc/pseries: Add
H_GET_CPU_CHARACTERISTICS flags & wrapper" by Michael Ellerman,
available at http://patchwork.ozlabs.org/patch/856914/ .

 Documentation/virtual/kvm/api.txt |  36 +++++++
 arch/powerpc/kvm/powerpc.c        | 202 ++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kvm.h          |   3 +
 3 files changed, 241 insertions(+)

Comments

Suraj Jitindar Singh Jan. 9, 2018, 8:28 a.m. UTC | #1
On Tue, 2018-01-09 at 15:48 +1100, Paul Mackerras wrote:
> This adds three new capabilities that give userspace information
> about
> the underlying machine's level of vulnerability to the Meltdown and
> Spectre attacks, and what instructions the hardware implements to
> assist software to work around the vulnerabilities.
> 
> Each capability is a tri-state, where 0 indicates that the machine is
> vulnerable and no workarounds are implement, 1 indicates that the
> machine is vulnerable but workaround assist instructions are
> available, and 2 indicates that the machine is not vulnerable.
> 
> The capabilities are:
> 
> KVM_CAP_PPC_SAFE_CACHE reports the vulnerability of the machine to
> attacks based on using speculative loads to data in L1 cache which
> should not be addressable.  The workaround provided by hardware is an
> instruction to invalidate the entire L1 data cache.
> 
> KVM_CAP_PPC_SAFE_BOUNDS_CHECK reports the vulnerability of the
> machine
> to attacks based on using speculative loads behind mispredicted
> bounds
> checks.  The workaround provided by hardware is an instruction that
> acts as a speculation barrier.
> 
> KVM_CAP_PPC_SAFE_INDIRECT_BRANCH reports the vulnerability of the
> machine to attacks based on poisoning the indirect branch predictor.
> No workaround that requires software changes is provided; the current
> hardware fix is to prevent speculation past indirect branches.
> 
> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
> ---
> Note: This patch depends on the patch "powerpc/pseries: Add
> H_GET_CPU_CHARACTERISTICS flags & wrapper" by Michael Ellerman,
> available at http://patchwork.ozlabs.org/patch/856914/ .
> 
>  Documentation/virtual/kvm/api.txt |  36 +++++++
>  arch/powerpc/kvm/powerpc.c        | 202
> ++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/kvm.h          |   3 +
>  3 files changed, 241 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/api.txt
> b/Documentation/virtual/kvm/api.txt
> index 57d3ee9..8d76260 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -4369,3 +4369,39 @@ Parameters: none
>  This capability indicates if the flic device will be able to get/set
> the
>  AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and
> allows
>  to discover this without having to create a flic device.
> +
> +8.14 KVM_CAP_PPC_SAFE_CACHE
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the Meltdown attack.  Its value is a
> +tristate, where 0 indicates the machine is vulnerable, 1 indicates
> the
> +hardware is vulnerable but provides assistance to work around the
> +vulnerability (specifically by providing a fast L1 data cache flush
> +facility), and 2 indicates that the machine is not vulnerable.
> +
> +8.15 KVM_CAP_PPC_SAFE_BOUNDS_CHECK
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the bounds-check variant of the
> Spectre
> +attack.  Its value is a tristate, where 0 indicates the machine is
> +vulnerable, 1 indicates the hardware is vulnerable but provides
> +assistance to work around the vulnerability (specifically by
> providing
> +an instruction that acts as a speculation barrier), and 2 indicates
> +that the machine is not vulnerable.
> +
> +8.16 KVM_CAP_PPC_SAFE_INDIRECT_BRANCH
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the indirect branch variant of the
> Spectre
> +attack.  Its value is a tristate, where 0 indicates the machine is
> +vulnerable and 2 indicates that the machine is not vulnerable.
> +(1 would indicate the availability of a workaround that software
> +needs to implement, but there is currently no workaround that needs
> +software changes.)
> +
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 1915e86..58e863b 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -39,6 +39,10 @@
>  #include <asm/iommu.h>
>  #include <asm/switch_to.h>
>  #include <asm/xive.h>
> +#ifdef CONFIG_PPC_PSERIES
> +#include <asm/hvcall.h>
> +#include <asm/plpar_wrappers.h>
> +#endif
>  
>  #include "timing.h"
>  #include "irq.h"
> @@ -488,6 +492,193 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
>  	module_put(kvm->arch.kvm_ops->owner);
>  }
>  
> +#ifdef CONFIG_PPC_BOOK3S_64
> +/*
> + * These functions check whether the underlying hardware is safe
> + * against the Meltdown/Spectre attacks and whether it supplies
> + * instructions for use in workarounds.  The information comes from
> + * firmware, either via the device tree on powernv platforms or
> + * from an hcall on pseries platforms.
> + *
> + * For check_safe_cache() and check_safe_bounds_check(), a return
> + * value of 0 means vulnerable, 1 means vulnerable but workaround
> + * instructions are provided, and 2 means not vulnerable (no
> workaround
> + * is needed).
> + * For check_safe_indirect_branch(), 0 means vulnerable and 2 means
> + * not vulnerable.
> + */
> +static inline bool have_fw_feat(struct device_node *fw_features,
> +				const char *state, const char *name)
> +{
> +	struct device_node *np;
> +	bool r = false;
> +
> +	np = of_get_child_by_name(fw_features, name);
> +	if (np) {
> +		r = of_property_read_bool(np, state);
> +		of_node_put(np);
> +	}
> +	return r;
> +}
> +
> +#ifdef CONFIG_PPC_PSERIES
> +static bool check_pseries_safe_cache(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (!(c.behavior &
> H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))

s/H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV/H_CPU_BEHAV_L1D_FLUSH_PR

> +			r = 2;
> +		else if ((c.character &
> H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&

s/H_GET_CPU_CHAR_CHAR_L1D_PRIVATE/H_CPU_CHAR_L1D_THREAD_PRIV

> +			 ((c.character &
> H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||

s/H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH/H_CPU_CHAR_L1D_FLUSH_ORI30

> +			  (c.character &
> H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))

s/H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH/H_CPU_CHAR_L1D_FLUSH_TRIG2

etc.

> +			r = 1;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +static bool check_pseries_safe_bounds_check(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (!(c.behavior &
> H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
> +			r = 2;
> +		else if (c.character &
> H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
> +			r = 1;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +static bool check_pseries_safe_indirect_branch(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
> +			r = 2;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +#else
> +static bool check_pseries_safe_cache(int *rp)
> +{
> +	return false;
> +}
> +
> +static bool check_pseries_safe_bounds_check(int *rp)
> +{
> +	return false;
> +}
> +
> +static bool check_pseries_safe_indirect_branch(int *rp)
> +{
> +	return false;
> +}
> +#endif
> +
> +static int check_safe_cache(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_cache(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "disabled",
> +				 "needs-l1d-flush-msr-pr-0-to-1"))
> +			r = 2;
> +		else if (have_fw_feat(fw_features, "enabled",
> +				      "fw-l1d-thread-split") &&
> +			 (have_fw_feat(fw_features, "enabled",
> +				       "inst-l1d-flush-trig2") ||
> +			  have_fw_feat(fw_features, "enabled",
> +				       "inst-l1d-flush-
> ori30,30,0")))
> +			r = 1;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +
> +static int check_safe_bounds_check(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_bounds_check(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "disabled",
> +				 "needs-spec-barrier-for-bound-
> checks"))
> +			r = 2;
> +		else if (have_fw_feat(fw_features, "enabled",
> +				      "inst-spec-barrier-
> ori31,31,0"))
> +			r = 1;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +
> +static int check_safe_indirect_branch(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_indirect_branch(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "enabled",
> +				 "fw-bcctrl-serialized"))
> +			r = 2;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +#endif
> +
>  int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  {
>  	int r;
> @@ -646,6 +837,17 @@ int kvm_vm_ioctl_check_extension(struct kvm
> *kvm, long ext)
>  		r = hv_enabled &&
>  		    (cur_cpu_spec->cpu_user_features2 &
> PPC_FEATURE2_HTM_COMP);
>  		break;
> +#ifdef CONFIG_PPC_BOOK3S_64
> +	case KVM_CAP_PPC_SAFE_CACHE:
> +		r = check_safe_cache();
> +		break;
> +	case KVM_CAP_PPC_SAFE_BOUNDS_CHECK:
> +		r = check_safe_bounds_check();
> +		break;
> +	case KVM_CAP_PPC_SAFE_INDIRECT_BRANCH:
> +		r = check_safe_indirect_branch();
> +		break;
> +#endif
>  	default:
>  		r = 0;
>  		break;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 496e59a..0a480e9 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -932,6 +932,9 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_HYPERV_SYNIC2 148
>  #define KVM_CAP_HYPERV_VP_INDEX 149
>  #define KVM_CAP_S390_AIS_MIGRATION 150
> +#define KVM_CAP_PPC_SAFE_CACHE 151
> +#define KVM_CAP_PPC_SAFE_BOUNDS_CHECK 152
> +#define KVM_CAP_PPC_SAFE_INDIRECT_BRANCH 153
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>
Suraj Jitindar Singh Jan. 9, 2018, 8:39 a.m. UTC | #2
On Tue, 2018-01-09 at 15:48 +1100, Paul Mackerras wrote:
> This adds three new capabilities that give userspace information
> about
> the underlying machine's level of vulnerability to the Meltdown and
> Spectre attacks, and what instructions the hardware implements to
> assist software to work around the vulnerabilities.
> 
> Each capability is a tri-state, where 0 indicates that the machine is
> vulnerable and no workarounds are implement, 1 indicates that the
> machine is vulnerable but workaround assist instructions are
> available, and 2 indicates that the machine is not vulnerable.
> 
> The capabilities are:
> 
> KVM_CAP_PPC_SAFE_CACHE reports the vulnerability of the machine to
> attacks based on using speculative loads to data in L1 cache which
> should not be addressable.  The workaround provided by hardware is an
> instruction to invalidate the entire L1 data cache.
> 
> KVM_CAP_PPC_SAFE_BOUNDS_CHECK reports the vulnerability of the
> machine
> to attacks based on using speculative loads behind mispredicted
> bounds
> checks.  The workaround provided by hardware is an instruction that
> acts as a speculation barrier.
> 
> KVM_CAP_PPC_SAFE_INDIRECT_BRANCH reports the vulnerability of the
> machine to attacks based on poisoning the indirect branch predictor.
> No workaround that requires software changes is provided; the current
> hardware fix is to prevent speculation past indirect branches.
> 
> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
> ---
> Note: This patch depends on the patch "powerpc/pseries: Add
> H_GET_CPU_CHARACTERISTICS flags & wrapper" by Michael Ellerman,
> available at http://patchwork.ozlabs.org/patch/856914/ .
> 
>  Documentation/virtual/kvm/api.txt |  36 +++++++
>  arch/powerpc/kvm/powerpc.c        | 202
> ++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/kvm.h          |   3 +
>  3 files changed, 241 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/api.txt
> b/Documentation/virtual/kvm/api.txt
> index 57d3ee9..8d76260 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -4369,3 +4369,39 @@ Parameters: none
>  This capability indicates if the flic device will be able to get/set
> the
>  AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and
> allows
>  to discover this without having to create a flic device.
> +
> +8.14 KVM_CAP_PPC_SAFE_CACHE
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the Meltdown attack.  Its value is a
> +tristate, where 0 indicates the machine is vulnerable, 1 indicates
> the
> +hardware is vulnerable but provides assistance to work around the
> +vulnerability (specifically by providing a fast L1 data cache flush
> +facility), and 2 indicates that the machine is not vulnerable.
> +
> +8.15 KVM_CAP_PPC_SAFE_BOUNDS_CHECK
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the bounds-check variant of the
> Spectre
> +attack.  Its value is a tristate, where 0 indicates the machine is
> +vulnerable, 1 indicates the hardware is vulnerable but provides
> +assistance to work around the vulnerability (specifically by
> providing
> +an instruction that acts as a speculation barrier), and 2 indicates
> +that the machine is not vulnerable.
> +
> +8.16 KVM_CAP_PPC_SAFE_INDIRECT_BRANCH
> +
> +Architectures: ppc
> +
> +This capability gives information about the underlying machine's
> +vulnerability or otherwise to the indirect branch variant of the
> Spectre
> +attack.  Its value is a tristate, where 0 indicates the machine is
> +vulnerable and 2 indicates that the machine is not vulnerable.
> +(1 would indicate the availability of a workaround that software
> +needs to implement, but there is currently no workaround that needs
> +software changes.)
> +
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 1915e86..58e863b 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -39,6 +39,10 @@
>  #include <asm/iommu.h>
>  #include <asm/switch_to.h>
>  #include <asm/xive.h>
> +#ifdef CONFIG_PPC_PSERIES
> +#include <asm/hvcall.h>
> +#include <asm/plpar_wrappers.h>
> +#endif
>  
>  #include "timing.h"
>  #include "irq.h"
> @@ -488,6 +492,193 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
>  	module_put(kvm->arch.kvm_ops->owner);
>  }
>  
> +#ifdef CONFIG_PPC_BOOK3S_64
> +/*
> + * These functions check whether the underlying hardware is safe
> + * against the Meltdown/Spectre attacks and whether it supplies
> + * instructions for use in workarounds.  The information comes from
> + * firmware, either via the device tree on powernv platforms or
> + * from an hcall on pseries platforms.
> + *
> + * For check_safe_cache() and check_safe_bounds_check(), a return
> + * value of 0 means vulnerable, 1 means vulnerable but workaround
> + * instructions are provided, and 2 means not vulnerable (no
> workaround
> + * is needed).
> + * For check_safe_indirect_branch(), 0 means vulnerable and 2 means
> + * not vulnerable.
> + */
> +static inline bool have_fw_feat(struct device_node *fw_features,
> +				const char *state, const char *name)
> +{
> +	struct device_node *np;
> +	bool r = false;
> +
> +	np = of_get_child_by_name(fw_features, name);
> +	if (np) {
> +		r = of_property_read_bool(np, state);
> +		of_node_put(np);
> +	}
> +	return r;
> +}
> +
> +#ifdef CONFIG_PPC_PSERIES
> +static bool check_pseries_safe_cache(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (!(c.behavior & 

s/behavior/behaviour

> H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
> +			r = 2;
> +		else if ((c.character &
> H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
> +			 ((c.character &
> H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
> +			  (c.character &
> H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
> +			r = 1;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +static bool check_pseries_safe_bounds_check(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (!(c.behavior & 

s/behavior/behaviour

> H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
> +			r = 2;
> +		else if (c.character &
> H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
> +			r = 1;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +static bool check_pseries_safe_indirect_branch(int *rp)
> +{
> +	struct h_cpu_char_result c;
> +	unsigned long rc;
> +	int r = 0;
> +
> +	if (!machine_is(pseries))
> +		return false;
> +
> +	rc = plpar_get_cpu_characteristics(&c);
> +	if (rc == H_SUCCESS) {
> +		if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
> +			r = 2;
> +	}
> +	*rp = r;
> +	return true;
> +}
> +
> +#else
> +static bool check_pseries_safe_cache(int *rp)
> +{
> +	return false;
> +}
> +
> +static bool check_pseries_safe_bounds_check(int *rp)
> +{
> +	return false;
> +}
> +
> +static bool check_pseries_safe_indirect_branch(int *rp)
> +{
> +	return false;
> +}
> +#endif
> +
> +static int check_safe_cache(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_cache(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "disabled",
> +				 "needs-l1d-flush-msr-pr-0-to-1"))
> +			r = 2;
> +		else if (have_fw_feat(fw_features, "enabled",
> +				      "fw-l1d-thread-split") &&
> +			 (have_fw_feat(fw_features, "enabled",
> +				       "inst-l1d-flush-trig2") ||
> +			  have_fw_feat(fw_features, "enabled",
> +				       "inst-l1d-flush-
> ori30,30,0")))
> +			r = 1;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +
> +static int check_safe_bounds_check(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_bounds_check(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "disabled",
> +				 "needs-spec-barrier-for-bound-
> checks"))
> +			r = 2;
> +		else if (have_fw_feat(fw_features, "enabled",
> +				      "inst-spec-barrier-
> ori31,31,0"))
> +			r = 1;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +
> +static int check_safe_indirect_branch(void)
> +{
> +	struct device_node *np, *fw_features;
> +	int r = 0;
> +
> +	if (check_pseries_safe_indirect_branch(&r))
> +		return r;
> +
> +	np = of_find_node_by_name(NULL, "ibm,opal");
> +	if (np) {
> +		fw_features = of_get_child_by_name(np, "fw-
> features");
> +		of_node_put(np);
> +		if (!fw_features)
> +			return 0;
> +		if (have_fw_feat(fw_features, "enabled",
> +				 "fw-bcctrl-serialized"))
> +			r = 2;
> +		of_node_put(fw_features);
> +	}
> +
> +	return r;
> +}
> +#endif
> +
>  int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  {
>  	int r;
> @@ -646,6 +837,17 @@ int kvm_vm_ioctl_check_extension(struct kvm
> *kvm, long ext)
>  		r = hv_enabled &&
>  		    (cur_cpu_spec->cpu_user_features2 &
> PPC_FEATURE2_HTM_COMP);
>  		break;
> +#ifdef CONFIG_PPC_BOOK3S_64
> +	case KVM_CAP_PPC_SAFE_CACHE:
> +		r = check_safe_cache();
> +		break;
> +	case KVM_CAP_PPC_SAFE_BOUNDS_CHECK:
> +		r = check_safe_bounds_check();
> +		break;
> +	case KVM_CAP_PPC_SAFE_INDIRECT_BRANCH:
> +		r = check_safe_indirect_branch();
> +		break;
> +#endif
>  	default:
>  		r = 0;
>  		break;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 496e59a..0a480e9 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -932,6 +932,9 @@ struct kvm_ppc_resize_hpt {
>  #define KVM_CAP_HYPERV_SYNIC2 148
>  #define KVM_CAP_HYPERV_VP_INDEX 149
>  #define KVM_CAP_S390_AIS_MIGRATION 150
> +#define KVM_CAP_PPC_SAFE_CACHE 151
> +#define KVM_CAP_PPC_SAFE_BOUNDS_CHECK 152
> +#define KVM_CAP_PPC_SAFE_INDIRECT_BRANCH 153
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>
Paul Mackerras Jan. 9, 2018, 9:18 a.m. UTC | #3
On Tue, Jan 09, 2018 at 07:28:35PM +1100, Suraj Jitindar Singh wrote:
[snip]
> > +	rc = plpar_get_cpu_characteristics(&c);
> > +	if (rc == H_SUCCESS) {
> > +		if (!(c.behavior &
> > H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
> 
> s/H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV/H_CPU_BEHAV_L1D_FLUSH_PR

Yes, somehow I managed to post an old version of the patch.  New
version coming.

Paul.
kernel test robot Jan. 9, 2018, 11:54 a.m. UTC | #4
Hi Paul,

I love your patch! Yet something to improve:

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.15-rc7 next-20180109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paul-Mackerras/KVM-PPC-Book3S-Add-capabilities-for-Meltdown-Spectre-workarounds/20180109-165503
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: powerpc-defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_cache':
   arch/powerpc/kvm/powerpc.c:527:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c:534:7: error: implicit declaration of function 'plpar_get_cpu_characteristics' [-Werror=implicit-function-declaration]
     rc = plpar_get_cpu_characteristics(&c);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:536:22: error: 'H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV' undeclared (first use in this function)
      if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:536:22: note: each undeclared identifier is reported only once for each function it appears in
   arch/powerpc/kvm/powerpc.c:538:27: error: 'H_GET_CPU_CHAR_CHAR_L1D_PRIVATE' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV'?
      else if ((c.character & H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                              H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV
   arch/powerpc/kvm/powerpc.c:539:21: error: 'H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_CHAR_L1D_PRIVATE'?
        ((c.character & H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        H_GET_CPU_CHAR_CHAR_L1D_PRIVATE
   arch/powerpc/kvm/powerpc.c:540:21: error: 'H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH'?
         (c.character & H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH
>> arch/powerpc/kvm/powerpc.c:527:27: error: unused variable 'c' [-Werror=unused-variable]
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_bounds_check':
   arch/powerpc/kvm/powerpc.c:549:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c:558:22: error: 'H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK' undeclared (first use in this function)
      if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:560:26: error: 'H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK'?
      else if (c.character & H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                             H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK
   arch/powerpc/kvm/powerpc.c:549:27: error: unused variable 'c' [-Werror=unused-variable]
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_indirect_branch':
   arch/powerpc/kvm/powerpc.c:569:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c:578:21: error: 'H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL' undeclared (first use in this function)
      if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:569:27: error: unused variable 'c' [-Werror=unused-variable]
     struct h_cpu_char_result c;
                              ^
   cc1: all warnings being treated as errors

vim +/c +527 arch/powerpc/kvm/powerpc.c

   523	
   524	#ifdef CONFIG_PPC_PSERIES
   525	static bool check_pseries_safe_cache(int *rp)
   526	{
 > 527		struct h_cpu_char_result c;
   528		unsigned long rc;
   529		int r = 0;
   530	
   531		if (!machine_is(pseries))
   532			return false;
   533	
   534		rc = plpar_get_cpu_characteristics(&c);
   535		if (rc == H_SUCCESS) {
   536			if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
   537				r = 2;
   538			else if ((c.character & H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
 > 539				 ((c.character & H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
   540				  (c.character & H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
   541				r = 1;
   542		}
   543		*rp = r;
   544		return true;
   545	}
   546	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Michal Suchánek Jan. 9, 2018, 11:57 a.m. UTC | #5
On Tue, 09 Jan 2018 19:39:14 +1100
Suraj Jitindar Singh <sjitindarsingh@gmail.com> wrote:

> 
> s/behavior/behaviour

Nope. Either is valid and the shorter American spelling is actually
more common.

If you must nickpick choose something actually broken :p

Thanks

Michal
Jose Ricardo Ziviani Jan. 9, 2018, 12:20 p.m. UTC | #6
On Tue, Jan 09, 2018 at 12:57:26PM +0100, Michal Suchánek wrote:
> On Tue, 09 Jan 2018 19:39:14 +1100
> Suraj Jitindar Singh <sjitindarsingh@gmail.com> wrote:
> 
> > 
> > s/behavior/behaviour
> 
> Nope. Either is valid and the shorter American spelling is actually
> more common.
> 
> If you must nickpick choose something actually broken :p

Suraj is right:

struct h_cpu_char_result {
       u64 character;
       u64 behaviour;
};

> 
> Thanks
> 
> Michal
>
Alexey Kardashevskiy Jan. 9, 2018, 12:44 p.m. UTC | #7
On 09/01/18 19:39, Suraj Jitindar Singh wrote:
> On Tue, 2018-01-09 at 15:48 +1100, Paul Mackerras wrote:
>> This adds three new capabilities that give userspace information
>> about
>> the underlying machine's level of vulnerability to the Meltdown and
>> Spectre attacks, and what instructions the hardware implements to
>> assist software to work around the vulnerabilities.
>>
>> Each capability is a tri-state, where 0 indicates that the machine is
>> vulnerable and no workarounds are implement, 1 indicates that the
>> machine is vulnerable but workaround assist instructions are
>> available, and 2 indicates that the machine is not vulnerable.
>>
>> The capabilities are:
>>
>> KVM_CAP_PPC_SAFE_CACHE reports the vulnerability of the machine to
>> attacks based on using speculative loads to data in L1 cache which
>> should not be addressable.  The workaround provided by hardware is an
>> instruction to invalidate the entire L1 data cache.
>>
>> KVM_CAP_PPC_SAFE_BOUNDS_CHECK reports the vulnerability of the
>> machine
>> to attacks based on using speculative loads behind mispredicted
>> bounds
>> checks.  The workaround provided by hardware is an instruction that
>> acts as a speculation barrier.
>>
>> KVM_CAP_PPC_SAFE_INDIRECT_BRANCH reports the vulnerability of the
>> machine to attacks based on poisoning the indirect branch predictor.
>> No workaround that requires software changes is provided; the current
>> hardware fix is to prevent speculation past indirect branches.
>>
>> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
>> ---
>> Note: This patch depends on the patch "powerpc/pseries: Add
>> H_GET_CPU_CHARACTERISTICS flags & wrapper" by Michael Ellerman,
>> available at http://patchwork.ozlabs.org/patch/856914/ .
>>
>>  Documentation/virtual/kvm/api.txt |  36 +++++++
>>  arch/powerpc/kvm/powerpc.c        | 202
>> ++++++++++++++++++++++++++++++++++++++
>>  include/uapi/linux/kvm.h          |   3 +
>>  3 files changed, 241 insertions(+)
>>
>> diff --git a/Documentation/virtual/kvm/api.txt
>> b/Documentation/virtual/kvm/api.txt
>> index 57d3ee9..8d76260 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -4369,3 +4369,39 @@ Parameters: none
>>  This capability indicates if the flic device will be able to get/set
>> the
>>  AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and
>> allows
>>  to discover this without having to create a flic device.
>> +
>> +8.14 KVM_CAP_PPC_SAFE_CACHE
>> +
>> +Architectures: ppc
>> +
>> +This capability gives information about the underlying machine's
>> +vulnerability or otherwise to the Meltdown attack.  Its value is a
>> +tristate, where 0 indicates the machine is vulnerable, 1 indicates
>> the
>> +hardware is vulnerable but provides assistance to work around the
>> +vulnerability (specifically by providing a fast L1 data cache flush
>> +facility), and 2 indicates that the machine is not vulnerable.
>> +
>> +8.15 KVM_CAP_PPC_SAFE_BOUNDS_CHECK
>> +
>> +Architectures: ppc
>> +
>> +This capability gives information about the underlying machine's
>> +vulnerability or otherwise to the bounds-check variant of the
>> Spectre
>> +attack.  Its value is a tristate, where 0 indicates the machine is
>> +vulnerable, 1 indicates the hardware is vulnerable but provides
>> +assistance to work around the vulnerability (specifically by
>> providing
>> +an instruction that acts as a speculation barrier), and 2 indicates
>> +that the machine is not vulnerable.
>> +
>> +8.16 KVM_CAP_PPC_SAFE_INDIRECT_BRANCH
>> +
>> +Architectures: ppc
>> +
>> +This capability gives information about the underlying machine's
>> +vulnerability or otherwise to the indirect branch variant of the
>> Spectre
>> +attack.  Its value is a tristate, where 0 indicates the machine is
>> +vulnerable and 2 indicates that the machine is not vulnerable.
>> +(1 would indicate the availability of a workaround that software
>> +needs to implement, but there is currently no workaround that needs
>> +software changes.)
>> +
>> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
>> index 1915e86..58e863b 100644
>> --- a/arch/powerpc/kvm/powerpc.c
>> +++ b/arch/powerpc/kvm/powerpc.c
>> @@ -39,6 +39,10 @@
>>  #include <asm/iommu.h>
>>  #include <asm/switch_to.h>
>>  #include <asm/xive.h>
>> +#ifdef CONFIG_PPC_PSERIES
>> +#include <asm/hvcall.h>
>> +#include <asm/plpar_wrappers.h>
>> +#endif
>>  
>>  #include "timing.h"
>>  #include "irq.h"
>> @@ -488,6 +492,193 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
>>  	module_put(kvm->arch.kvm_ops->owner);
>>  }
>>  
>> +#ifdef CONFIG_PPC_BOOK3S_64
>> +/*
>> + * These functions check whether the underlying hardware is safe
>> + * against the Meltdown/Spectre attacks and whether it supplies
>> + * instructions for use in workarounds.  The information comes from
>> + * firmware, either via the device tree on powernv platforms or
>> + * from an hcall on pseries platforms.
>> + *
>> + * For check_safe_cache() and check_safe_bounds_check(), a return
>> + * value of 0 means vulnerable, 1 means vulnerable but workaround
>> + * instructions are provided, and 2 means not vulnerable (no
>> workaround
>> + * is needed).
>> + * For check_safe_indirect_branch(), 0 means vulnerable and 2 means
>> + * not vulnerable.
>> + */
>> +static inline bool have_fw_feat(struct device_node *fw_features,
>> +				const char *state, const char *name)
>> +{
>> +	struct device_node *np;
>> +	bool r = false;
>> +
>> +	np = of_get_child_by_name(fw_features, name);
>> +	if (np) {
>> +		r = of_property_read_bool(np, state);
>> +		of_node_put(np);
>> +	}
>> +	return r;
>> +}
>> +
>> +#ifdef CONFIG_PPC_PSERIES
>> +static bool check_pseries_safe_cache(int *rp)
>> +{
>> +	struct h_cpu_char_result c;
>> +	unsigned long rc;
>> +	int r = 0;
>> +
>> +	if (!machine_is(pseries))
>> +		return false;
>> +
>> +	rc = plpar_get_cpu_characteristics(&c);
>> +	if (rc == H_SUCCESS) {
>> +		if (!(c.behavior & 
> 
> s/behavior/behaviour

Why?
https://dictionary.cambridge.org/dictionary/english/behavior
Greg Kurz Jan. 9, 2018, 12:54 p.m. UTC | #8
On Tue, 9 Jan 2018 23:44:56 +1100
Alexey Kardashevskiy <aik@ozlabs.ru> wrote:

> On 09/01/18 19:39, Suraj Jitindar Singh wrote:
[...]
> >> +	rc = plpar_get_cpu_characteristics(&c);
> >> +	if (rc == H_SUCCESS) {
> >> +		if (!(c.behavior &   
> > 
> > s/behavior/behaviour  
> 
> Why?
> https://dictionary.cambridge.org/dictionary/english/behavior
> 

Behavior is US English while behaviour is UK (and US)... Matter of taste ? :)

> 
>
kernel test robot Jan. 9, 2018, 1:48 p.m. UTC | #9
Hi Paul,

I love your patch! Yet something to improve:

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.15-rc7 next-20180109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paul-Mackerras/KVM-PPC-Book3S-Add-capabilities-for-Meltdown-Spectre-workarounds/20180109-165503
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_cache':
>> arch/powerpc/kvm/powerpc.c:527:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
>> arch/powerpc/kvm/powerpc.c:534:7: error: implicit declaration of function 'plpar_get_cpu_characteristics' [-Werror=implicit-function-declaration]
     rc = plpar_get_cpu_characteristics(&c);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/powerpc/kvm/powerpc.c:536:22: error: 'H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV' undeclared (first use in this function)
      if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:536:22: note: each undeclared identifier is reported only once for each function it appears in
>> arch/powerpc/kvm/powerpc.c:538:27: error: 'H_GET_CPU_CHAR_CHAR_L1D_PRIVATE' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV'?
      else if ((c.character & H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                              H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV
>> arch/powerpc/kvm/powerpc.c:539:21: error: 'H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_CHAR_L1D_PRIVATE'?
        ((c.character & H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        H_GET_CPU_CHAR_CHAR_L1D_PRIVATE
>> arch/powerpc/kvm/powerpc.c:540:21: error: 'H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH'?
         (c.character & H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH
   arch/powerpc/kvm/powerpc.c:527:27: warning: unused variable 'c' [-Wunused-variable]
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_bounds_check':
   arch/powerpc/kvm/powerpc.c:549:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
>> arch/powerpc/kvm/powerpc.c:558:22: error: 'H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK' undeclared (first use in this function)
      if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/powerpc/kvm/powerpc.c:560:26: error: 'H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR' undeclared (first use in this function); did you mean 'H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK'?
      else if (c.character & H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                             H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK
   arch/powerpc/kvm/powerpc.c:549:27: warning: unused variable 'c' [-Wunused-variable]
     struct h_cpu_char_result c;
                              ^
   arch/powerpc/kvm/powerpc.c: In function 'check_pseries_safe_indirect_branch':
   arch/powerpc/kvm/powerpc.c:569:27: error: storage size of 'c' isn't known
     struct h_cpu_char_result c;
                              ^
>> arch/powerpc/kvm/powerpc.c:578:21: error: 'H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL' undeclared (first use in this function)
      if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/powerpc/kvm/powerpc.c:569:27: warning: unused variable 'c' [-Wunused-variable]
     struct h_cpu_char_result c;
                              ^
   cc1: some warnings being treated as errors

vim +527 arch/powerpc/kvm/powerpc.c

   523	
   524	#ifdef CONFIG_PPC_PSERIES
   525	static bool check_pseries_safe_cache(int *rp)
   526	{
 > 527		struct h_cpu_char_result c;
   528		unsigned long rc;
   529		int r = 0;
   530	
   531		if (!machine_is(pseries))
   532			return false;
   533	
 > 534		rc = plpar_get_cpu_characteristics(&c);
   535		if (rc == H_SUCCESS) {
 > 536			if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
   537				r = 2;
 > 538			else if ((c.character & H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
 > 539				 ((c.character & H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
 > 540				  (c.character & H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
   541				r = 1;
   542		}
   543		*rp = r;
   544		return true;
   545	}
   546	
   547	static bool check_pseries_safe_bounds_check(int *rp)
   548	{
 > 549		struct h_cpu_char_result c;
   550		unsigned long rc;
   551		int r = 0;
   552	
   553		if (!machine_is(pseries))
   554			return false;
   555	
   556		rc = plpar_get_cpu_characteristics(&c);
   557		if (rc == H_SUCCESS) {
 > 558			if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
   559				r = 2;
 > 560			else if (c.character & H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
   561				r = 1;
   562		}
   563		*rp = r;
   564		return true;
   565	}
   566	
   567	static bool check_pseries_safe_indirect_branch(int *rp)
   568	{
   569		struct h_cpu_char_result c;
   570		unsigned long rc;
   571		int r = 0;
   572	
   573		if (!machine_is(pseries))
   574			return false;
   575	
   576		rc = plpar_get_cpu_characteristics(&c);
   577		if (rc == H_SUCCESS) {
 > 578			if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
   579				r = 2;
   580		}
   581		*rp = r;
   582		return true;
   583	}
   584	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Michael Ellerman Jan. 9, 2018, 2:36 p.m. UTC | #10
Greg Kurz <groug@kaod.org> writes:

> On Tue, 9 Jan 2018 23:44:56 +1100
> Alexey Kardashevskiy <aik@ozlabs.ru> wrote:
>
>> On 09/01/18 19:39, Suraj Jitindar Singh wrote:
> [...]
>> >> +	rc = plpar_get_cpu_characteristics(&c);
>> >> +	if (rc == H_SUCCESS) {
>> >> +		if (!(c.behavior &   
>> > 
>> > s/behavior/behaviour  
>> 
>> Why?
>> https://dictionary.cambridge.org/dictionary/english/behavior
>> 
>
> Behavior is US English while behaviour is UK (and US)... Matter of taste ? :)

Straya mate!

cheers
Suraj Jitindar Singh Jan. 10, 2018, 12:59 a.m. UTC | #11
On Tue, 2018-01-09 at 23:44 +1100, Alexey Kardashevskiy wrote:
> On 09/01/18 19:39, Suraj Jitindar Singh wrote:
> > On Tue, 2018-01-09 at 15:48 +1100, Paul Mackerras wrote:
> > > This adds three new capabilities that give userspace information
> > > about
> > > the underlying machine's level of vulnerability to the Meltdown
> > > and
> > > Spectre attacks, and what instructions the hardware implements to
> > > assist software to work around the vulnerabilities.
> > > 
> > > Each capability is a tri-state, where 0 indicates that the
> > > machine is
> > > vulnerable and no workarounds are implement, 1 indicates that the
> > > machine is vulnerable but workaround assist instructions are
> > > available, and 2 indicates that the machine is not vulnerable.
> > > 
> > > The capabilities are:
> > > 
> > > KVM_CAP_PPC_SAFE_CACHE reports the vulnerability of the machine
> > > to
> > > attacks based on using speculative loads to data in L1 cache
> > > which
> > > should not be addressable.  The workaround provided by hardware
> > > is an
> > > instruction to invalidate the entire L1 data cache.
> > > 
> > > KVM_CAP_PPC_SAFE_BOUNDS_CHECK reports the vulnerability of the
> > > machine
> > > to attacks based on using speculative loads behind mispredicted
> > > bounds
> > > checks.  The workaround provided by hardware is an instruction
> > > that
> > > acts as a speculation barrier.
> > > 
> > > KVM_CAP_PPC_SAFE_INDIRECT_BRANCH reports the vulnerability of the
> > > machine to attacks based on poisoning the indirect branch
> > > predictor.
> > > No workaround that requires software changes is provided; the
> > > current
> > > hardware fix is to prevent speculation past indirect branches.
> > > 
> > > Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
> > > ---
> > > Note: This patch depends on the patch "powerpc/pseries: Add
> > > H_GET_CPU_CHARACTERISTICS flags & wrapper" by Michael Ellerman,
> > > available at http://patchwork.ozlabs.org/patch/856914/ .
> > > 
> > >  Documentation/virtual/kvm/api.txt |  36 +++++++
> > >  arch/powerpc/kvm/powerpc.c        | 202
> > > ++++++++++++++++++++++++++++++++++++++
> > >  include/uapi/linux/kvm.h          |   3 +
> > >  3 files changed, 241 insertions(+)
> > > 
> > > diff --git a/Documentation/virtual/kvm/api.txt
> > > b/Documentation/virtual/kvm/api.txt
> > > index 57d3ee9..8d76260 100644
> > > --- a/Documentation/virtual/kvm/api.txt
> > > +++ b/Documentation/virtual/kvm/api.txt
> > > @@ -4369,3 +4369,39 @@ Parameters: none
> > >  This capability indicates if the flic device will be able to
> > > get/set
> > > the
> > >  AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute
> > > and
> > > allows
> > >  to discover this without having to create a flic device.
> > > +
> > > +8.14 KVM_CAP_PPC_SAFE_CACHE
> > > +
> > > +Architectures: ppc
> > > +
> > > +This capability gives information about the underlying machine's
> > > +vulnerability or otherwise to the Meltdown attack.  Its value is
> > > a
> > > +tristate, where 0 indicates the machine is vulnerable, 1
> > > indicates
> > > the
> > > +hardware is vulnerable but provides assistance to work around
> > > the
> > > +vulnerability (specifically by providing a fast L1 data cache
> > > flush
> > > +facility), and 2 indicates that the machine is not vulnerable.
> > > +
> > > +8.15 KVM_CAP_PPC_SAFE_BOUNDS_CHECK
> > > +
> > > +Architectures: ppc
> > > +
> > > +This capability gives information about the underlying machine's
> > > +vulnerability or otherwise to the bounds-check variant of the
> > > Spectre
> > > +attack.  Its value is a tristate, where 0 indicates the machine
> > > is
> > > +vulnerable, 1 indicates the hardware is vulnerable but provides
> > > +assistance to work around the vulnerability (specifically by
> > > providing
> > > +an instruction that acts as a speculation barrier), and 2
> > > indicates
> > > +that the machine is not vulnerable.
> > > +
> > > +8.16 KVM_CAP_PPC_SAFE_INDIRECT_BRANCH
> > > +
> > > +Architectures: ppc
> > > +
> > > +This capability gives information about the underlying machine's
> > > +vulnerability or otherwise to the indirect branch variant of the
> > > Spectre
> > > +attack.  Its value is a tristate, where 0 indicates the machine
> > > is
> > > +vulnerable and 2 indicates that the machine is not vulnerable.
> > > +(1 would indicate the availability of a workaround that software
> > > +needs to implement, but there is currently no workaround that
> > > needs
> > > +software changes.)
> > > +
> > > diff --git a/arch/powerpc/kvm/powerpc.c
> > > b/arch/powerpc/kvm/powerpc.c
> > > index 1915e86..58e863b 100644
> > > --- a/arch/powerpc/kvm/powerpc.c
> > > +++ b/arch/powerpc/kvm/powerpc.c
> > > @@ -39,6 +39,10 @@
> > >  #include <asm/iommu.h>
> > >  #include <asm/switch_to.h>
> > >  #include <asm/xive.h>
> > > +#ifdef CONFIG_PPC_PSERIES
> > > +#include <asm/hvcall.h>
> > > +#include <asm/plpar_wrappers.h>
> > > +#endif
> > >  
> > >  #include "timing.h"
> > >  #include "irq.h"
> > > @@ -488,6 +492,193 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
> > >  	module_put(kvm->arch.kvm_ops->owner);
> > >  }
> > >  
> > > +#ifdef CONFIG_PPC_BOOK3S_64
> > > +/*
> > > + * These functions check whether the underlying hardware is safe
> > > + * against the Meltdown/Spectre attacks and whether it supplies
> > > + * instructions for use in workarounds.  The information comes
> > > from
> > > + * firmware, either via the device tree on powernv platforms or
> > > + * from an hcall on pseries platforms.
> > > + *
> > > + * For check_safe_cache() and check_safe_bounds_check(), a
> > > return
> > > + * value of 0 means vulnerable, 1 means vulnerable but
> > > workaround
> > > + * instructions are provided, and 2 means not vulnerable (no
> > > workaround
> > > + * is needed).
> > > + * For check_safe_indirect_branch(), 0 means vulnerable and 2
> > > means
> > > + * not vulnerable.
> > > + */
> > > +static inline bool have_fw_feat(struct device_node *fw_features,
> > > +				const char *state, const char
> > > *name)
> > > +{
> > > +	struct device_node *np;
> > > +	bool r = false;
> > > +
> > > +	np = of_get_child_by_name(fw_features, name);
> > > +	if (np) {
> > > +		r = of_property_read_bool(np, state);
> > > +		of_node_put(np);
> > > +	}
> > > +	return r;
> > > +}
> > > +
> > > +#ifdef CONFIG_PPC_PSERIES
> > > +static bool check_pseries_safe_cache(int *rp)
> > > +{
> > > +	struct h_cpu_char_result c;
> > > +	unsigned long rc;
> > > +	int r = 0;
> > > +
> > > +	if (!machine_is(pseries))
> > > +		return false;
> > > +
> > > +	rc = plpar_get_cpu_characteristics(&c);
> > > +	if (rc == H_SUCCESS) {
> > > +		if (!(c.behavior & 
> > 
> > s/behavior/behaviour
> 

Mainly because that's what it's called in the struct and so needs to be
that if you want it to compile :)

Also, straya

> Why?
> https://dictionary.cambridge.org/dictionary/english/behavior
> 
> 
>
diff mbox series

Patch

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 57d3ee9..8d76260 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -4369,3 +4369,39 @@  Parameters: none
 This capability indicates if the flic device will be able to get/set the
 AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows
 to discover this without having to create a flic device.
+
+8.14 KVM_CAP_PPC_SAFE_CACHE
+
+Architectures: ppc
+
+This capability gives information about the underlying machine's
+vulnerability or otherwise to the Meltdown attack.  Its value is a
+tristate, where 0 indicates the machine is vulnerable, 1 indicates the
+hardware is vulnerable but provides assistance to work around the
+vulnerability (specifically by providing a fast L1 data cache flush
+facility), and 2 indicates that the machine is not vulnerable.
+
+8.15 KVM_CAP_PPC_SAFE_BOUNDS_CHECK
+
+Architectures: ppc
+
+This capability gives information about the underlying machine's
+vulnerability or otherwise to the bounds-check variant of the Spectre
+attack.  Its value is a tristate, where 0 indicates the machine is
+vulnerable, 1 indicates the hardware is vulnerable but provides
+assistance to work around the vulnerability (specifically by providing
+an instruction that acts as a speculation barrier), and 2 indicates
+that the machine is not vulnerable.
+
+8.16 KVM_CAP_PPC_SAFE_INDIRECT_BRANCH
+
+Architectures: ppc
+
+This capability gives information about the underlying machine's
+vulnerability or otherwise to the indirect branch variant of the Spectre
+attack.  Its value is a tristate, where 0 indicates the machine is
+vulnerable and 2 indicates that the machine is not vulnerable.
+(1 would indicate the availability of a workaround that software
+needs to implement, but there is currently no workaround that needs
+software changes.)
+
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 1915e86..58e863b 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -39,6 +39,10 @@ 
 #include <asm/iommu.h>
 #include <asm/switch_to.h>
 #include <asm/xive.h>
+#ifdef CONFIG_PPC_PSERIES
+#include <asm/hvcall.h>
+#include <asm/plpar_wrappers.h>
+#endif
 
 #include "timing.h"
 #include "irq.h"
@@ -488,6 +492,193 @@  void kvm_arch_destroy_vm(struct kvm *kvm)
 	module_put(kvm->arch.kvm_ops->owner);
 }
 
+#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * These functions check whether the underlying hardware is safe
+ * against the Meltdown/Spectre attacks and whether it supplies
+ * instructions for use in workarounds.  The information comes from
+ * firmware, either via the device tree on powernv platforms or
+ * from an hcall on pseries platforms.
+ *
+ * For check_safe_cache() and check_safe_bounds_check(), a return
+ * value of 0 means vulnerable, 1 means vulnerable but workaround
+ * instructions are provided, and 2 means not vulnerable (no workaround
+ * is needed).
+ * For check_safe_indirect_branch(), 0 means vulnerable and 2 means
+ * not vulnerable.
+ */
+static inline bool have_fw_feat(struct device_node *fw_features,
+				const char *state, const char *name)
+{
+	struct device_node *np;
+	bool r = false;
+
+	np = of_get_child_by_name(fw_features, name);
+	if (np) {
+		r = of_property_read_bool(np, state);
+		of_node_put(np);
+	}
+	return r;
+}
+
+#ifdef CONFIG_PPC_PSERIES
+static bool check_pseries_safe_cache(int *rp)
+{
+	struct h_cpu_char_result c;
+	unsigned long rc;
+	int r = 0;
+
+	if (!machine_is(pseries))
+		return false;
+
+	rc = plpar_get_cpu_characteristics(&c);
+	if (rc == H_SUCCESS) {
+		if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_L1_FLUSH_LOW_PRIV))
+			r = 2;
+		else if ((c.character & H_GET_CPU_CHAR_CHAR_L1D_PRIVATE) &&
+			 ((c.character & H_GET_CPU_CHAR_CHAR_ORI30_L1_FLUSH) ||
+			  (c.character & H_GET_CPU_CHAR_CHAR_MTTRIG2_L1_FLUSH)))
+			r = 1;
+	}
+	*rp = r;
+	return true;
+}
+
+static bool check_pseries_safe_bounds_check(int *rp)
+{
+	struct h_cpu_char_result c;
+	unsigned long rc;
+	int r = 0;
+
+	if (!machine_is(pseries))
+		return false;
+
+	rc = plpar_get_cpu_characteristics(&c);
+	if (rc == H_SUCCESS) {
+		if (!(c.behavior & H_GET_CPU_CHAR_BEHAV_SPEC_BAR_BNDS_CHK))
+			r = 2;
+		else if (c.character & H_GET_CPU_CHAR_CHAR_ORI31_SPEC_BAR)
+			r = 1;
+	}
+	*rp = r;
+	return true;
+}
+
+static bool check_pseries_safe_indirect_branch(int *rp)
+{
+	struct h_cpu_char_result c;
+	unsigned long rc;
+	int r = 0;
+
+	if (!machine_is(pseries))
+		return false;
+
+	rc = plpar_get_cpu_characteristics(&c);
+	if (rc == H_SUCCESS) {
+		if (c.character & H_GET_CPU_CHAR_CHAR_BCCTR_SERIAL)
+			r = 2;
+	}
+	*rp = r;
+	return true;
+}
+
+#else
+static bool check_pseries_safe_cache(int *rp)
+{
+	return false;
+}
+
+static bool check_pseries_safe_bounds_check(int *rp)
+{
+	return false;
+}
+
+static bool check_pseries_safe_indirect_branch(int *rp)
+{
+	return false;
+}
+#endif
+
+static int check_safe_cache(void)
+{
+	struct device_node *np, *fw_features;
+	int r = 0;
+
+	if (check_pseries_safe_cache(&r))
+		return r;
+
+	np = of_find_node_by_name(NULL, "ibm,opal");
+	if (np) {
+		fw_features = of_get_child_by_name(np, "fw-features");
+		of_node_put(np);
+		if (!fw_features)
+			return 0;
+		if (have_fw_feat(fw_features, "disabled",
+				 "needs-l1d-flush-msr-pr-0-to-1"))
+			r = 2;
+		else if (have_fw_feat(fw_features, "enabled",
+				      "fw-l1d-thread-split") &&
+			 (have_fw_feat(fw_features, "enabled",
+				       "inst-l1d-flush-trig2") ||
+			  have_fw_feat(fw_features, "enabled",
+				       "inst-l1d-flush-ori30,30,0")))
+			r = 1;
+		of_node_put(fw_features);
+	}
+
+	return r;
+}
+
+static int check_safe_bounds_check(void)
+{
+	struct device_node *np, *fw_features;
+	int r = 0;
+
+	if (check_pseries_safe_bounds_check(&r))
+		return r;
+
+	np = of_find_node_by_name(NULL, "ibm,opal");
+	if (np) {
+		fw_features = of_get_child_by_name(np, "fw-features");
+		of_node_put(np);
+		if (!fw_features)
+			return 0;
+		if (have_fw_feat(fw_features, "disabled",
+				 "needs-spec-barrier-for-bound-checks"))
+			r = 2;
+		else if (have_fw_feat(fw_features, "enabled",
+				      "inst-spec-barrier-ori31,31,0"))
+			r = 1;
+		of_node_put(fw_features);
+	}
+
+	return r;
+}
+
+static int check_safe_indirect_branch(void)
+{
+	struct device_node *np, *fw_features;
+	int r = 0;
+
+	if (check_pseries_safe_indirect_branch(&r))
+		return r;
+
+	np = of_find_node_by_name(NULL, "ibm,opal");
+	if (np) {
+		fw_features = of_get_child_by_name(np, "fw-features");
+		of_node_put(np);
+		if (!fw_features)
+			return 0;
+		if (have_fw_feat(fw_features, "enabled",
+				 "fw-bcctrl-serialized"))
+			r = 2;
+		of_node_put(fw_features);
+	}
+
+	return r;
+}
+#endif
+
 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 {
 	int r;
@@ -646,6 +837,17 @@  int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 		r = hv_enabled &&
 		    (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM_COMP);
 		break;
+#ifdef CONFIG_PPC_BOOK3S_64
+	case KVM_CAP_PPC_SAFE_CACHE:
+		r = check_safe_cache();
+		break;
+	case KVM_CAP_PPC_SAFE_BOUNDS_CHECK:
+		r = check_safe_bounds_check();
+		break;
+	case KVM_CAP_PPC_SAFE_INDIRECT_BRANCH:
+		r = check_safe_indirect_branch();
+		break;
+#endif
 	default:
 		r = 0;
 		break;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 496e59a..0a480e9 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -932,6 +932,9 @@  struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_SYNIC2 148
 #define KVM_CAP_HYPERV_VP_INDEX 149
 #define KVM_CAP_S390_AIS_MIGRATION 150
+#define KVM_CAP_PPC_SAFE_CACHE 151
+#define KVM_CAP_PPC_SAFE_BOUNDS_CHECK 152
+#define KVM_CAP_PPC_SAFE_INDIRECT_BRANCH 153
 
 #ifdef KVM_CAP_IRQ_ROUTING