diff mbox

[v2,4/5] drivers: firmware: psci: add extended stateid power_state support

Message ID 1436375811-10529-5-git-send-email-lorenzo.pieralisi@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lorenzo Pieralisi July 8, 2015, 5:16 p.m. UTC
PSCI v1.0 augmented the power_state parameter format specification
(extended stateid) and introduced a way to probe it through the
PSCI_FEATURES interface.

This patch implements code that detects the power_state format at
run-time through the PSCI_FEATURES interface, so that the power_state
argument can be properly detected and validated in the kernel according
to the information provided through firmware.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 drivers/firmware/psci.c   | 34 ++++++++++++++++++++++++++++++++--
 include/uapi/linux/psci.h | 12 ++++++++++++
 2 files changed, 44 insertions(+), 2 deletions(-)

Comments

Kevin Hilman Oct. 22, 2015, 10:07 p.m. UTC | #1
On Wed, Jul 8, 2015 at 10:16 AM, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> PSCI v1.0 augmented the power_state parameter format specification
> (extended stateid) and introduced a way to probe it through the
> PSCI_FEATURES interface.
>
> This patch implements code that detects the power_state format at
> run-time through the PSCI_FEATURES interface, so that the power_state
> argument can be properly detected and validated in the kernel according
> to the information provided through firmware.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>

kernelci.org started finding a new boot failures in the arm-soc tree
on arm64 qemu[1] and it was bisected down to this patch, which is in
arm-soc in the form of commit a5c00bb28da0 (drivers: firmware: psci:
add extended stateid power_state support)

The patch doesn't revert cleanly, so I didn't dig much further, but
this suggests that some more testing on qemu is needed (or does qemu
need to be upgraded?)

Kevin

[1] http://kernelci.org/boot/all/job/arm-soc/kernel/v4.3-rc5-557-g159ca7e43189/

> ---
>  drivers/firmware/psci.c   | 34 ++++++++++++++++++++++++++++++++--
>  include/uapi/linux/psci.h | 12 ++++++++++++
>  2 files changed, 44 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 24ef3a8..bd2ba5b 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -75,14 +75,34 @@ static u32 psci_function_id[PSCI_FN_MAX];
>                                 PSCI_0_2_POWER_STATE_TYPE_MASK | \
>                                 PSCI_0_2_POWER_STATE_AFFL_MASK)
>
> +#define PSCI_1_0_EXT_POWER_STATE_MASK          \
> +                               (PSCI_1_0_EXT_POWER_STATE_ID_MASK | \
> +                               PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
> +
> +static u32 psci_cpu_suspend_feature;
> +
> +static inline bool psci_has_ext_power_state(void)
> +{
> +       return psci_cpu_suspend_feature &
> +                               PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
> +}
> +
>  bool psci_power_state_loses_context(u32 state)
>  {
> -       return state & PSCI_0_2_POWER_STATE_TYPE_MASK;
> +       const u32 mask = psci_has_ext_power_state() ?
> +                                       PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
> +                                       PSCI_0_2_POWER_STATE_TYPE_MASK;
> +
> +       return state & mask;
>  }
>
>  bool psci_power_state_is_valid(u32 state)
>  {
> -       return !(state & ~PSCI_0_2_POWER_STATE_MASK);
> +       const u32 valid_mask = psci_has_ext_power_state() ?
> +                              PSCI_1_0_EXT_POWER_STATE_MASK :
> +                              PSCI_0_2_POWER_STATE_MASK;
> +
> +       return !(state & ~valid_mask);
>  }
>
>  static int psci_to_linux_errno(int errno)
> @@ -203,6 +223,14 @@ static int __init psci_features(u32 psci_func_id)
>                               psci_func_id, 0, 0);
>  }
>
> +static void __init psci_init_cpu_suspend(void)
> +{
> +       int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]);
> +
> +       if (feature != PSCI_RET_NOT_SUPPORTED)
> +               psci_cpu_suspend_feature = feature;
> +}
> +
>  /*
>   * Detect the presence of a resident Trusted OS which may cause CPU_OFF to
>   * return DENIED (which would be fatal).
> @@ -287,6 +315,8 @@ static int __init psci_probe(void)
>
>         psci_init_migrate();
>
> +       psci_init_cpu_suspend();
> +
>         return 0;
>  }
>
> diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
> index 187b828d..0a9485f 100644
> --- a/include/uapi/linux/psci.h
> +++ b/include/uapi/linux/psci.h
> @@ -58,6 +58,13 @@
>  #define PSCI_0_2_POWER_STATE_AFFL_MASK         \
>                                 (0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
>
> +/* PSCI extended power state encoding for CPU_SUSPEND function */
> +#define PSCI_1_0_EXT_POWER_STATE_ID_MASK       0xfffffff
> +#define PSCI_1_0_EXT_POWER_STATE_ID_SHIFT      0
> +#define PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT    30
> +#define PSCI_1_0_EXT_POWER_STATE_TYPE_MASK     \
> +                               (0x1 << PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT)
> +
>  /* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
>  #define PSCI_0_2_AFFINITY_LEVEL_ON             0
>  #define PSCI_0_2_AFFINITY_LEVEL_OFF            1
> @@ -78,6 +85,11 @@
>  #define PSCI_VERSION_MINOR(ver)                        \
>                 ((ver) & PSCI_VERSION_MINOR_MASK)
>
> +/* PSCI features decoding (>=1.0) */
> +#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
> +#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK  \
> +                       (0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
> +
>  /* PSCI return values (inclusive of all PSCI versions) */
>  #define PSCI_RET_SUCCESS                       0
>  #define PSCI_RET_NOT_SUPPORTED                 -1
> --
> 2.2.1
>
Arnd Bergmann Oct. 23, 2015, 10:23 a.m. UTC | #2
On Thursday 22 October 2015 15:07:06 Kevin Hilman wrote:
> Spam Status: Spamassassin    CRM114    
> On Wed, Jul 8, 2015 at 10:16 AM, Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com> wrote:
> > PSCI v1.0 augmented the power_state parameter format specification
> > (extended stateid) and introduced a way to probe it through the
> > PSCI_FEATURES interface.
> >
> > This patch implements code that detects the power_state format at
> > run-time through the PSCI_FEATURES interface, so that the power_state
> > argument can be properly detected and validated in the kernel according
> > to the information provided through firmware.
> >
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> 
> kernelci.org started finding a new boot failures in the arm-soc tree
> on arm64 qemu[1] and it was bisected down to this patch, which is in
> arm-soc in the form of commit a5c00bb28da0 (drivers: firmware: psci:
> add extended stateid power_state support)
> 
> The patch doesn't revert cleanly, so I didn't dig much further, but
> this suggests that some more testing on qemu is needed (or does qemu
> need to be upgraded?)
> 
> Kevin
> 
> [1] http://kernelci.org/boot/all/job/arm-soc/kernel/v4.3-rc5-557-g159ca7e43189/
> 

Could it be that qemu claims to support psci-1.0 but is actually not
compatible?

	Arnd
Lorenzo Pieralisi Oct. 23, 2015, 10:44 a.m. UTC | #3
On Fri, Oct 23, 2015 at 12:23:53PM +0200, Arnd Bergmann wrote:
> On Thursday 22 October 2015 15:07:06 Kevin Hilman wrote:
> > On Wed, Jul 8, 2015 at 10:16 AM, Lorenzo Pieralisi
> > <lorenzo.pieralisi@arm.com> wrote:
> > > PSCI v1.0 augmented the power_state parameter format specification
> > > (extended stateid) and introduced a way to probe it through the
> > > PSCI_FEATURES interface.
> > >
> > > This patch implements code that detects the power_state format at
> > > run-time through the PSCI_FEATURES interface, so that the power_state
> > > argument can be properly detected and validated in the kernel according
> > > to the information provided through firmware.
> > >
> > > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > > Cc: Mark Rutland <mark.rutland@arm.com>
> > 
> > kernelci.org started finding a new boot failures in the arm-soc tree
> > on arm64 qemu[1] and it was bisected down to this patch, which is in
> > arm-soc in the form of commit a5c00bb28da0 (drivers: firmware: psci:
> > add extended stateid power_state support)
> > 
> > The patch doesn't revert cleanly, so I didn't dig much further, but
> > this suggests that some more testing on qemu is needed (or does qemu
> > need to be upgraded?)
> > 
> > Kevin
> > 
> > [1] http://kernelci.org/boot/all/job/arm-soc/kernel/v4.3-rc5-557-g159ca7e43189/
> > 
> 
> Could it be that qemu claims to support psci-1.0 but is actually not
> compatible?

Yes, the problem is, PSCI functions that are not implemented must return
NOT_SUPPORTED according to the SMC calling convention and the PSCI
spec. The KVM implementation was not compliant and we patched the
kernel already:

commit e2d997366dc5b ("ARM: kvm: psci: fix handling of unimplemented
functions")

So the KVM PSCI implementation is fine now.

Problem with Qemu emulation is that it does not emulate the PSCI 1.0
specs correctly (it does not even consider PSCI 1.0 functions proper PSCI
calls), I tested it and I think we should update Qemu as we
did with KVM kernel code instead of working around it by dodging the
problem in the PSCI implementation by adding code that checks the
PSCI version before issuing the PSCI calls through the respective
conduit.

Thoughts appreciated.

Thanks,
Lorenzo
Arnd Bergmann Oct. 23, 2015, 10:55 a.m. UTC | #4
On Friday 23 October 2015 11:44:58 Lorenzo Pieralisi wrote:
> 
> Problem with Qemu emulation is that it does not emulate the PSCI 1.0
> specs correctly (it does not even consider PSCI 1.0 functions proper PSCI
> calls), I tested it and I think we should update Qemu as we
> did with KVM kernel code instead of working around it by dodging the
> problem in the PSCI implementation by adding code that checks the
> PSCI version before issuing the PSCI calls through the respective
> conduit.
> 
> Thoughts appreciated.

I think we really cannot break existing qemu installations, but need
a way to detect whether we are dealing with a broken qemu (and warn
about that) or with a working PSCI implementation.

Fixing qemu is of course a good idea, but it's not sufficient.

	Arnd
Lorenzo Pieralisi Oct. 23, 2015, 11:36 a.m. UTC | #5
On Fri, Oct 23, 2015 at 12:55:34PM +0200, Arnd Bergmann wrote:
> On Friday 23 October 2015 11:44:58 Lorenzo Pieralisi wrote:
> > 
> > Problem with Qemu emulation is that it does not emulate the PSCI 1.0
> > specs correctly (it does not even consider PSCI 1.0 functions proper PSCI
> > calls), I tested it and I think we should update Qemu as we
> > did with KVM kernel code instead of working around it by dodging the
> > problem in the PSCI implementation by adding code that checks the
> > PSCI version before issuing the PSCI calls through the respective
> > conduit.
> > 
> > Thoughts appreciated.
> 
> I think we really cannot break existing qemu installations, but need
> a way to detect whether we are dealing with a broken qemu (and warn
> about that) or with a working PSCI implementation.
> 
> Fixing qemu is of course a good idea, but it's not sufficient.

I will patch the PSCI back-end in the kernel to issue PSCI_FEATURES calls
only if the PSCI version detected is 1.0, therefore solving the issue, it
is not necessary according to the specs, but that's belt and braces
and sorts this niggle out.

I will send a patch shortly to be applied on top of arm-soc drivers/psci.

Thanks !
Lorenzo
Kevin Hilman Oct. 23, 2015, 3:10 p.m. UTC | #6
On Fri, Oct 23, 2015 at 4:36 AM, Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
> On Fri, Oct 23, 2015 at 12:55:34PM +0200, Arnd Bergmann wrote:
>> On Friday 23 October 2015 11:44:58 Lorenzo Pieralisi wrote:
>> >
>> > Problem with Qemu emulation is that it does not emulate the PSCI 1.0
>> > specs correctly (it does not even consider PSCI 1.0 functions proper PSCI
>> > calls), I tested it and I think we should update Qemu as we
>> > did with KVM kernel code instead of working around it by dodging the
>> > problem in the PSCI implementation by adding code that checks the
>> > PSCI version before issuing the PSCI calls through the respective
>> > conduit.
>> >
>> > Thoughts appreciated.
>>
>> I think we really cannot break existing qemu installations, but need
>> a way to detect whether we are dealing with a broken qemu (and warn
>> about that) or with a working PSCI implementation.
>>
>> Fixing qemu is of course a good idea, but it's not sufficient.
>
> I will patch the PSCI back-end in the kernel to issue PSCI_FEATURES calls
> only if the PSCI version detected is 1.0, therefore solving the issue, it
> is not necessary according to the specs, but that's belt and braces
> and sorts this niggle out.
>
> I will send a patch shortly to be applied on top of arm-soc drivers/psci.

Thanks!

In parallel, since you understandn better what qemu is/isn't doing,
can you ping the qemu folks about this bug?

Thanks,

Kevin
Lorenzo Pieralisi Oct. 26, 2015, 10:05 a.m. UTC | #7
On Fri, Oct 23, 2015 at 08:10:30AM -0700, Kevin Hilman wrote:
> On Fri, Oct 23, 2015 at 4:36 AM, Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com> wrote:
> > On Fri, Oct 23, 2015 at 12:55:34PM +0200, Arnd Bergmann wrote:
> >> On Friday 23 October 2015 11:44:58 Lorenzo Pieralisi wrote:
> >> >
> >> > Problem with Qemu emulation is that it does not emulate the PSCI 1.0
> >> > specs correctly (it does not even consider PSCI 1.0 functions proper PSCI
> >> > calls), I tested it and I think we should update Qemu as we
> >> > did with KVM kernel code instead of working around it by dodging the
> >> > problem in the PSCI implementation by adding code that checks the
> >> > PSCI version before issuing the PSCI calls through the respective
> >> > conduit.
> >> >
> >> > Thoughts appreciated.
> >>
> >> I think we really cannot break existing qemu installations, but need
> >> a way to detect whether we are dealing with a broken qemu (and warn
> >> about that) or with a working PSCI implementation.
> >>
> >> Fixing qemu is of course a good idea, but it's not sufficient.
> >
> > I will patch the PSCI back-end in the kernel to issue PSCI_FEATURES calls
> > only if the PSCI version detected is 1.0, therefore solving the issue, it
> > is not necessary according to the specs, but that's belt and braces
> > and sorts this niggle out.
> >
> > I will send a patch shortly to be applied on top of arm-soc drivers/psci.
> 
> Thanks!
> 
> In parallel, since you understandn better what qemu is/isn't doing,
> can you ping the qemu folks about this bug?

Yes, I will help them implement PSCI 1.0 support so that we can
upgrade smoothly.

Thanks Kevin !
Lorenzo
diff mbox

Patch

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 24ef3a8..bd2ba5b 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -75,14 +75,34 @@  static u32 psci_function_id[PSCI_FN_MAX];
 				PSCI_0_2_POWER_STATE_TYPE_MASK | \
 				PSCI_0_2_POWER_STATE_AFFL_MASK)
 
+#define PSCI_1_0_EXT_POWER_STATE_MASK		\
+				(PSCI_1_0_EXT_POWER_STATE_ID_MASK | \
+				PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
+
+static u32 psci_cpu_suspend_feature;
+
+static inline bool psci_has_ext_power_state(void)
+{
+	return psci_cpu_suspend_feature &
+				PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
+}
+
 bool psci_power_state_loses_context(u32 state)
 {
-	return state & PSCI_0_2_POWER_STATE_TYPE_MASK;
+	const u32 mask = psci_has_ext_power_state() ?
+					PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
+					PSCI_0_2_POWER_STATE_TYPE_MASK;
+
+	return state & mask;
 }
 
 bool psci_power_state_is_valid(u32 state)
 {
-	return !(state & ~PSCI_0_2_POWER_STATE_MASK);
+	const u32 valid_mask = psci_has_ext_power_state() ?
+			       PSCI_1_0_EXT_POWER_STATE_MASK :
+			       PSCI_0_2_POWER_STATE_MASK;
+
+	return !(state & ~valid_mask);
 }
 
 static int psci_to_linux_errno(int errno)
@@ -203,6 +223,14 @@  static int __init psci_features(u32 psci_func_id)
 			      psci_func_id, 0, 0);
 }
 
+static void __init psci_init_cpu_suspend(void)
+{
+	int feature = psci_features(psci_function_id[PSCI_FN_CPU_SUSPEND]);
+
+	if (feature != PSCI_RET_NOT_SUPPORTED)
+		psci_cpu_suspend_feature = feature;
+}
+
 /*
  * Detect the presence of a resident Trusted OS which may cause CPU_OFF to
  * return DENIED (which would be fatal).
@@ -287,6 +315,8 @@  static int __init psci_probe(void)
 
 	psci_init_migrate();
 
+	psci_init_cpu_suspend();
+
 	return 0;
 }
 
diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
index 187b828d..0a9485f 100644
--- a/include/uapi/linux/psci.h
+++ b/include/uapi/linux/psci.h
@@ -58,6 +58,13 @@ 
 #define PSCI_0_2_POWER_STATE_AFFL_MASK		\
 				(0x3 << PSCI_0_2_POWER_STATE_AFFL_SHIFT)
 
+/* PSCI extended power state encoding for CPU_SUSPEND function */
+#define PSCI_1_0_EXT_POWER_STATE_ID_MASK	0xfffffff
+#define PSCI_1_0_EXT_POWER_STATE_ID_SHIFT	0
+#define PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT	30
+#define PSCI_1_0_EXT_POWER_STATE_TYPE_MASK	\
+				(0x1 << PSCI_1_0_EXT_POWER_STATE_TYPE_SHIFT)
+
 /* PSCI v0.2 affinity level state returned by AFFINITY_INFO */
 #define PSCI_0_2_AFFINITY_LEVEL_ON		0
 #define PSCI_0_2_AFFINITY_LEVEL_OFF		1
@@ -78,6 +85,11 @@ 
 #define PSCI_VERSION_MINOR(ver)			\
 		((ver) & PSCI_VERSION_MINOR_MASK)
 
+/* PSCI features decoding (>=1.0) */
+#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT	1
+#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK	\
+			(0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
+
 /* PSCI return values (inclusive of all PSCI versions) */
 #define PSCI_RET_SUCCESS			0
 #define PSCI_RET_NOT_SUPPORTED			-1