[Skiboot] [RFC] opal : Support for pre-entry and post-exit of stop state in opal
Gautham R Shenoy
ego at linux.vnet.ibm.com
Wed Apr 8 21:09:17 AEST 2020
Hi Abhishek,
On Fri, Apr 03, 2020 at 03:56:38AM -0500, Abhishek Goel wrote:
> This patch provides opal support for save restore of sprs in idle stop
> loop for LE opal. Opal support for stop states is needed to selectively
> enable stop states or to introduce a quirk quickly in case a buggy
> stop state is present.
> We make a opal call from kernel if firmware-stop-support for stop
> states is enabled. All the quirks for pre-entry of stop state is
> handled inside opal. A call from opal is made into kernel where we
> execute stop afer saving of NVGPRs.
> After waking up from 0x100 vector in kernel, we enter back into opal.
> All the quirks in post exit path, if any, are then handled in opal,
> from where we return successfully back to kernel.
> For deep stop states in which additional SPRs are lost, saving and
> restoration will be done in OPAL.
>
> This idea was first proposed by Nick here:
> https://patchwork.ozlabs.org/patch/1208159/
>
> Will combine this patch with the idle-stop versioning patch for BE
> opal proposed here : https://patchwork.ozlabs.org/patch/1249114/
> Signed-off-by: Abhishek Goel <huntbag at linux.vnet.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Since the patch originally came from Nicholas, his Signed-off-by
should be above yours. And since he is authored major portions of the
patch, Author credit should go to him.
> ---
> core/opal.c | 57 +++++++++++++++++++++++++++++++++++++++++
> hw/slw.c | 3 +++
> include/opal-api.h | 8 +++++-
> include/opal-internal.h | 10 ++++++++
> 4 files changed, 77 insertions(+), 1 deletion(-)
>
> diff --git a/core/opal.c b/core/opal.c
> index 64fdfe62..e7fa087c 100644
> --- a/core/opal.c
> +++ b/core/opal.c
> @@ -44,6 +44,7 @@ static uint64_t opal_dynamic_events;
> extern uint32_t attn_trigger;
> extern uint32_t hir_trigger;
>
> +struct os_ops os_ops;
>
> void opal_table_init(void)
> {
> @@ -422,6 +423,62 @@ void add_opal_node(void)
> memcons_add_properties();
> }
>
> +/*
> + * Function to register all the os operations in opal.
> + * Currently registering a os_ops that will handle idle stop
> + * saving and restoring of sprs in kernel.
> + */
> +static int64_t opal_register_os_ops(struct opal_os_ops *__os_ops)
> +{
> + struct cpu_thread *cpu;
> +
> + for_each_cpu(cpu) {
> + if (cpu == this_cpu())
> + continue;
> + if (cpu->state == cpu_state_os)
> + return OPAL_BUSY;
> + }
Why is this synchronization required?
> +
> + os_ops.os_idle_stop = (void *)be64_to_cpu(__os_ops->os_idle_stop);
> +
> + return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_REGISTER_OS_OPS, opal_register_os_ops, 1);
> +
> +/*
> + * Opal function to handle idle stop in kernel.
> + */
> +static uint64_t opal_cpu_idle(__be64 srr1_addr, uint64_t psscr)
> +{
> + u64 *le_srr1 = (u64 *)be64_to_cpu(srr1_addr);
> +
> + if (!os_ops.os_idle_stop)
> + return OPAL_UNSUPPORTED;
> +
> + if (proc_gen != proc_gen_p9)
> + return OPAL_UNSUPPORTED;
> +
> + /*
> + * This will contain all the kernel code or quirks which
> + * manages saving of sprs before entering into stop.
> + * Saving of Additional SPRs required for deep stop states will
> + * be done here.
> + */
> + if (!(psscr & (OPAL_PM_PSSCR_EC|OPAL_PM_PSSCR_ESL)))
> + *le_srr1 = os_ops.os_idle_stop(psscr, false);
> + else
> + *le_srr1 = os_ops.os_idle_stop(psscr, true);
Just curious.. Does this work with stop4/5 as well or only stop0-2 ?
> + /*
> + * This will contain all the kernel code or quirks which
> + * manages restoring of sprs after exiting from stop.
> + * Restoration of additional SPRs that are lost for deep stop
> + * states will be done here.
> + */
> +
> + return OPAL_SUCCESS;
> +}
> +opal_call(OPAL_CPU_IDLE, opal_cpu_idle, 2);
> +
> static struct lock evt_lock = LOCK_UNLOCKED;
>
> void opal_update_pending_evt(uint64_t evt_mask, uint64_t evt_values)
> diff --git a/hw/slw.c b/hw/slw.c
> index beb129a8..96e7152f 100644
> --- a/hw/slw.c
> +++ b/hw/slw.c
> @@ -958,6 +958,9 @@ void add_cpu_idle_state_properties(void)
> dt_add_property(power_mgt, "ibm,cpu-idle-state-psscr-mask",
> pm_ctrl_reg_mask_buf,
> num_supported_idle_states * sizeof(u64));
> + if (__BYTE_ORDER == __LITTLE_ENDIAN)
> + dt_add_property_string(power_mgt, "compatible",
> + "firmware-stop-supported");
This can be a dt_cpu_feature instead of another property under
power_mgt, no ?
> } else {
> dt_add_property(power_mgt, "ibm,cpu-idle-state-pmicr",
> pm_ctrl_reg_val_buf,
> diff --git a/include/opal-api.h b/include/opal-api.h
> index e90cab1e..a1e7d122 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -227,7 +227,9 @@
> #define OPAL_SECVAR_ENQUEUE_UPDATE 178
> #define OPAL_PHB_SET_OPTION 179
> #define OPAL_PHB_GET_OPTION 180
> -#define OPAL_LAST 180
> +#define OPAL_REGISTER_OS_OPS 181
> +#define OPAL_CPU_IDLE 182
> +#define OPAL_LAST 182
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> @@ -1255,6 +1257,10 @@ struct opal_mpipl_fadump {
> struct opal_mpipl_region region[];
> };
>
> +struct opal_os_ops {
> + __be64 os_idle_stop;
> +};
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* __OPAL_API_H */
> diff --git a/include/opal-internal.h b/include/opal-internal.h
> index f6ca7ac3..9368fb79 100644
> --- a/include/opal-internal.h
> +++ b/include/opal-internal.h
> @@ -18,6 +18,14 @@ struct opal_table_entry {
> u32 nargs;
> };
>
> +struct os_ops {
> + /*
> + * save_gprs help us distinguish between lite states and
> + * non-lite states.
> + */
> + int64_t (*os_idle_stop)(uint64_t psscr, bool save_gprs);
> +};
> +
> #ifdef __CHECKER__
> #define __opal_func_test_arg(__func, __nargs) 0
> #else
> @@ -75,6 +83,8 @@ extern void opal_run_pollers(void);
> extern void opal_add_host_sync_notifier(bool (*notify)(void *data), void *data);
> extern void opal_del_host_sync_notifier(bool (*notify)(void *data), void *data);
>
> +extern int64_t os_idle_stop(uint64_t psscr, bool save_gprs);
> +
> /*
> * Opal internal function prototype
> */
> --
> 2.17.1
>
More information about the Skiboot
mailing list