Re: [PATCH 14/14] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Marc Zyngier
On 28/01/18 23:08, Ard Biesheuvel wrote:
> On 26 January 2018 at 14:28, Marc Zyngier  wrote:
>> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
>> It is lovely. Really.
>>
>> Signed-off-by: Marc Zyngier 
>> ---
>>  arch/arm64/kernel/bpi.S| 20 
>>  arch/arm64/kernel/cpu_errata.c | 71 
>> +-
>>  2 files changed, 90 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
>> index 76225c2611ea..add7e08a018d 100644
>> --- a/arch/arm64/kernel/bpi.S
>> +++ b/arch/arm64/kernel/bpi.S
>> @@ -17,6 +17,7 @@
>>   */
>>
>>  #include 
>> +#include 
>>
>>  .macro ventry target
>> .rept 31
>> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
>> .endr
>> ldp x29, x30, [sp], #16
>>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
>> +
>> +.macro smccc_workaround_1 inst
>> +   sub sp, sp, #(8 * 4)
>> +   stp x2, x3, [sp, #(16 * 0)]
>> +   stp x0, x1, [sp, #(16 * 1)]
>> +   orr w0, wzr, #ARM_SMCCC_ARCH_WORKAROUND_1
>> +   \inst   #0
>> +   ldp x2, x3, [sp, #(16 * 0)]
>> +   ldp x0, x1, [sp, #(16 * 1)]
>> +   add sp, sp, #(8 * 4)
>> +.endm
>> +
>> +ENTRY(__smccc_workaround_1_smc_start)
>> +   smccc_workaround_1  smc
>> +ENTRY(__smccc_workaround_1_smc_end)
>> +
>> +ENTRY(__smccc_workaround_1_hvc_start)
>> +   smccc_workaround_1  hvc
>> +ENTRY(__smccc_workaround_1_hvc_end)
>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
>> index ed6881882231..f1501873f2e4 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
>> bp_hardening_data);
>>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>>  extern char __qcom_hyp_sanitize_link_stack_start[];
>>  extern char __qcom_hyp_sanitize_link_stack_end[];
>> +extern char __smccc_workaround_1_smc_start[];
>> +extern char __smccc_workaround_1_smc_end[];
>> +extern char __smccc_workaround_1_hvc_start[];
>> +extern char __smccc_workaround_1_hvc_end[];
>>
>>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
>> const char *hyp_vecs_end)
>> @@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t 
>> fn,
>>  #define __psci_hyp_bp_inval_endNULL
>>  #define __qcom_hyp_sanitize_link_stack_start   NULL
>>  #define __qcom_hyp_sanitize_link_stack_end NULL
>> +#define __smccc_workaround_1_smc_start NULL
>> +#define __smccc_workaround_1_smc_end   NULL
>> +#define __smccc_workaround_1_hvc_start NULL
>> +#define __smccc_workaround_1_hvc_end   NULL
>>
>>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>>   const char *hyp_vecs_start,
>> @@ -142,17 +150,78 @@ static void  install_bp_hardening_cb(const struct 
>> arm64_cpu_capabilities *entry,
>> __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>>  }
>>
>> +#include 
>> +#include 
>>  #include 
>>
>> +static void call_smc_arch_workaround_1(void)
>> +{
>> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
>> +   asm volatile("smc   #0\n"
>> +: "+r" (w0));
>> +}
>> +
>> +static void call_hvc_arch_workaround_1(void)
>> +{
>> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
>> +   asm volatile("hvc   #0\n"
>> +: "+r" (w0));
>> +}
>> +
>> +static bool check_smccc_arch_workaround_1(const struct 
>> arm64_cpu_capabilities *entry)
>> +{
>> +   bp_hardening_cb_t cb;
>> +   void *smccc_start, *smccc_end;
>> +   struct arm_smccc_res res;
>> +
>> +   if (psci_ops.variant == SMCCC_VARIANT_1_0)
>> +   return false;
>> +
>> +   switch (psci_ops.conduit) {
>> +   case PSCI_CONDUIT_HVC:
>> +   arm_smccc_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
>> + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 0,
>> + &res);
>> +   if (res.a0)
>> +   return false;
>> +   cb = call_hvc_arch_workaround_1;
>> +   smccc_start = __smccc_workaround_1_hvc_start;
>> +   smccc_end = __smccc_workaround_1_hvc_end;
>> +   break;
>> +
>> +   case PSCI_CONDUIT_SMC:
>> +   arm_smccc_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
>> + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 0,
>> + &res);
> 
> This compiles to
> 
>  4a8:   928fffe1mov x1, #0x8000 // #-32768
>  4ac:   b26187e0mov x0, #0x8001 // 
> #-2147483647
>  4b0:   d287mov x7, #0x0// #0
>  4b4:   d286mov x6, #0x0  

Re: [PATCH 14/14] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Ard Biesheuvel
On 29 January 2018 at 09:36, Marc Zyngier  wrote:
> On 28/01/18 23:08, Ard Biesheuvel wrote:
>> On 26 January 2018 at 14:28, Marc Zyngier  wrote:
>>> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
>>> It is lovely. Really.
>>>
>>> Signed-off-by: Marc Zyngier 
>>> ---
>>>  arch/arm64/kernel/bpi.S| 20 
>>>  arch/arm64/kernel/cpu_errata.c | 71 
>>> +-
>>>  2 files changed, 90 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
>>> index 76225c2611ea..add7e08a018d 100644
>>> --- a/arch/arm64/kernel/bpi.S
>>> +++ b/arch/arm64/kernel/bpi.S
>>> @@ -17,6 +17,7 @@
>>>   */
>>>
>>>  #include 
>>> +#include 
>>>
>>>  .macro ventry target
>>> .rept 31
>>> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
>>> .endr
>>> ldp x29, x30, [sp], #16
>>>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
>>> +
>>> +.macro smccc_workaround_1 inst
>>> +   sub sp, sp, #(8 * 4)
>>> +   stp x2, x3, [sp, #(16 * 0)]
>>> +   stp x0, x1, [sp, #(16 * 1)]
>>> +   orr w0, wzr, #ARM_SMCCC_ARCH_WORKAROUND_1
>>> +   \inst   #0
>>> +   ldp x2, x3, [sp, #(16 * 0)]
>>> +   ldp x0, x1, [sp, #(16 * 1)]
>>> +   add sp, sp, #(8 * 4)
>>> +.endm
>>> +
>>> +ENTRY(__smccc_workaround_1_smc_start)
>>> +   smccc_workaround_1  smc
>>> +ENTRY(__smccc_workaround_1_smc_end)
>>> +
>>> +ENTRY(__smccc_workaround_1_hvc_start)
>>> +   smccc_workaround_1  hvc
>>> +ENTRY(__smccc_workaround_1_hvc_end)
>>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
>>> index ed6881882231..f1501873f2e4 100644
>>> --- a/arch/arm64/kernel/cpu_errata.c
>>> +++ b/arch/arm64/kernel/cpu_errata.c
>>> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
>>> bp_hardening_data);
>>>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>>>  extern char __qcom_hyp_sanitize_link_stack_start[];
>>>  extern char __qcom_hyp_sanitize_link_stack_end[];
>>> +extern char __smccc_workaround_1_smc_start[];
>>> +extern char __smccc_workaround_1_smc_end[];
>>> +extern char __smccc_workaround_1_hvc_start[];
>>> +extern char __smccc_workaround_1_hvc_end[];
>>>
>>>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
>>> const char *hyp_vecs_end)
>>> @@ -116,6 +120,10 @@ static void 
>>> __install_bp_hardening_cb(bp_hardening_cb_t fn,
>>>  #define __psci_hyp_bp_inval_endNULL
>>>  #define __qcom_hyp_sanitize_link_stack_start   NULL
>>>  #define __qcom_hyp_sanitize_link_stack_end NULL
>>> +#define __smccc_workaround_1_smc_start NULL
>>> +#define __smccc_workaround_1_smc_end   NULL
>>> +#define __smccc_workaround_1_hvc_start NULL
>>> +#define __smccc_workaround_1_hvc_end   NULL
>>>
>>>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>>>   const char *hyp_vecs_start,
>>> @@ -142,17 +150,78 @@ static void  install_bp_hardening_cb(const struct 
>>> arm64_cpu_capabilities *entry,
>>> __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>>>  }
>>>
>>> +#include 
>>> +#include 
>>>  #include 
>>>
>>> +static void call_smc_arch_workaround_1(void)
>>> +{
>>> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
>>> +   asm volatile("smc   #0\n"
>>> +: "+r" (w0));
>>> +}
>>> +
>>> +static void call_hvc_arch_workaround_1(void)
>>> +{
>>> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
>>> +   asm volatile("hvc   #0\n"
>>> +: "+r" (w0));
>>> +}
>>> +
>>> +static bool check_smccc_arch_workaround_1(const struct 
>>> arm64_cpu_capabilities *entry)
>>> +{
>>> +   bp_hardening_cb_t cb;
>>> +   void *smccc_start, *smccc_end;
>>> +   struct arm_smccc_res res;
>>> +
>>> +   if (psci_ops.variant == SMCCC_VARIANT_1_0)
>>> +   return false;
>>> +
>>> +   switch (psci_ops.conduit) {
>>> +   case PSCI_CONDUIT_HVC:
>>> +   arm_smccc_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
>>> + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 0,
>>> + &res);
>>> +   if (res.a0)
>>> +   return false;
>>> +   cb = call_hvc_arch_workaround_1;
>>> +   smccc_start = __smccc_workaround_1_hvc_start;
>>> +   smccc_end = __smccc_workaround_1_hvc_end;
>>> +   break;
>>> +
>>> +   case PSCI_CONDUIT_SMC:
>>> +   arm_smccc_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
>>> + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 0,
>>> + &res);
>>
>> This compiles to
>>
>>  4a8:   928fffe1mov x1, #0x8000 // #-32768
>>  4ac:   b26187e0mov x0, #0xff

Re: [PATCH 13/14] firmware/psci: Expose SMCCC version through psci_ops

2018-01-29 Thread Ard Biesheuvel
On 26 January 2018 at 14:28, Marc Zyngier  wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
>
> Signed-off-by: Marc Zyngier 
> ---
>  drivers/firmware/psci.c | 22 ++
>  include/linux/psci.h|  6 ++
>  2 files changed, 28 insertions(+)
>
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 570187e5d084..b260bbf637a2 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -509,6 +509,27 @@ static void __init psci_init_migrate(void)
> pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>  }
>
> +static void __init psci_init_smccc(u32 ver)
> +{
> +   int feature = PSCI_RET_NOT_SUPPORTED;
> +
> +   if (PSCI_VERSION_MAJOR(ver) > 1 ||
> +   (PSCI_VERSION_MAJOR(ver) == 1 && PSCI_VERSION_MINOR(ver) >= 0))

'PSCI_VERSION_MAJOR(ver) >= 1' should be sufficient here, no?

> +   feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> +   if (feature == PSCI_RET_NOT_SUPPORTED) {
> +   psci_ops.variant = SMCCC_VARIANT_1_0;
> +   } else {
> +   ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> +   if (ver != ARM_SMCCC_VERSION_1_1)
> +   psci_ops.variant = SMCCC_VARIANT_1_0;
> +   else
> +   psci_ops.variant = SMCCC_VARIANT_1_1;
> +   }
> +
> +   pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>  static void __init psci_0_2_set_functions(void)
>  {
> pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -555,6 +576,7 @@ static int __init psci_probe(void)
> psci_0_2_set_functions();
>
> psci_init_migrate();
> +   psci_init_smccc(ver);
>
> if (PSCI_VERSION_MAJOR(ver) >= 1) {
> psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
> PSCI_CONDUIT_HVC,
>  };
>
> +enum smccc_variant {
> +   SMCCC_VARIANT_1_0,
> +   SMCCC_VARIANT_1_1,
> +};
> +
>  struct psci_operations {
> u32 (*get_version)(void);
> int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
> unsigned long lowest_affinity_level);
> int (*migrate_info_type)(void);
> enum psci_conduit conduit;
> +   enum smccc_variant variant;
>  };
>
>  extern struct psci_operations psci_ops;
> --
> 2.14.2
>
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 12/14] firmware/psci: Expose PSCI conduit

2018-01-29 Thread Ard Biesheuvel
On 26 January 2018 at 14:28, Marc Zyngier  wrote:
> In order to call into the firmware to apply workarounds, it is
> useful to find out whether we're using HVC or SMC. Let's expose
> this through the psci_ops.
>
> Signed-off-by: Marc Zyngier 
> ---
>  drivers/firmware/psci.c | 26 +-
>  include/linux/psci.h|  7 +++
>  2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 8b25d31e8401..570187e5d084 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
> return cpu == resident_cpu;
>  }
>
> -struct psci_operations psci_ops;
> +struct psci_operations psci_ops = {
> +   .conduit = PSCI_CONDUIT_NONE,
> +};
>
>  typedef unsigned long (psci_fn)(unsigned long, unsigned long,
> unsigned long, unsigned long);
> @@ -210,6 +212,20 @@ static unsigned long psci_migrate_info_up_cpu(void)
>   0, 0, 0);
>  }
>
> +static void set_conduit(enum psci_conduit conduit)
> +{
> +   switch (conduit) {
> +   case PSCI_CONDUIT_HVC:
> +   invoke_psci_fn = __invoke_psci_fn_hvc;
> +   break;
> +   case PSCI_CONDUIT_SMC:
> +   invoke_psci_fn = __invoke_psci_fn_smc;
> +   break;

I get a GCC warning here about PSCI_CONDUIT_NONE not being handled.

> +   }
> +
> +   psci_ops.conduit = conduit;
> +}
> +
>  static int get_set_conduit_method(struct device_node *np)
>  {
> const char *method;
> @@ -222,9 +238,9 @@ static int get_set_conduit_method(struct device_node *np)
> }
>
> if (!strcmp("hvc", method)) {
> -   invoke_psci_fn = __invoke_psci_fn_hvc;
> +   set_conduit(PSCI_CONDUIT_HVC);
> } else if (!strcmp("smc", method)) {
> -   invoke_psci_fn = __invoke_psci_fn_smc;
> +   set_conduit(PSCI_CONDUIT_SMC);
> } else {
> pr_warn("invalid \"method\" property: %s\n", method);
> return -EINVAL;
> @@ -654,9 +670,9 @@ int __init psci_acpi_init(void)
> pr_info("probing for conduit method from ACPI.\n");
>
> if (acpi_psci_use_hvc())
> -   invoke_psci_fn = __invoke_psci_fn_hvc;
> +   set_conduit(PSCI_CONDUIT_HVC);
> else
> -   invoke_psci_fn = __invoke_psci_fn_smc;
> +   set_conduit(PSCI_CONDUIT_SMC);
>
> return psci_probe();
>  }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f724fd8c78e8..f2679e5faa4f 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
>  int psci_cpu_init_idle(unsigned int cpu);
>  int psci_cpu_suspend_enter(unsigned long index);
>
> +enum psci_conduit {
> +   PSCI_CONDUIT_NONE,
> +   PSCI_CONDUIT_SMC,
> +   PSCI_CONDUIT_HVC,
> +};
> +
>  struct psci_operations {
> u32 (*get_version)(void);
> int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -34,6 +40,7 @@ struct psci_operations {
> int (*affinity_info)(unsigned long target_affinity,
> unsigned long lowest_affinity_level);
> int (*migrate_info_type)(void);
> +   enum psci_conduit conduit;
>  };
>
>  extern struct psci_operations psci_ops;
> --
> 2.14.2
>
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 14/14] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Marc Zyngier
On 29/01/18 09:42, Ard Biesheuvel wrote:
> On 29 January 2018 at 09:36, Marc Zyngier  wrote:
>> On 28/01/18 23:08, Ard Biesheuvel wrote:
>>> On 26 January 2018 at 14:28, Marc Zyngier  wrote:
 Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
 It is lovely. Really.

 Signed-off-by: Marc Zyngier 
 ---
  arch/arm64/kernel/bpi.S| 20 
  arch/arm64/kernel/cpu_errata.c | 71 
 +-
  2 files changed, 90 insertions(+), 1 deletion(-)

 diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
 index 76225c2611ea..add7e08a018d 100644
 --- a/arch/arm64/kernel/bpi.S
 +++ b/arch/arm64/kernel/bpi.S
 @@ -17,6 +17,7 @@
   */

  #include 
 +#include 

  .macro ventry target
 .rept 31
 @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
 .endr
 ldp x29, x30, [sp], #16
  ENTRY(__qcom_hyp_sanitize_link_stack_end)
 +
 +.macro smccc_workaround_1 inst
 +   sub sp, sp, #(8 * 4)
 +   stp x2, x3, [sp, #(16 * 0)]
 +   stp x0, x1, [sp, #(16 * 1)]
 +   orr w0, wzr, #ARM_SMCCC_ARCH_WORKAROUND_1
 +   \inst   #0
 +   ldp x2, x3, [sp, #(16 * 0)]
 +   ldp x0, x1, [sp, #(16 * 1)]
 +   add sp, sp, #(8 * 4)
 +.endm
 +
 +ENTRY(__smccc_workaround_1_smc_start)
 +   smccc_workaround_1  smc
 +ENTRY(__smccc_workaround_1_smc_end)
 +
 +ENTRY(__smccc_workaround_1_hvc_start)
 +   smccc_workaround_1  hvc
 +ENTRY(__smccc_workaround_1_hvc_end)
 diff --git a/arch/arm64/kernel/cpu_errata.c 
 b/arch/arm64/kernel/cpu_errata.c
 index ed6881882231..f1501873f2e4 100644
 --- a/arch/arm64/kernel/cpu_errata.c
 +++ b/arch/arm64/kernel/cpu_errata.c
 @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
 bp_hardening_data);
  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
  extern char __qcom_hyp_sanitize_link_stack_start[];
  extern char __qcom_hyp_sanitize_link_stack_end[];
 +extern char __smccc_workaround_1_smc_start[];
 +extern char __smccc_workaround_1_smc_end[];
 +extern char __smccc_workaround_1_hvc_start[];
 +extern char __smccc_workaround_1_hvc_end[];

  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 const char *hyp_vecs_end)
 @@ -116,6 +120,10 @@ static void 
 __install_bp_hardening_cb(bp_hardening_cb_t fn,
  #define __psci_hyp_bp_inval_endNULL
  #define __qcom_hyp_sanitize_link_stack_start   NULL
  #define __qcom_hyp_sanitize_link_stack_end NULL
 +#define __smccc_workaround_1_smc_start NULL
 +#define __smccc_workaround_1_smc_end   NULL
 +#define __smccc_workaround_1_hvc_start NULL
 +#define __smccc_workaround_1_hvc_end   NULL

  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
   const char *hyp_vecs_start,
 @@ -142,17 +150,78 @@ static void  install_bp_hardening_cb(const struct 
 arm64_cpu_capabilities *entry,
 __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
  }

 +#include 
 +#include 
  #include 

 +static void call_smc_arch_workaround_1(void)
 +{
 +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
 +   asm volatile("smc   #0\n"
 +: "+r" (w0));
 +}
 +
 +static void call_hvc_arch_workaround_1(void)
 +{
 +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
 +   asm volatile("hvc   #0\n"
 +: "+r" (w0));
 +}
 +
 +static bool check_smccc_arch_workaround_1(const struct 
 arm64_cpu_capabilities *entry)
 +{
 +   bp_hardening_cb_t cb;
 +   void *smccc_start, *smccc_end;
 +   struct arm_smccc_res res;
 +
 +   if (psci_ops.variant == SMCCC_VARIANT_1_0)
 +   return false;
 +
 +   switch (psci_ops.conduit) {
 +   case PSCI_CONDUIT_HVC:
 +   arm_smccc_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
 + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 
 0,
 + &res);
 +   if (res.a0)
 +   return false;
 +   cb = call_hvc_arch_workaround_1;
 +   smccc_start = __smccc_workaround_1_hvc_start;
 +   smccc_end = __smccc_workaround_1_hvc_end;
 +   break;
 +
 +   case PSCI_CONDUIT_SMC:
 +   arm_smccc_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
 + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 
 0,
 

Re: [PATCH 12/14] firmware/psci: Expose PSCI conduit

2018-01-29 Thread Marc Zyngier
On 29/01/18 10:04, Ard Biesheuvel wrote:
> On 26 January 2018 at 14:28, Marc Zyngier  wrote:
>> In order to call into the firmware to apply workarounds, it is
>> useful to find out whether we're using HVC or SMC. Let's expose
>> this through the psci_ops.
>>
>> Signed-off-by: Marc Zyngier 
>> ---
>>  drivers/firmware/psci.c | 26 +-
>>  include/linux/psci.h|  7 +++
>>  2 files changed, 28 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
>> index 8b25d31e8401..570187e5d084 100644
>> --- a/drivers/firmware/psci.c
>> +++ b/drivers/firmware/psci.c
>> @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
>> return cpu == resident_cpu;
>>  }
>>
>> -struct psci_operations psci_ops;
>> +struct psci_operations psci_ops = {
>> +   .conduit = PSCI_CONDUIT_NONE,
>> +};
>>
>>  typedef unsigned long (psci_fn)(unsigned long, unsigned long,
>> unsigned long, unsigned long);
>> @@ -210,6 +212,20 @@ static unsigned long psci_migrate_info_up_cpu(void)
>>   0, 0, 0);
>>  }
>>
>> +static void set_conduit(enum psci_conduit conduit)
>> +{
>> +   switch (conduit) {
>> +   case PSCI_CONDUIT_HVC:
>> +   invoke_psci_fn = __invoke_psci_fn_hvc;
>> +   break;
>> +   case PSCI_CONDUIT_SMC:
>> +   invoke_psci_fn = __invoke_psci_fn_smc;
>> +   break;
> 
> I get a GCC warning here about PSCI_CONDUIT_NONE not being handled.


Yup, I fixed it already.

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 14/14] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Ard Biesheuvel
On 29 January 2018 at 10:07, Marc Zyngier  wrote:
> On 29/01/18 09:42, Ard Biesheuvel wrote:
>> On 29 January 2018 at 09:36, Marc Zyngier  wrote:
>>> On 28/01/18 23:08, Ard Biesheuvel wrote:
 On 26 January 2018 at 14:28, Marc Zyngier  wrote:
> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
> It is lovely. Really.
>
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/kernel/bpi.S| 20 
>  arch/arm64/kernel/cpu_errata.c | 71 
> +-
>  2 files changed, 90 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
> index 76225c2611ea..add7e08a018d 100644
> --- a/arch/arm64/kernel/bpi.S
> +++ b/arch/arm64/kernel/bpi.S
> @@ -17,6 +17,7 @@
>   */
>
>  #include 
> +#include 
>
>  .macro ventry target
> .rept 31
> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
> .endr
> ldp x29, x30, [sp], #16
>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
> +
> +.macro smccc_workaround_1 inst
> +   sub sp, sp, #(8 * 4)
> +   stp x2, x3, [sp, #(16 * 0)]
> +   stp x0, x1, [sp, #(16 * 1)]
> +   orr w0, wzr, #ARM_SMCCC_ARCH_WORKAROUND_1
> +   \inst   #0
> +   ldp x2, x3, [sp, #(16 * 0)]
> +   ldp x0, x1, [sp, #(16 * 1)]
> +   add sp, sp, #(8 * 4)
> +.endm
> +
> +ENTRY(__smccc_workaround_1_smc_start)
> +   smccc_workaround_1  smc
> +ENTRY(__smccc_workaround_1_smc_end)
> +
> +ENTRY(__smccc_workaround_1_hvc_start)
> +   smccc_workaround_1  hvc
> +ENTRY(__smccc_workaround_1_hvc_end)
> diff --git a/arch/arm64/kernel/cpu_errata.c 
> b/arch/arm64/kernel/cpu_errata.c
> index ed6881882231..f1501873f2e4 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
> bp_hardening_data);
>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>  extern char __qcom_hyp_sanitize_link_stack_start[];
>  extern char __qcom_hyp_sanitize_link_stack_end[];
> +extern char __smccc_workaround_1_smc_start[];
> +extern char __smccc_workaround_1_smc_end[];
> +extern char __smccc_workaround_1_hvc_start[];
> +extern char __smccc_workaround_1_hvc_end[];
>
>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
> const char *hyp_vecs_end)
> @@ -116,6 +120,10 @@ static void 
> __install_bp_hardening_cb(bp_hardening_cb_t fn,
>  #define __psci_hyp_bp_inval_endNULL
>  #define __qcom_hyp_sanitize_link_stack_start   NULL
>  #define __qcom_hyp_sanitize_link_stack_end NULL
> +#define __smccc_workaround_1_smc_start NULL
> +#define __smccc_workaround_1_smc_end   NULL
> +#define __smccc_workaround_1_hvc_start NULL
> +#define __smccc_workaround_1_hvc_end   NULL
>
>  static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
>   const char *hyp_vecs_start,
> @@ -142,17 +150,78 @@ static void  install_bp_hardening_cb(const struct 
> arm64_cpu_capabilities *entry,
> __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>  }
>
> +#include 
> +#include 
>  #include 
>
> +static void call_smc_arch_workaround_1(void)
> +{
> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
> +   asm volatile("smc   #0\n"
> +: "+r" (w0));
> +}
> +
> +static void call_hvc_arch_workaround_1(void)
> +{
> +   register int w0 asm("w0") = ARM_SMCCC_ARCH_WORKAROUND_1;
> +   asm volatile("hvc   #0\n"
> +: "+r" (w0));
> +}
> +
> +static bool check_smccc_arch_workaround_1(const struct 
> arm64_cpu_capabilities *entry)
> +{
> +   bp_hardening_cb_t cb;
> +   void *smccc_start, *smccc_end;
> +   struct arm_smccc_res res;
> +
> +   if (psci_ops.variant == SMCCC_VARIANT_1_0)
> +   return false;
> +
> +   switch (psci_ops.conduit) {
> +   case PSCI_CONDUIT_HVC:
> +   arm_smccc_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> + ARM_SMCCC_ARCH_WORKAROUND_1, 0, 0, 0, 0, 0, 
> 0,
> + &res);
> +   if (res.a0)
> +   return false;
> +   cb = call_hvc_arch_workaround_1;
> +   smccc_start = __smccc_workaround_1_hvc_start;
> +   smccc_end = __smccc_workaround_1_hvc_end;
> +   break;
> +
> +   case PSC

[PATCH v2 00/16] arm64: Add SMCCC v1.1 support and CVE-2017-5715 (Spectre variant 2) mitigation

2018-01-29 Thread Marc Zyngier
ARM has recently published a SMC Calling Convention (SMCCC)
specification update[1] that provides an optimised calling convention
and optional, discoverable support for mitigating CVE-2017-5715. ARM
Trusted Firmware (ATF) has already gained such an implementation[2].

This series addresses a few things:

- It provides a KVM implementation of PSCI v1.0, which is a
  prerequisite for being able to discover SMCCC v1.1, together with a
  new userspace API to control the PSCI revision number that the guest
  sees.

- It allows KVM to advertise SMCCC v1.1, which is de-facto supported
  already (it never corrupts any of the guest registers).

- It implements KVM support for the ARCH_WORKAROUND_1 function that is
  used to mitigate CVE-2017-5715 in a guest (if such mitigation is
  available on the host).

- It implements SMCCC v1.1 and ARCH_WORKAROUND_1 discovery support in
  the kernel itself.

- It finally provides firmware callbacks for CVE-2017-5715 for both
  kernel and KVM.

This method is intended to fully replace the initial PSCI_GET_VERSION
approach. Although PSCI_GET_VERSION still works, it has an obvious
overhead and is called on some of the hottest paths. We expect
ARCH_WORKAROUND_1 to be much faster.

Patch 1 is already merged, and included here for reference. Patches on
top of arm64/for-next/core. Tested on Seattle and Juno, the latter
with ATF implementing SMCCC v1.1.

[1]: 
https://developer.arm.com/-/media/developer/pdf/ARM%20DEN%200070A%20Firmware%20interfaces%20for%20mitigating%20CVE-2017-5715_V1.0.pdf

Hopefully this link is a persistent one. It is otherwise linked to
from [3], which is persistent.

[2]: https://github.com/ARM-software/arm-trusted-firmware/pull/1240

[3]: 
https://developer.arm.com/support/security-update/frequently-asked-questions

* From v1:
  - Fixed 32bit build
  - Fix function number sign extension (Ard)
  - Inline SMCCC v1.1 primitives (cpp soup)
  - Prevent SMCCC spamming on feature probing
  - Random fixes and tidying up

Marc Zyngier (16):
  arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls
  arm/arm64: KVM: Consolidate the PSCI include files
  arm/arm64: KVM: Add PSCI_VERSION helper
  arm/arm64: KVM: Add smccc accessors to PSCI code
  arm/arm64: KVM: Implement PSCI 1.0 support
  arm/arm64: KVM: Add PSCI version selection API
  arm/arm64: KVM: Advertise SMCCC v1.1
  arm/arm64: KVM: Turn kvm_psci_version into a static inline
  arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
  arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
  firmware/psci: Expose PSCI conduit
  firmware/psci: Expose SMCCC version through psci_ops
  arm/arm64: smccc: Make function identifiers an unsigned quantity
  arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
  arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

 Documentation/virtual/kvm/api.txt  |   3 +-
 Documentation/virtual/kvm/arm/psci.txt |  30 +
 arch/arm/include/asm/kvm_host.h|   3 +
 arch/arm/include/asm/kvm_psci.h|  27 -
 arch/arm/include/uapi/asm/kvm.h|   6 +
 arch/arm/kvm/guest.c   |  13 +++
 arch/arm/kvm/handle_exit.c |   8 +-
 arch/arm64/include/asm/kvm_host.h  |   3 +
 arch/arm64/include/asm/kvm_psci.h  |  44 ++-
 arch/arm64/include/uapi/asm/kvm.h  |   6 +
 arch/arm64/kernel/bpi.S|  20 
 arch/arm64/kernel/cpu_errata.c |  68 ++-
 arch/arm64/kvm/guest.c |  14 ++-
 arch/arm64/kvm/handle_exit.c   |   9 +-
 arch/arm64/kvm/hyp/hyp-entry.S |  20 +++-
 arch/arm64/kvm/hyp/switch.c|  20 ++--
 drivers/firmware/psci.c|  49 +++-
 include/kvm/arm_psci.h |  63 ++
 include/linux/arm-smccc.h  | 181 -
 include/linux/psci.h   |  13 +++
 virt/kvm/arm/arm.c |   2 +-
 virt/kvm/arm/psci.c| 202 +
 22 files changed, 721 insertions(+), 83 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 create mode 100644 include/kvm/arm_psci.h

-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 01/16] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls

2018-01-29 Thread Marc Zyngier
KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: 
Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index c09fc5a576c7..520b0dad3c62 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -53,7 +53,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
 
ret = kvm_psci_call(vcpu);
if (ret < 0) {
-   kvm_inject_undefined(vcpu);
+   vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
}
 
@@ -62,7 +62,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-   kvm_inject_undefined(vcpu);
+   vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
 }
 
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 02/16] arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls

2018-01-29 Thread Marc Zyngier
KVM doesn't follow the SMCCC when it comes to unimplemented calls,
and inject an UNDEF instead of returning an error. Since firmware
calls are now used for security mitigation, they are becoming more
common, and the undef is counter productive.

Instead, let's follow the SMCCC which states that -1 must be returned
to the caller when getting an unknown function number.

Cc: 
Signed-off-by: Marc Zyngier 
---
 arch/arm/kvm/handle_exit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index cf8bf6bf87c4..d15ac772d186 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
 
ret = kvm_psci_call(vcpu);
if (ret < 0) {
-   kvm_inject_undefined(vcpu);
+   vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
}
 
@@ -47,7 +47,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-   kvm_inject_undefined(vcpu);
+   vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
 }
 
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 03/16] arm/arm64: KVM: Consolidate the PSCI include files

2018-01-29 Thread Marc Zyngier
As we're about to update the PSCI support, and because I'm lazy,
let's move the PSCI include file to include/kvm so that both
ARM architectures can find it.

Signed-off-by: Marc Zyngier 
---
 arch/arm/include/asm/kvm_psci.h| 27 --
 arch/arm/kvm/handle_exit.c |  2 +-
 arch/arm64/kvm/handle_exit.c   |  3 ++-
 .../asm/kvm_psci.h => include/kvm/arm_psci.h   |  6 ++---
 virt/kvm/arm/arm.c |  2 +-
 virt/kvm/arm/psci.c|  3 ++-
 6 files changed, 9 insertions(+), 34 deletions(-)
 delete mode 100644 arch/arm/include/asm/kvm_psci.h
 rename arch/arm64/include/asm/kvm_psci.h => include/kvm/arm_psci.h (89%)

diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
deleted file mode 100644
index 6bda945d31fa..
--- a/arch/arm/include/asm/kvm_psci.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2012 - ARM Ltd
- * Author: Marc Zyngier 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see .
- */
-
-#ifndef __ARM_KVM_PSCI_H__
-#define __ARM_KVM_PSCI_H__
-
-#define KVM_ARM_PSCI_0_1   1
-#define KVM_ARM_PSCI_0_2   2
-
-int kvm_psci_version(struct kvm_vcpu *vcpu);
-int kvm_psci_call(struct kvm_vcpu *vcpu);
-
-#endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index d15ac772d186..e020cc82c4b1 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -21,7 +21,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 #include "trace.h"
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 520b0dad3c62..97e8d64a203d 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -22,13 +22,14 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
diff --git a/arch/arm64/include/asm/kvm_psci.h b/include/kvm/arm_psci.h
similarity index 89%
rename from arch/arm64/include/asm/kvm_psci.h
rename to include/kvm/arm_psci.h
index bc39e557c56c..2042bb909474 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -15,8 +15,8 @@
  * along with this program.  If not, see .
  */
 
-#ifndef __ARM64_KVM_PSCI_H__
-#define __ARM64_KVM_PSCI_H__
+#ifndef __KVM_ARM_PSCI_H__
+#define __KVM_ARM_PSCI_H__
 
 #define KVM_ARM_PSCI_0_1   1
 #define KVM_ARM_PSCI_0_2   2
@@ -24,4 +24,4 @@
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
 
-#endif /* __ARM64_KVM_PSCI_H__ */
+#endif /* __KVM_ARM_PSCI_H__ */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 15bf026eb182..af3e98fc377e 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -46,7 +47,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 #ifdef REQUIRES_VIRT
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index f1e363bab5e8..b322e46fd142 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -21,9 +21,10 @@
 
 #include 
 #include 
-#include 
 #include 
 
+#include 
+
 #include 
 
 /*
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 04/16] arm/arm64: KVM: Add PSCI_VERSION helper

2018-01-29 Thread Marc Zyngier
As we're about to trigger a PSCI version explosion, it doesn't
hurt to introduce a PSCI_VERSION helper that is going to be
used everywhere.

Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_psci.h | 5 +++--
 virt/kvm/arm/psci.c| 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 2042bb909474..3a408c846c09 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,8 +18,9 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
-#define KVM_ARM_PSCI_0_1   1
-#define KVM_ARM_PSCI_0_2   2
+#define PSCI_VERSION(x,y)  x) & 0x7fff) << 16) | ((y) & 0x))
+#define KVM_ARM_PSCI_0_1   PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2   PSCI_VERSION(0, 2)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index b322e46fd142..c00bb324e14e 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -222,7 +222,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 * Bits[31:16] = Major Version = 0
 * Bits[15:0] = Minor Version = 2
 */
-   val = 2;
+   val = KVM_ARM_PSCI_0_2;
break;
case PSCI_0_2_FN_CPU_SUSPEND:
case PSCI_0_2_FN64_CPU_SUSPEND:
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 05/16] arm/arm64: KVM: Add smccc accessors to PSCI code

2018-01-29 Thread Marc Zyngier
Instead of open coding the accesses to the various registers,
let's add explicit SMCCC accessors.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/psci.c | 52 ++--
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index c00bb324e14e..053654082bd4 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -34,6 +34,38 @@
 
 #define AFFINITY_MASK(level)   ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
 
+static u32 smccc_get_function(struct kvm_vcpu *vcpu)
+{
+   return vcpu_get_reg(vcpu, 0);
+}
+
+static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+   return vcpu_get_reg(vcpu, 1);
+}
+
+static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+   return vcpu_get_reg(vcpu, 2);
+}
+
+static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
+{
+   return vcpu_get_reg(vcpu, 3);
+}
+
+static void smccc_set_retval(struct kvm_vcpu *vcpu,
+unsigned long a0,
+unsigned long a1,
+unsigned long a2,
+unsigned long a3)
+{
+   vcpu_set_reg(vcpu, 0, a0);
+   vcpu_set_reg(vcpu, 1, a1);
+   vcpu_set_reg(vcpu, 2, a2);
+   vcpu_set_reg(vcpu, 3, a3);
+}
+
 static unsigned long psci_affinity_mask(unsigned long affinity_level)
 {
if (affinity_level <= 3)
@@ -79,7 +111,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu 
*source_vcpu)
unsigned long context_id;
phys_addr_t target_pc;
 
-   cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
+   cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
if (vcpu_mode_is_32bit(source_vcpu))
cpu_id &= ~((u32) 0);
 
@@ -98,8 +130,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu 
*source_vcpu)
return PSCI_RET_INVALID_PARAMS;
}
 
-   target_pc = vcpu_get_reg(source_vcpu, 2);
-   context_id = vcpu_get_reg(source_vcpu, 3);
+   target_pc = smccc_get_arg2(source_vcpu);
+   context_id = smccc_get_arg3(source_vcpu);
 
kvm_reset_vcpu(vcpu);
 
@@ -118,7 +150,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu 
*source_vcpu)
 * NOTE: We always update r0 (or x0) because for PSCI v0.1
 * the general puspose registers are undefined upon CPU_ON.
 */
-   vcpu_set_reg(vcpu, 0, context_id);
+   smccc_set_retval(vcpu, context_id, 0, 0, 0);
vcpu->arch.power_off = false;
smp_mb();   /* Make sure the above is visible */
 
@@ -138,8 +170,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct 
kvm_vcpu *vcpu)
struct kvm *kvm = vcpu->kvm;
struct kvm_vcpu *tmp;
 
-   target_affinity = vcpu_get_reg(vcpu, 1);
-   lowest_affinity_level = vcpu_get_reg(vcpu, 2);
+   target_affinity = smccc_get_arg1(vcpu);
+   lowest_affinity_level = smccc_get_arg2(vcpu);
 
/* Determine target affinity mask */
target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
@@ -212,7 +244,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
struct kvm *kvm = vcpu->kvm;
-   unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+   u32 psci_fn = smccc_get_function(vcpu);
unsigned long val;
int ret = 1;
 
@@ -279,14 +311,14 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
break;
}
 
-   vcpu_set_reg(vcpu, 0, val);
+   smccc_set_retval(vcpu, val, 0, 0, 0);
return ret;
 }
 
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
struct kvm *kvm = vcpu->kvm;
-   unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+   u32 psci_fn = smccc_get_function(vcpu);
unsigned long val;
 
switch (psci_fn) {
@@ -304,7 +336,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
break;
}
 
-   vcpu_set_reg(vcpu, 0, val);
+   smccc_set_retval(vcpu, val, 0, 0, 0);
return 1;
 }
 
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 06/16] arm/arm64: KVM: Implement PSCI 1.0 support

2018-01-29 Thread Marc Zyngier
PSCI 1.0 can be trivially implemented by having PSCI 0.2 and
the FEATURES call. Of, and returning 1.0 as the PSCI version.

We happily ignore everything else, as it is optional.

Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_psci.h |  1 +
 virt/kvm/arm/psci.c| 43 +++
 2 files changed, 44 insertions(+)

diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 3a408c846c09..e7f69c0dc249 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -21,6 +21,7 @@
 #define PSCI_VERSION(x,y)  x) & 0x7fff) << 16) | ((y) & 0x))
 #define KVM_ARM_PSCI_0_1   PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2   PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0   PSCI_VERSION(1, 0)
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 053654082bd4..6299501f7664 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -315,6 +315,47 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
return ret;
 }
 
+static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
+{
+   u32 psci_fn = smccc_get_function(vcpu);
+   u32 feature;
+   unsigned long val;
+   int ret = 1;
+
+   switch(psci_fn) {
+   case PSCI_0_2_FN_PSCI_VERSION:
+   val = KVM_ARM_PSCI_1_0;
+   break;
+   case PSCI_1_0_FN_PSCI_FEATURES:
+   feature = smccc_get_arg1(vcpu);
+   switch(feature) {
+   case PSCI_0_2_FN_PSCI_VERSION:
+   case PSCI_0_2_FN_CPU_SUSPEND:
+   case PSCI_0_2_FN64_CPU_SUSPEND:
+   case PSCI_0_2_FN_CPU_OFF:
+   case PSCI_0_2_FN_CPU_ON:
+   case PSCI_0_2_FN64_CPU_ON:
+   case PSCI_0_2_FN_AFFINITY_INFO:
+   case PSCI_0_2_FN64_AFFINITY_INFO:
+   case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
+   case PSCI_0_2_FN_SYSTEM_OFF:
+   case PSCI_0_2_FN_SYSTEM_RESET:
+   case PSCI_1_0_FN_PSCI_FEATURES:
+   val = 0;
+   break;
+   default:
+   val = PSCI_RET_NOT_SUPPORTED;
+   break;
+   }
+   break;
+   default:
+   return kvm_psci_0_2_call(vcpu);
+   }
+
+   smccc_set_retval(vcpu, val, 0, 0, 0);
+   return ret;
+}
+
 static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 {
struct kvm *kvm = vcpu->kvm;
@@ -357,6 +398,8 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
switch (kvm_psci_version(vcpu)) {
+   case KVM_ARM_PSCI_1_0:
+   return kvm_psci_1_0_call(vcpu);
case KVM_ARM_PSCI_0_2:
return kvm_psci_0_2_call(vcpu);
case KVM_ARM_PSCI_0_1:
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 07/16] arm/arm64: KVM: Add PSCI version selection API

2018-01-29 Thread Marc Zyngier
Although we've implemented PSCI 1.0 and 1.1, nothing can select them
Since all the new PSCI versions are backward compatible, we decide to
default to the latest version of the PSCI implementation. This is no
different from doing a firmware upgrade on KVM.

But in order to give a chance to hypothetical badly implemented guests
that would have a fit by discovering something other than PSCI 0.2,
let's provide a new API that allows userspace to pick one particular
version of the API.

This is implemented as a new class of "firmware" registers, where
we expose the PSCI version. This allows the PSCI version to be
save/restored as part of a guest migration, and also set to
any supported version if the guest requires it.

Signed-off-by: Marc Zyngier 
---
 Documentation/virtual/kvm/api.txt  |  3 +-
 Documentation/virtual/kvm/arm/psci.txt | 28 ++
 arch/arm/include/asm/kvm_host.h|  3 ++
 arch/arm/include/uapi/asm/kvm.h|  6 +++
 arch/arm/kvm/guest.c   | 13 +++
 arch/arm64/include/asm/kvm_host.h  |  3 ++
 arch/arm64/include/uapi/asm/kvm.h  |  6 +++
 arch/arm64/kvm/guest.c | 14 ++-
 include/kvm/arm_psci.h |  9 +
 virt/kvm/arm/psci.c| 68 +-
 10 files changed, 149 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/virtual/kvm/arm/psci.txt

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 57d3ee9e4bde..334905202141 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2493,7 +2493,8 @@ Possible features:
  and execute guest code when KVM_RUN is called.
- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
  Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
-   - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
+   - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
+  backward compatible with v0.2) for the CPU.
  Depends on KVM_CAP_ARM_PSCI_0_2.
- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
  Depends on KVM_CAP_ARM_PMU_V3.
diff --git a/Documentation/virtual/kvm/arm/psci.txt 
b/Documentation/virtual/kvm/arm/psci.txt
new file mode 100644
index ..2e49a4e9f084
--- /dev/null
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -0,0 +1,28 @@
+KVM implements the PSCI (Power State Coordination Interface)
+specification in order to provide services such as CPU on/off, reset
+and power-off to the guest.
+
+The PSCI specification is regularly updated to provide new features,
+and KVM implements these updates if they make sense from a virtualization
+point of view.
+
+This means that a guest booted on two different versions of KVM can
+observe two different "firmware" revisions. This could cause issues if
+a given guest is tied to a particular PSCI revision (unlikely), or if
+a migration causes a different PSCI version to be exposed out of the
+blue to an unsuspecting guest.
+
+In order to remedy this situation, KVM exposes a set of "firmware
+pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+interface. These registers can be saved/restored by userspace, and set
+to a convenient value if required.
+
+The following register is defined:
+
+* KVM_REG_ARM_PSCI_VERSION:
+
+  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
+  - Returns the current PSCI version on GET_ONE_REG
+  - Allows any supported PSCI version compatible with v0.2 to be set
+with SET_ONE_REG
+  - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index acbf9ec7b396..e9d57060d88c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -75,6 +75,9 @@ struct kvm_arch {
/* Interrupt controller */
struct vgic_distvgic;
int max_vcpus;
+
+   /* Mandated version of PSCI */
+   u32 psci_version;
 };
 
 #define KVM_NR_MEM_OBJS 40
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 6edd177bb1c7..47dfc99f5cd0 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -186,6 +186,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_VFP_FPINST 0x1009
 #define KVM_REG_ARM_VFP_FPINST20x100A
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)  (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
+KVM_REG_ARM_FW | ((r) & 0x))
+#define KVM_REG_ARM_PSCI_VERSION   KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR  0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 1e0784ebbfd6..a18f33edc471 100644
--- a/arch/arm/kvm/guest.c
+++ b/

[PATCH v2 09/16] arm/arm64: KVM: Turn kvm_psci_version into a static inline

2018-01-29 Thread Marc Zyngier
We're about to need kvm_psci_version in HYP too. So let's turn it
into a static inline, and pass the kvm structure as a second
parameter (so that HYP can do a kern_hyp_va on it).

Signed-off-by: Marc Zyngier 
---
 arch/arm64/kvm/hyp/switch.c | 20 
 include/kvm/arm_psci.h  | 27 ++-
 virt/kvm/arm/psci.c | 23 ++-
 3 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 036e1f3d77a6..408c04d789a5 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -19,6 +19,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -350,14 +352,16 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 
if (exit_code == ARM_EXCEPTION_TRAP &&
(kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC64 ||
-kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32) &&
-   vcpu_get_reg(vcpu, 0) == PSCI_0_2_FN_PSCI_VERSION) {
-   u64 val = PSCI_RET_NOT_SUPPORTED;
-   if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
-   val = 2;
-
-   vcpu_set_reg(vcpu, 0, val);
-   goto again;
+kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32)) {
+   u32 val = vcpu_get_reg(vcpu, 0);
+
+   if (val == PSCI_0_2_FN_PSCI_VERSION) {
+   val = kvm_psci_version(vcpu, kern_hyp_va(vcpu->kvm));
+   if (unlikely(val == KVM_ARM_PSCI_0_1))
+   val = PSCI_RET_NOT_SUPPORTED;
+   vcpu_set_reg(vcpu, 0, val);
+   goto again;
+   }
}
 
if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 4876bfac2195..32978b578002 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -18,6 +18,8 @@
 #ifndef __KVM_ARM_PSCI_H__
 #define __KVM_ARM_PSCI_H__
 
+#include 
+
 #define PSCI_VERSION(x,y)  x) & 0x7fff) << 16) | ((y) & 0x))
 #define KVM_ARM_PSCI_0_1   PSCI_VERSION(0, 1)
 #define KVM_ARM_PSCI_0_2   PSCI_VERSION(0, 2)
@@ -25,7 +27,30 @@
 
 #define KVM_ARM_PSCI_LATESTKVM_ARM_PSCI_1_0
 
-int kvm_psci_version(struct kvm_vcpu *vcpu);
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+   /*
+* Our PSCI implementation stays the same across versions from
+* v0.2 onward, only adding the few mandatory functions (such
+* as FEATURES with 1.0) that are required by newer
+* revisions. It is thus safe to return the latest, unless
+* userspace has instructed us otherwise.
+*/
+   if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+   if (kvm->arch.psci_version)
+   return kvm->arch.psci_version;
+
+   return KVM_ARM_PSCI_LATEST;
+   }
+
+   return KVM_ARM_PSCI_0_1;
+}
+
+
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 3bb336ac7d7d..a021b62ed762 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -126,7 +126,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu 
*source_vcpu)
if (!vcpu)
return PSCI_RET_INVALID_PARAMS;
if (!vcpu->arch.power_off) {
-   if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
+   if (kvm_psci_version(source_vcpu, kvm) != KVM_ARM_PSCI_0_1)
return PSCI_RET_ALREADY_ON;
else
return PSCI_RET_INVALID_PARAMS;
@@ -235,25 +235,6 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
 }
 
-int kvm_psci_version(struct kvm_vcpu *vcpu)
-{
-   /*
-* Our PSCI implementation stays the same across versions from
-* v0.2 onward, only adding the few mandatory functions (such
-* as FEATURES with 1.0) that are required by newer
-* revisions. It is thus safe to return the latest, unless
-* userspace has instructed us otherwise.
-*/
-   if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
-   if (vcpu->kvm->arch.psci_version)
-   return vcpu->kvm->arch.psci_version;
-
-   return KVM_ARM_PSCI_LATEST;
-   }
-
-   return KVM_ARM_PSCI_0_1;
-}
-
 static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 {
struct kvm *kvm = vcpu->kvm;
@@ -411,7 +392,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  */
 static int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
-   switch (kvm_psci_version(vcpu)) {
+   switch (kvm_psci_version(vcpu, vcpu->kvm)) {
   

[PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1

2018-01-29 Thread Marc Zyngier
The new SMC Calling Convention (v1.1) allows for a reduced overhead
when calling into the firmware, and provides a new feature discovery
mechanism.

Make it visible to KVM guests.

Signed-off-by: Marc Zyngier 
---
 Documentation/virtual/kvm/arm/psci.txt | 12 +++-
 arch/arm/kvm/handle_exit.c |  2 +-
 arch/arm64/kvm/handle_exit.c   |  2 +-
 include/kvm/arm_psci.h |  2 +-
 include/linux/arm-smccc.h  | 13 +
 virt/kvm/arm/psci.c| 24 +++-
 6 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/arm/psci.txt 
b/Documentation/virtual/kvm/arm/psci.txt
index 2e49a4e9f084..aafdab887b04 100644
--- a/Documentation/virtual/kvm/arm/psci.txt
+++ b/Documentation/virtual/kvm/arm/psci.txt
@@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed out 
of the
 blue to an unsuspecting guest.
 
 In order to remedy this situation, KVM exposes a set of "firmware
-pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
+pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
 interface. These registers can be saved/restored by userspace, and set
 to a convenient value if required.
 
@@ -21,8 +21,10 @@ The following register is defined:
 
 * KVM_REG_ARM_PSCI_VERSION:
 
-  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
-  - Returns the current PSCI version on GET_ONE_REG
-  - Allows any supported PSCI version compatible with v0.2 to be set
-with SET_ONE_REG
+  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
+(and thus has already been initialized)
+  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
+highest PSCI version implemented by KVM and compatible with v0.2)
+  - Allows any PSCI version implemented by KVM and compatible with
+v0.2 to be set with SET_ONE_REG
   - Affects the whole VM (even if the register view is per-vcpu)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index e020cc82c4b1..a4520c7118d2 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
  kvm_vcpu_hvc_get_imm(vcpu));
vcpu->stat.hvc_exit_stat++;
 
-   ret = kvm_psci_call(vcpu);
+   ret = kvm_hvc_call_handler(vcpu);
if (ret < 0) {
vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 97e8d64a203d..bb6e1518d819 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
*run)
kvm_vcpu_hvc_get_imm(vcpu));
vcpu->stat.hvc_exit_stat++;
 
-   ret = kvm_psci_call(vcpu);
+   ret = kvm_hvc_call_handler(vcpu);
if (ret < 0) {
vcpu_set_reg(vcpu, 0, ~0UL);
return 1;
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index f2fa7d752c4e..4876bfac2195 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -26,7 +26,7 @@
 #define KVM_ARM_PSCI_LATESTKVM_ARM_PSCI_1_0
 
 int kvm_psci_version(struct kvm_vcpu *vcpu);
-int kvm_psci_call(struct kvm_vcpu *vcpu);
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
 
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4c5bca38c653..dc68aa5a7261 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -60,6 +60,19 @@
 #define ARM_SMCCC_QUIRK_NONE   0
 #define ARM_SMCCC_QUIRK_QCOM_A61 /* Save/restore register a6 */
 
+#define ARM_SMCCC_VERSION_1_0  0x1
+#define ARM_SMCCC_VERSION_1_1  0x10001
+
+#define ARM_SMCCC_VERSION_FUNC_ID  \
+   ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+  ARM_SMCCC_SMC_32,\
+  0, 0)
+
+#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID
\
+   ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+  ARM_SMCCC_SMC_32,\
+  0, 1)
+
 #ifndef __ASSEMBLY__
 
 #include 
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 682f9be6264b..3bb336ac7d7d 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see .
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -353,6 +354,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
case PSCI_0_2_FN_SYSTEM_OFF:
case PSCI_0_2_FN_SYSTEM_RESET:
case PSCI_1_0_FN_PSCI_FEATURES:
+   case ARM_SMCCC_VERSION_FUNC_ID:
val = 0;
 

[PATCH v2 10/16] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Marc Zyngier
A new feature of SMCCC 1.1 is that it offers firmware-based CPU
workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides
BP hardening for CVE-2017-5715.

If the host has some mitigation for this issue, report that
we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the
host workaround on every guest exit.

Signed-off-by: Marc Zyngier 
---
 include/linux/arm-smccc.h |  5 +
 virt/kvm/arm/psci.c   | 17 +++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dc68aa5a7261..e1ef944ef1da 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -73,6 +73,11 @@
   ARM_SMCCC_SMC_32,\
   0, 1)
 
+#define ARM_SMCCC_ARCH_WORKAROUND_1\
+   ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+  ARM_SMCCC_SMC_32,\
+  0, 0x8000)
+
 #ifndef __ASSEMBLY__
 
 #include 
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index a021b62ed762..5677d16abc71 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -407,14 +407,27 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
 {
u32 func_id = smccc_get_function(vcpu);
-   u32 val;
+   u32 val, feature;
 
switch (func_id) {
case ARM_SMCCC_VERSION_FUNC_ID:
val = ARM_SMCCC_VERSION_1_1;
break;
case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
-   val = -1;   /* Nothing supported yet */
+   feature = smccc_get_arg1(vcpu);
+   switch(feature) {
+#ifdef CONFIG_ARM64
+   case ARM_SMCCC_ARCH_WORKAROUND_1:
+   if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR))
+   val = 0;
+   else
+   val = -1;
+   break;
+#endif
+   default:
+   val = -1;
+   break;
+   }
break;
default:
return kvm_psci_call(vcpu);
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 11/16] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling

2018-01-29 Thread Marc Zyngier
We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible.
So let's intercept it as early as we can by testing for the
function call number as soon as we've identified a HVC call
coming from the guest.

Signed-off-by: Marc Zyngier 
---
 arch/arm64/kvm/hyp/hyp-entry.S | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index e4f37b9dd47c..f36464bd57c5 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -15,6 +15,7 @@
  * along with this program.  If not, see .
  */
 
+#include 
 #include 
 
 #include 
@@ -64,10 +65,11 @@ alternative_endif
lsr x0, x1, #ESR_ELx_EC_SHIFT
 
cmp x0, #ESR_ELx_EC_HVC64
+   ccmpx0, #ESR_ELx_EC_HVC32, #4, ne
b.neel1_trap
 
-   mrs x1, vttbr_el2   // If vttbr is valid, the 64bit guest
-   cbnzx1, el1_trap// called HVC
+   mrs x1, vttbr_el2   // If vttbr is valid, the guest
+   cbnzx1, el1_hvc_guest   // called HVC
 
/* Here, we're pretty sure the host called HVC. */
ldp x0, x1, [sp], #16
@@ -100,6 +102,20 @@ alternative_endif
 
eret
 
+el1_hvc_guest:
+   /*
+* Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1.
+* The workaround has already been applied on the host,
+* so let's quickly get back to the guest. We don't bother
+* restoring x1, as it can be clobbered anyway.
+*/
+   ldr x1, [sp]// Guest's x0
+   eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
+   cbnzw1, el1_trap
+   mov x0, x1
+   add sp, sp, #16
+   eret
+
 el1_trap:
/*
 * x0: ESR_EC
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 12/16] firmware/psci: Expose PSCI conduit

2018-01-29 Thread Marc Zyngier
In order to call into the firmware to apply workarounds, it is
useful to find out whether we're using HVC or SMC. Let's expose
this through the psci_ops.

Signed-off-by: Marc Zyngier 
---
 drivers/firmware/psci.c | 28 +++-
 include/linux/psci.h|  7 +++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 8b25d31e8401..e9493da2b111 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
return cpu == resident_cpu;
 }
 
-struct psci_operations psci_ops;
+struct psci_operations psci_ops = {
+   .conduit = PSCI_CONDUIT_NONE,
+};
 
 typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long);
@@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
  0, 0, 0);
 }
 
+static void set_conduit(enum psci_conduit conduit)
+{
+   switch (conduit) {
+   case PSCI_CONDUIT_HVC:
+   invoke_psci_fn = __invoke_psci_fn_hvc;
+   break;
+   case PSCI_CONDUIT_SMC:
+   invoke_psci_fn = __invoke_psci_fn_smc;
+   break;
+   default:
+   WARN(1, "Unexpected PSCI conduit %d\n", conduit);
+   }
+
+   psci_ops.conduit = conduit;
+}
+
 static int get_set_conduit_method(struct device_node *np)
 {
const char *method;
@@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
}
 
if (!strcmp("hvc", method)) {
-   invoke_psci_fn = __invoke_psci_fn_hvc;
+   set_conduit(PSCI_CONDUIT_HVC);
} else if (!strcmp("smc", method)) {
-   invoke_psci_fn = __invoke_psci_fn_smc;
+   set_conduit(PSCI_CONDUIT_SMC);
} else {
pr_warn("invalid \"method\" property: %s\n", method);
return -EINVAL;
@@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
pr_info("probing for conduit method from ACPI.\n");
 
if (acpi_psci_use_hvc())
-   invoke_psci_fn = __invoke_psci_fn_hvc;
+   set_conduit(PSCI_CONDUIT_HVC);
else
-   invoke_psci_fn = __invoke_psci_fn_smc;
+   set_conduit(PSCI_CONDUIT_SMC);
 
return psci_probe();
 }
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f724fd8c78e8..f2679e5faa4f 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
 int psci_cpu_init_idle(unsigned int cpu);
 int psci_cpu_suspend_enter(unsigned long index);
 
+enum psci_conduit {
+   PSCI_CONDUIT_NONE,
+   PSCI_CONDUIT_SMC,
+   PSCI_CONDUIT_HVC,
+};
+
 struct psci_operations {
u32 (*get_version)(void);
int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -34,6 +40,7 @@ struct psci_operations {
int (*affinity_info)(unsigned long target_affinity,
unsigned long lowest_affinity_level);
int (*migrate_info_type)(void);
+   enum psci_conduit conduit;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops

2018-01-29 Thread Marc Zyngier
Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
let's do that at boot time, and expose the version of the calling
convention as part of the psci_ops structure.

Signed-off-by: Marc Zyngier 
---
 drivers/firmware/psci.c | 21 +
 include/linux/psci.h|  6 ++
 2 files changed, 27 insertions(+)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index e9493da2b111..dd035aaa1c33 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
 }
 
+static void __init psci_init_smccc(u32 ver)
+{
+   int feature = PSCI_RET_NOT_SUPPORTED;
+
+   if (PSCI_VERSION_MAJOR(ver) >= 1)
+   feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
+
+   if (feature == PSCI_RET_NOT_SUPPORTED) {
+   psci_ops.variant = SMCCC_VARIANT_1_0;
+   } else {
+   ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
+   if (ver != ARM_SMCCC_VERSION_1_1)
+   psci_ops.variant = SMCCC_VARIANT_1_0;
+   else
+   psci_ops.variant = SMCCC_VARIANT_1_1;
+   }
+
+   pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
+}
+
 static void __init psci_0_2_set_functions(void)
 {
pr_info("Using standard PSCI v0.2 function IDs\n");
@@ -557,6 +577,7 @@ static int __init psci_probe(void)
psci_0_2_set_functions();
 
psci_init_migrate();
+   psci_init_smccc(ver);
 
if (PSCI_VERSION_MAJOR(ver) >= 1) {
psci_init_cpu_suspend();
diff --git a/include/linux/psci.h b/include/linux/psci.h
index f2679e5faa4f..83fd16a37be3 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -31,6 +31,11 @@ enum psci_conduit {
PSCI_CONDUIT_HVC,
 };
 
+enum smccc_variant {
+   SMCCC_VARIANT_1_0,
+   SMCCC_VARIANT_1_1,
+};
+
 struct psci_operations {
u32 (*get_version)(void);
int (*cpu_suspend)(u32 state, unsigned long entry_point);
@@ -41,6 +46,7 @@ struct psci_operations {
unsigned long lowest_affinity_level);
int (*migrate_info_type)(void);
enum psci_conduit conduit;
+   enum smccc_variant variant;
 };
 
 extern struct psci_operations psci_ops;
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 14/16] arm/arm64: smccc: Make function identifiers an unsigned quantity

2018-01-29 Thread Marc Zyngier
Function identifiers are a 32bit, unsigned quantity. But we never
tell so to the compiler, resulting in the following:

 4ac:   b26187e0mov x0, #0x8001

We thus rely on the firmware narrowing it for us, which is not
always a reasonable expectation.

Cc: sta...@vger.kernel.org
Reported-by: Ard Biesheuvel 
Acked-by: Ard Biesheuvel 
Tested-by: Ard Biesheuvel 
Signed-off-by: Marc Zyngier 
---
 include/linux/arm-smccc.h | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1ef944ef1da..dd44d8458c04 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -14,14 +14,16 @@
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
 
+#include 
+
 /*
  * This file provides common defines for ARM SMC Calling Convention as
  * specified in
  * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
  */
 
-#define ARM_SMCCC_STD_CALL 0
-#define ARM_SMCCC_FAST_CALL1
+#define ARM_SMCCC_STD_CALL _AC(0,U)
+#define ARM_SMCCC_FAST_CALL_AC(1,U)
 #define ARM_SMCCC_TYPE_SHIFT   31
 
 #define ARM_SMCCC_SMC_32   0
-- 
2.14.2

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive

2018-01-29 Thread Marc Zyngier
One of the major improvement of SMCCC v1.1 is that it only clobbers
the first 4 registers, both on 32 and 64bit. This means that it
becomes very easy to provide an inline version of the SMC call
primitive, and avoid performing a function call to stash the
registers that would otherwise be clobbered by SMCCC v1.0.

Signed-off-by: Marc Zyngier 
---
 include/linux/arm-smccc.h | 157 ++
 1 file changed, 157 insertions(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dd44d8458c04..bc5843728909 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, 
unsigned long a1,
 
 #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
 
+/* SMCCC v1.1 implementation madness follows */
+#ifdef CONFIG_ARM64
+
+#define SMCCC_SMC_INST "smc#0"
+#define SMCCC_HVC_INST "hvc#0"
+
+#define __arm_smccc_1_1_prologue(inst) \
+   inst "\n"   \
+   "cbz%[ptr], 1f\n"   \
+   "stp%x[r0], %x[r1], %[ra0]\n"   \
+   "stp%x[r2], %x[r3], %[ra2]\n"   \
+   "1:\n"  \
+   : [ra0] "=Ump" (*(&___res->a0)),\
+ [ra2] "=Ump" (*(&___res->a2)),
+
+#define __arm_smccc_1_1_epilogue   : "memory"
+
+#endif
+
+#ifdef CONFIG_ARM
+#include 
+#include 
+
+#define SMCCC_SMC_INST __SMC(0)
+#define SMCCC_HVC_INST __HVC(0)
+
+#define __arm_smccc_1_1_prologue(inst) \
+   inst "\n"   \
+   "cmp%[ptr], #0\n"   \
+   "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n" \
+   : "=m" (*___res),
+
+#define __arm_smccc_1_1_epilogue   : "memory", "cc"
+
+#endif
+
+#define __constraint_write_0   \
+   [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_1   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_2   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
+#define __constraint_write_3   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
+#define __constraint_write_4   __constraint_write_3
+#define __constraint_write_5   __constraint_write_3
+#define __constraint_write_6   __constraint_write_3
+#define __constraint_write_7   __constraint_write_3
+
+#define __constraint_read_0: [ptr] "r" (___res)
+#define __constraint_read_1__constraint_read_0
+#define __constraint_read_2__constraint_read_0
+#define __constraint_read_3__constraint_read_0
+#define __constraint_read_4__constraint_read_3, "r" (r4)
+#define __constraint_read_5__constraint_read_4, "r" (r5)
+#define __constraint_read_6__constraint_read_5, "r" (r6)
+#define __constraint_read_7__constraint_read_6, "r" (r7)
+
+#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
+
+#define __count_args(...)  \
+   ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define __declare_arg_0(a0, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 asm("r0") = a0;   \
+   register unsigned long r1 asm("r1");\
+   register unsigned long r2 asm("r2");\
+   register unsigned long r3 asm("r3")
+
+#define __declare_arg_1(a0, a1, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 asm("r0") = a0;   \
+   register typeof(a1)r1 asm("r1") = a1;   \
+   register unsigned long r2 asm("r2");\
+   register unsigned long r3 asm("r3")
+
+#define __declare_arg_2(a0, a1, a2, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 asm("r0") = a0;   \
+   register typeof(a1)r1 asm("r1") = a1;   \
+   register typeof(a2)r2 asm("r2") = a2;   \
+   register unsigned long r3 asm("r3")
+
+#define __declare_arg_3(a0, a1, a2, a3, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 as

[PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Marc Zyngier
Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
It is lovely. Really.

Signed-off-by: Marc Zyngier 
---
 arch/arm64/include/asm/kvm_psci.h | 63 
 arch/arm64/kernel/bpi.S   | 20 
 arch/arm64/kernel/cpu_errata.c| 68 ++-
 3 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/kvm_psci.h

diff --git a/arch/arm64/include/asm/kvm_psci.h 
b/arch/arm64/include/asm/kvm_psci.h
new file mode 100644
index ..f553e3795a4e
--- /dev/null
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef __ARM64_KVM_PSCI_H__
+#define __ARM64_KVM_PSCI_H__
+
+#include 
+
+#define PSCI_VERSION(x,y)  x) & 0x7fff) << 16) | ((y) & 0x))
+#define KVM_ARM_PSCI_0_1   PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2   PSCI_VERSION(0, 2)
+#define KVM_ARM_PSCI_1_0   PSCI_VERSION(1, 0)
+
+#define KVM_ARM_PSCI_LATESTKVM_ARM_PSCI_1_0
+
+/*
+ * We need the KVM pointer independently from the vcpu as we can call
+ * this from HYP, and need to apply kern_hyp_va on it...
+ */
+static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
+{
+   /*
+* Our PSCI implementation stays the same across versions from
+* v0.2 onward, only adding the few mandatory functions (such
+* as FEATURES with 1.0) that are required by newer
+* revisions. It is thus safe to return the latest, unless
+* userspace has instructed us otherwise.
+*/
+   if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
+   if (kvm->arch.psci_version)
+   return kvm->arch.psci_version;
+
+   return KVM_ARM_PSCI_LATEST;
+   }
+
+   return KVM_ARM_PSCI_0_1;
+}
+
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+struct kvm_one_reg;
+
+int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
+#endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
index 76225c2611ea..fdeed629f2c6 100644
--- a/arch/arm64/kernel/bpi.S
+++ b/arch/arm64/kernel/bpi.S
@@ -17,6 +17,7 @@
  */
 
 #include 
+#include 
 
 .macro ventry target
.rept 31
@@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
.endr
ldp x29, x30, [sp], #16
 ENTRY(__qcom_hyp_sanitize_link_stack_end)
+
+.macro smccc_workaround_1 inst
+   sub sp, sp, #(8 * 4)
+   stp x2, x3, [sp, #(8 * 0)]
+   stp x0, x1, [sp, #(8 * 2)]
+   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1
+   \inst   #0
+   ldp x2, x3, [sp, #(8 * 0)]
+   ldp x0, x1, [sp, #(8 * 2)]
+   add sp, sp, #(8 * 4)
+.endm
+
+ENTRY(__smccc_workaround_1_smc_start)
+   smccc_workaround_1  smc
+ENTRY(__smccc_workaround_1_smc_end)
+
+ENTRY(__smccc_workaround_1_hvc_start)
+   smccc_workaround_1  hvc
+ENTRY(__smccc_workaround_1_hvc_end)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index ed6881882231..36cff870d5d7 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
bp_hardening_data);
 extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
 extern char __qcom_hyp_sanitize_link_stack_start[];
 extern char __qcom_hyp_sanitize_link_stack_end[];
+extern char __smccc_workaround_1_smc_start[];
+extern char __smccc_workaround_1_smc_end[];
+extern char __smccc_workaround_1_hvc_start[];
+extern char __smccc_workaround_1_hvc_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
const char *hyp_vecs_end)
@@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
 #define __psci_hyp_bp_inval_endNULL
 #define __qcom_hyp_sanitize_link_stack_start   NULL
 #define __qcom_hyp_sanitize_link_stack_end NULL
+#define __smccc_workaround_1_smc_start NULL
+#define __smccc_workaround_1_smc_end   NULL
+#defin

Re: [PATCH v2 12/16] firmware/psci: Expose PSCI conduit

2018-01-29 Thread Lorenzo Pieralisi
On Mon, Jan 29, 2018 at 05:45:55PM +, Marc Zyngier wrote:
> In order to call into the firmware to apply workarounds, it is
> useful to find out whether we're using HVC or SMC. Let's expose
> this through the psci_ops.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  drivers/firmware/psci.c | 28 +++-
>  include/linux/psci.h|  7 +++
>  2 files changed, 30 insertions(+), 5 deletions(-)

Acked-by: Lorenzo Pieralisi 

> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 8b25d31e8401..e9493da2b111 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu)
>   return cpu == resident_cpu;
>  }
>  
> -struct psci_operations psci_ops;
> +struct psci_operations psci_ops = {
> + .conduit = PSCI_CONDUIT_NONE,
> +};
>  
>  typedef unsigned long (psci_fn)(unsigned long, unsigned long,
>   unsigned long, unsigned long);
> @@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void)
> 0, 0, 0);
>  }
>  
> +static void set_conduit(enum psci_conduit conduit)
> +{
> + switch (conduit) {
> + case PSCI_CONDUIT_HVC:
> + invoke_psci_fn = __invoke_psci_fn_hvc;
> + break;
> + case PSCI_CONDUIT_SMC:
> + invoke_psci_fn = __invoke_psci_fn_smc;
> + break;
> + default:
> + WARN(1, "Unexpected PSCI conduit %d\n", conduit);
> + }
> +
> + psci_ops.conduit = conduit;
> +}
> +
>  static int get_set_conduit_method(struct device_node *np)
>  {
>   const char *method;
> @@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np)
>   }
>  
>   if (!strcmp("hvc", method)) {
> - invoke_psci_fn = __invoke_psci_fn_hvc;
> + set_conduit(PSCI_CONDUIT_HVC);
>   } else if (!strcmp("smc", method)) {
> - invoke_psci_fn = __invoke_psci_fn_smc;
> + set_conduit(PSCI_CONDUIT_SMC);
>   } else {
>   pr_warn("invalid \"method\" property: %s\n", method);
>   return -EINVAL;
> @@ -654,9 +672,9 @@ int __init psci_acpi_init(void)
>   pr_info("probing for conduit method from ACPI.\n");
>  
>   if (acpi_psci_use_hvc())
> - invoke_psci_fn = __invoke_psci_fn_hvc;
> + set_conduit(PSCI_CONDUIT_HVC);
>   else
> - invoke_psci_fn = __invoke_psci_fn_smc;
> + set_conduit(PSCI_CONDUIT_SMC);
>  
>   return psci_probe();
>  }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f724fd8c78e8..f2679e5faa4f 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu);
>  int psci_cpu_init_idle(unsigned int cpu);
>  int psci_cpu_suspend_enter(unsigned long index);
>  
> +enum psci_conduit {
> + PSCI_CONDUIT_NONE,
> + PSCI_CONDUIT_SMC,
> + PSCI_CONDUIT_HVC,
> +};
> +
>  struct psci_operations {
>   u32 (*get_version)(void);
>   int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -34,6 +40,7 @@ struct psci_operations {
>   int (*affinity_info)(unsigned long target_affinity,
>   unsigned long lowest_affinity_level);
>   int (*migrate_info_type)(void);
> + enum psci_conduit conduit;
>  };
>  
>  extern struct psci_operations psci_ops;
> -- 
> 2.14.2
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 13/16] firmware/psci: Expose SMCCC version through psci_ops

2018-01-29 Thread Lorenzo Pieralisi
On Mon, Jan 29, 2018 at 05:45:56PM +, Marc Zyngier wrote:
> Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed,
> let's do that at boot time, and expose the version of the calling
> convention as part of the psci_ops structure.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  drivers/firmware/psci.c | 21 +
>  include/linux/psci.h|  6 ++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index e9493da2b111..dd035aaa1c33 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -511,6 +511,26 @@ static void __init psci_init_migrate(void)
>   pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid);
>  }
>  
> +static void __init psci_init_smccc(u32 ver)
> +{
> + int feature = PSCI_RET_NOT_SUPPORTED;
> +
> + if (PSCI_VERSION_MAJOR(ver) >= 1)
> + feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
> +
> + if (feature == PSCI_RET_NOT_SUPPORTED) {
> + psci_ops.variant = SMCCC_VARIANT_1_0;
> + } else {
> + ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
> + if (ver != ARM_SMCCC_VERSION_1_1)
> + psci_ops.variant = SMCCC_VARIANT_1_0;
> + else
> + psci_ops.variant = SMCCC_VARIANT_1_1;
> + }
> +
> + pr_info("SMC Calling Convention v1.%d\n", psci_ops.variant);
> +}
> +
>  static void __init psci_0_2_set_functions(void)
>  {
>   pr_info("Using standard PSCI v0.2 function IDs\n");
> @@ -557,6 +577,7 @@ static int __init psci_probe(void)
>   psci_0_2_set_functions();
>  
>   psci_init_migrate();
> + psci_init_smccc(ver);

Given that SMCCC_VARIANT_1_0 is already the default value (unless you do
the same we did with the conduit) we can move psci_init_smccc() call
inside the if below (that is there to detect a callable psci_features())
and remove the check in psci_init_smccc(), up to you.

>  
>   if (PSCI_VERSION_MAJOR(ver) >= 1) {
>   psci_init_cpu_suspend();
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index f2679e5faa4f..83fd16a37be3 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -31,6 +31,11 @@ enum psci_conduit {
>   PSCI_CONDUIT_HVC,
>  };
>  
> +enum smccc_variant {
> + SMCCC_VARIANT_1_0,
> + SMCCC_VARIANT_1_1,
> +};
> +
>  struct psci_operations {
>   u32 (*get_version)(void);
>   int (*cpu_suspend)(u32 state, unsigned long entry_point);
> @@ -41,6 +46,7 @@ struct psci_operations {
>   unsigned long lowest_affinity_level);
>   int (*migrate_info_type)(void);
>   enum psci_conduit conduit;
> + enum smccc_variant variant;

Nit: I would add an smccc_ prefix to the variant field (or rename it
to smccc_version).

You can add my:

Acked-by: Lorenzo Pieralisi 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive

2018-01-29 Thread Robin Murphy

On 29/01/18 17:45, Marc Zyngier wrote:

One of the major improvement of SMCCC v1.1 is that it only clobbers
the first 4 registers, both on 32 and 64bit. This means that it
becomes very easy to provide an inline version of the SMC call
primitive, and avoid performing a function call to stash the
registers that would otherwise be clobbered by SMCCC v1.0.


This is disgusting... I love it :D


Signed-off-by: Marc Zyngier 
---
  include/linux/arm-smccc.h | 157 ++
  1 file changed, 157 insertions(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index dd44d8458c04..bc5843728909 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, 
unsigned long a1,
  
  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
  
+/* SMCCC v1.1 implementation madness follows */

+#ifdef CONFIG_ARM64
+
+#define SMCCC_SMC_INST "smc   #0"
+#define SMCCC_HVC_INST "hvc   #0"
+
+#define __arm_smccc_1_1_prologue(inst) \
+   inst "\n" \
+   "cbz   %[ptr], 1f\n"  \
+   "stp   %x[r0], %x[r1], %[ra0]\n"  \
+   "stp   %x[r2], %x[r3], %[ra2]\n"  \
+   "1:\n"\
+   : [ra0] "=Ump" (*(&___res->a0)),   \
+ [ra2] "=Ump" (*(&___res->a2)),


Rather than embedding a guaranteed spill to memory, I wonder if there's 
money in just always declaring r0-r3 as in-out operands, and propagating 
them by value afterwards, i.e.:


asm(...);
if (___res)
*___res = (struct arm_smccc_res){ r0, r1, r2, r3 };

In theory, for sufficiently simple callers that might allow res to stay 
in registers for its entire lifetime and give nicer codegen. It *might* 
also simplify some of this macro machinery too, although at this point 
in the evening I can't really tell...


Robin.


+
+#define __arm_smccc_1_1_epilogue   : "memory"
+   
+#endif
+
+#ifdef CONFIG_ARM
+#include 
+#include 
+
+#define SMCCC_SMC_INST __SMC(0)
+#define SMCCC_HVC_INST __HVC(0)
+
+#define __arm_smccc_1_1_prologue(inst) \
+   inst "\n" \
+   "cmp   %[ptr], #0\n"  \
+   "stmne %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n"\
+   : "=m" (*___res),
+
+#define __arm_smccc_1_1_epilogue   : "memory", "cc"
+   
+#endif
+
+#define __constraint_write_0   \
+   [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_1   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
+#define __constraint_write_2   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
+#define __constraint_write_3   \
+   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)
+#define __constraint_write_4   __constraint_write_3
+#define __constraint_write_5   __constraint_write_3
+#define __constraint_write_6   __constraint_write_3
+#define __constraint_write_7   __constraint_write_3
+
+#define __constraint_read_0: [ptr] "r" (___res)
+#define __constraint_read_1__constraint_read_0
+#define __constraint_read_2__constraint_read_0
+#define __constraint_read_3__constraint_read_0
+#define __constraint_read_4__constraint_read_3, "r" (r4)
+#define __constraint_read_5__constraint_read_4, "r" (r5)
+#define __constraint_read_6__constraint_read_5, "r" (r6)
+#define __constraint_read_7__constraint_read_6, "r" (r7)
+
+#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
+
+#define __count_args(...)  \
+   ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define __declare_arg_0(a0, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 asm("r0") = a0; \
+   register unsigned long r1 asm("r1");  \
+   register unsigned long r2 asm("r2");  \
+   register unsigned long r3 asm("r3")
+
+#define __declare_arg_1(a0, a1, res)   \
+   struct arm_smccc_res   *___res = res;   \
+   register u32   r0 asm("r0") = a0; \
+   register typeof(a1)r1 asm("r1") = a1; \
+   register unsigned long r2 asm("r2");  \
+

Re: [PATCH v2 16/16] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support

2018-01-29 Thread Ard Biesheuvel
On 29 January 2018 at 17:45, Marc Zyngier  wrote:
> Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1.
> It is lovely. Really.
>
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/include/asm/kvm_psci.h | 63 
>  arch/arm64/kernel/bpi.S   | 20 
>  arch/arm64/kernel/cpu_errata.c| 68 
> ++-
>  3 files changed, 150 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm64/include/asm/kvm_psci.h
>
> diff --git a/arch/arm64/include/asm/kvm_psci.h 
> b/arch/arm64/include/asm/kvm_psci.h

Did you mean to add this file? It is mostly identical to include/kvm/arm_psci.h

> new file mode 100644
> index ..f553e3795a4e
> --- /dev/null
> +++ b/arch/arm64/include/asm/kvm_psci.h
> @@ -0,0 +1,63 @@
> +/*
> + * Copyright (C) 2012,2013 - ARM Ltd
> + * Author: Marc Zyngier 
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see .
> + */
> +
> +#ifndef __ARM64_KVM_PSCI_H__
> +#define __ARM64_KVM_PSCI_H__
> +
> +#include 
> +
> +#define PSCI_VERSION(x,y)  x) & 0x7fff) << 16) | ((y) & 0x))
> +#define KVM_ARM_PSCI_0_1   PSCI_VERSION(0, 1)
> +#define KVM_ARM_PSCI_0_2   PSCI_VERSION(0, 2)
> +#define KVM_ARM_PSCI_1_0   PSCI_VERSION(1, 0)
> +
> +#define KVM_ARM_PSCI_LATESTKVM_ARM_PSCI_1_0
> +
> +/*
> + * We need the KVM pointer independently from the vcpu as we can call
> + * this from HYP, and need to apply kern_hyp_va on it...
> + */
> +static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
> +{
> +   /*
> +* Our PSCI implementation stays the same across versions from
> +* v0.2 onward, only adding the few mandatory functions (such
> +* as FEATURES with 1.0) that are required by newer
> +* revisions. It is thus safe to return the latest, unless
> +* userspace has instructed us otherwise.
> +*/
> +   if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) {
> +   if (kvm->arch.psci_version)
> +   return kvm->arch.psci_version;
> +
> +   return KVM_ARM_PSCI_LATEST;
> +   }
> +
> +   return KVM_ARM_PSCI_0_1;
> +}
> +
> +
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
> +
> +struct kvm_one_reg;
> +
> +int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
> +int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
> +int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> +
> +#endif /* __ARM64_KVM_PSCI_H__ */
> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
> index 76225c2611ea..fdeed629f2c6 100644
> --- a/arch/arm64/kernel/bpi.S
> +++ b/arch/arm64/kernel/bpi.S
> @@ -17,6 +17,7 @@
>   */
>
>  #include 
> +#include 
>
>  .macro ventry target
> .rept 31
> @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start)
> .endr
> ldp x29, x30, [sp], #16
>  ENTRY(__qcom_hyp_sanitize_link_stack_end)
> +
> +.macro smccc_workaround_1 inst
> +   sub sp, sp, #(8 * 4)
> +   stp x2, x3, [sp, #(8 * 0)]
> +   stp x0, x1, [sp, #(8 * 2)]
> +   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1
> +   \inst   #0
> +   ldp x2, x3, [sp, #(8 * 0)]
> +   ldp x0, x1, [sp, #(8 * 2)]
> +   add sp, sp, #(8 * 4)
> +.endm
> +
> +ENTRY(__smccc_workaround_1_smc_start)
> +   smccc_workaround_1  smc
> +ENTRY(__smccc_workaround_1_smc_end)
> +
> +ENTRY(__smccc_workaround_1_hvc_start)
> +   smccc_workaround_1  hvc
> +ENTRY(__smccc_workaround_1_hvc_end)
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index ed6881882231..36cff870d5d7 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, 
> bp_hardening_data);
>  extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
>  extern char __qcom_hyp_sanitize_link_stack_start[];
>  extern char __qcom_hyp_sanitize_link_stack_end[];
> +extern char __smccc_workaround_1_smc_start[];
> +extern char __smccc_workaround_1_smc_end[];
> +extern char __smccc_workaround_1_hvc_start[];
> +extern char __smccc_workaround_1_hvc_end[];
>
>  static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
> 

Re: [PATCH v2 15/16] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive

2018-01-29 Thread Ard Biesheuvel
On 29 January 2018 at 17:45, Marc Zyngier  wrote:
> One of the major improvement of SMCCC v1.1 is that it only clobbers
> the first 4 registers, both on 32 and 64bit. This means that it
> becomes very easy to provide an inline version of the SMC call
> primitive, and avoid performing a function call to stash the
> registers that would otherwise be clobbered by SMCCC v1.0.
>
> Signed-off-by: Marc Zyngier 
> ---
>  include/linux/arm-smccc.h | 157 
> ++
>  1 file changed, 157 insertions(+)
>
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index dd44d8458c04..bc5843728909 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -150,5 +150,162 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, 
> unsigned long a1,
>
>  #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
>
> +/* SMCCC v1.1 implementation madness follows */
> +#ifdef CONFIG_ARM64
> +
> +#define SMCCC_SMC_INST "smc#0"
> +#define SMCCC_HVC_INST "hvc#0"
> +
> +#define __arm_smccc_1_1_prologue(inst) \
> +   inst "\n"   \
> +   "cbz%[ptr], 1f\n"   \
> +   "stp%x[r0], %x[r1], %[ra0]\n"   \
> +   "stp%x[r2], %x[r3], %[ra2]\n"   \
> +   "1:\n"  \
> +   : [ra0] "=Ump" (*(&___res->a0)),\
> + [ra2] "=Ump" (*(&___res->a2)),
> +
> +#define __arm_smccc_1_1_epilogue   : "memory"
> +
> +#endif
> +
> +#ifdef CONFIG_ARM
> +#include 
> +#include 
> +
> +#define SMCCC_SMC_INST __SMC(0)
> +#define SMCCC_HVC_INST __HVC(0)
> +
> +#define __arm_smccc_1_1_prologue(inst) \
> +   inst "\n"   \
> +   "cmp%[ptr], #0\n"   \
> +   "stmne  %[ptr], {%[r0], %[r1], %[r2], %[r3]}\n" \
> +   : "=m" (*___res),
> +
> +#define __arm_smccc_1_1_epilogue   : "memory", "cc"
> +
> +#endif
> +
> +#define __constraint_write_0   \
> +   [r0] "+r" (r0), [r1] "=r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_1   \
> +   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "=r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_2   \
> +   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "=r" (r3)
> +#define __constraint_write_3   \
> +   [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [r3] "+r" (r3)

It seems you need +r for all arguments, otherwise the compiler will
notice that the value is never used, and may assign the register to
'res' instead, i.e.,

 3e4:   320107e0mov w0, #0x8001 // #-2147483647
 3e8:   320183e1mov w1, #0x80008000 // #-2147450880
 3ec:   910123a2add x2, x29, #0x48
 3f0:   d402hvc #0x0
 3f4:   b462cbz x2, 400 
 3f8:   a90487a0stp x0, x1, [x29, #72]
 3fc:   a9058fa2stp x2, x3, [x29, #88]

(for the code generated in the next patch)

> +#define __constraint_write_4   __constraint_write_3
> +#define __constraint_write_5   __constraint_write_3
> +#define __constraint_write_6   __constraint_write_3
> +#define __constraint_write_7   __constraint_write_3
> +
> +#define __constraint_read_0: [ptr] "r" (___res)
> +#define __constraint_read_1__constraint_read_0
> +#define __constraint_read_2__constraint_read_0
> +#define __constraint_read_3__constraint_read_0
> +#define __constraint_read_4__constraint_read_3, "r" (r4)
> +#define __constraint_read_5__constraint_read_4, "r" (r5)
> +#define __constraint_read_6__constraint_read_5, "r" (r6)
> +#define __constraint_read_7__constraint_read_6, "r" (r7)
> +
> +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x
> +
> +#define __count_args(...)  \
> +   ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
> +
> +#define __declare_arg_0(a0, res)   \
> +   struct arm_smccc_res   *___res = res;   \
> +   register u32   r0 asm("r0") = a0;   \
> +   register unsigned long r1 asm("r1");\
> +   register unsigned long r2 asm("r2");\
> +   register unsigned long r3 asm("r3")
> +
> +#define __declare_arg_1(a0, a1, res)   \
> +   struct arm_smccc_res   *___res = res;   \
> +   register u32   r0 asm("r0") = a0;   \
> +   

Re: [PATCH v2 08/16] arm/arm64: KVM: Advertise SMCCC v1.1

2018-01-29 Thread Russell King - ARM Linux
On Mon, Jan 29, 2018 at 05:45:51PM +, Marc Zyngier wrote:
> The new SMC Calling Convention (v1.1) allows for a reduced overhead
> when calling into the firmware, and provides a new feature discovery
> mechanism.
> 
> Make it visible to KVM guests.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  Documentation/virtual/kvm/arm/psci.txt | 12 +++-
>  arch/arm/kvm/handle_exit.c |  2 +-
>  arch/arm64/kvm/handle_exit.c   |  2 +-
>  include/kvm/arm_psci.h |  2 +-
>  include/linux/arm-smccc.h  | 13 +
>  virt/kvm/arm/psci.c| 24 +++-
>  6 files changed, 46 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/virtual/kvm/arm/psci.txt 
> b/Documentation/virtual/kvm/arm/psci.txt
> index 2e49a4e9f084..aafdab887b04 100644
> --- a/Documentation/virtual/kvm/arm/psci.txt
> +++ b/Documentation/virtual/kvm/arm/psci.txt
> @@ -13,7 +13,7 @@ a migration causes a different PSCI version to be exposed 
> out of the
>  blue to an unsuspecting guest.
>  
>  In order to remedy this situation, KVM exposes a set of "firmware
> -pseuodo-registers" that can be manipulated using the GET/SET_ONE_REG
> +pseudo-registers" that can be manipulated using the GET/SET_ONE_REG

This should surely be in patch 7?

>  interface. These registers can be saved/restored by userspace, and set
>  to a convenient value if required.
>  
> @@ -21,8 +21,10 @@ The following register is defined:
>  
>  * KVM_REG_ARM_PSCI_VERSION:
>  
> -  - Only valid if the vcpu has KVM_ARM_VCPU_PSCI_0_2 feature set
> -  - Returns the current PSCI version on GET_ONE_REG
> -  - Allows any supported PSCI version compatible with v0.2 to be set
> -with SET_ONE_REG
> +  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
> +(and thus has already been initialized)
> +  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
> +highest PSCI version implemented by KVM and compatible with v0.2)
> +  - Allows any PSCI version implemented by KVM and compatible with
> +v0.2 to be set with SET_ONE_REG
>- Affects the whole VM (even if the register view is per-vcpu)
> diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
> index e020cc82c4b1..a4520c7118d2 100644
> --- a/arch/arm/kvm/handle_exit.c
> +++ b/arch/arm/kvm/handle_exit.c
> @@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
> *run)
> kvm_vcpu_hvc_get_imm(vcpu));
>   vcpu->stat.hvc_exit_stat++;
>  
> - ret = kvm_psci_call(vcpu);
> + ret = kvm_hvc_call_handler(vcpu);
>   if (ret < 0) {
>   vcpu_set_reg(vcpu, 0, ~0UL);
>   return 1;
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 97e8d64a203d..bb6e1518d819 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run 
> *run)
>   kvm_vcpu_hvc_get_imm(vcpu));
>   vcpu->stat.hvc_exit_stat++;
>  
> - ret = kvm_psci_call(vcpu);
> + ret = kvm_hvc_call_handler(vcpu);
>   if (ret < 0) {
>   vcpu_set_reg(vcpu, 0, ~0UL);
>   return 1;
> diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
> index f2fa7d752c4e..4876bfac2195 100644
> --- a/include/kvm/arm_psci.h
> +++ b/include/kvm/arm_psci.h
> @@ -26,7 +26,7 @@
>  #define KVM_ARM_PSCI_LATEST  KVM_ARM_PSCI_1_0
>  
>  int kvm_psci_version(struct kvm_vcpu *vcpu);
> -int kvm_psci_call(struct kvm_vcpu *vcpu);
> +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
>  
>  struct kvm_one_reg;
>  
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 4c5bca38c653..dc68aa5a7261 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -60,6 +60,19 @@
>  #define ARM_SMCCC_QUIRK_NONE 0
>  #define ARM_SMCCC_QUIRK_QCOM_A6  1 /* Save/restore register a6 */
>  
> +#define ARM_SMCCC_VERSION_1_00x1
> +#define ARM_SMCCC_VERSION_1_10x10001
> +
> +#define ARM_SMCCC_VERSION_FUNC_ID\
> + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
> +ARM_SMCCC_SMC_32,\
> +0, 0)
> +
> +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID  
> \
> + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
> +ARM_SMCCC_SMC_32,\
> +0, 1)
> +
>  #ifndef __ASSEMBLY__
>  
>  #include 
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index 682f9be6264b..3bb336ac7d7d 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -15,6 +15,7 @@
>   * along with this program.  If not, see .
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include