From a59caa4cbd03c394e7a5bf098ddd9db457b35aae Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Thu, 5 Dec 2013 14:21:04 +0000 Subject: [PATCH] psci: replace secure context with suspend context The secure context saved and restored across a cpu_suspend operation can be more than just the state of the secure system registers e.g. we also need to save the affinity level till which the cpu is being powered down. This patch creates a suspend_context data structure which includes the system register context. This will allow other bits to be saved and restored as well in subsequent patches. Change-Id: I1c1f7d25497388b54b7d6ee4fab77e8c6a9992c4 --- common/psci/psci_afflvl_suspend.c | 40 +++++++++++++++---------------- common/psci/psci_common.c | 4 ++-- common/psci/psci_private.h | 31 ++++++++++-------------- include/aarch64/arch.h | 17 +++++++++++++ 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/common/psci/psci_afflvl_suspend.c b/common/psci/psci_afflvl_suspend.c index d91b9210..6fb60f4a 100644 --- a/common/psci/psci_afflvl_suspend.c +++ b/common/psci/psci_afflvl_suspend.c @@ -73,16 +73,16 @@ static int psci_afflvl0_suspend(unsigned long mpidr, * Arch. management: Save the secure context, flush the * L1 caches and exit intra-cluster coherency et al */ - psci_secure_context[index].sctlr = read_sctlr(); - psci_secure_context[index].scr = read_scr(); - psci_secure_context[index].cptr = read_cptr(); - psci_secure_context[index].cpacr = read_cpacr(); - psci_secure_context[index].cntfrq = read_cntfrq_el0(); - psci_secure_context[index].mair = read_mair(); - psci_secure_context[index].tcr = read_tcr(); - psci_secure_context[index].ttbr = read_ttbr0(); - psci_secure_context[index].vbar = read_vbar(); - psci_secure_context[index].pstate = + psci_suspend_context[index].sec_sysregs.sctlr = read_sctlr(); + psci_suspend_context[index].sec_sysregs.scr = read_scr(); + psci_suspend_context[index].sec_sysregs.cptr = read_cptr(); + psci_suspend_context[index].sec_sysregs.cpacr = read_cpacr(); + psci_suspend_context[index].sec_sysregs.cntfrq = read_cntfrq_el0(); + psci_suspend_context[index].sec_sysregs.mair = read_mair(); + psci_suspend_context[index].sec_sysregs.tcr = read_tcr(); + psci_suspend_context[index].sec_sysregs.ttbr = read_ttbr0(); + psci_suspend_context[index].sec_sysregs.vbar = read_vbar(); + psci_suspend_context[index].sec_sysregs.pstate = read_daif() & (DAIF_ABT_BIT | DAIF_DBG_BIT); /* Set the secure world (EL3) re-entry point after BL1 */ @@ -411,18 +411,18 @@ static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr, * Arch. management: Restore the stashed secure architectural * context in the right order. */ - write_vbar(psci_secure_context[index].vbar); - write_daif(read_daif() | psci_secure_context[index].pstate); - write_mair(psci_secure_context[index].mair); - write_tcr(psci_secure_context[index].tcr); - write_ttbr0(psci_secure_context[index].ttbr); - write_sctlr(psci_secure_context[index].sctlr); + write_vbar(psci_suspend_context[index].sec_sysregs.vbar); + write_daif(read_daif() | psci_suspend_context[index].sec_sysregs.pstate); + write_mair(psci_suspend_context[index].sec_sysregs.mair); + write_tcr(psci_suspend_context[index].sec_sysregs.tcr); + write_ttbr0(psci_suspend_context[index].sec_sysregs.ttbr); + write_sctlr(psci_suspend_context[index].sec_sysregs.sctlr); /* MMU and coherency should be enabled by now */ - write_scr(psci_secure_context[index].scr); - write_cptr(psci_secure_context[index].cptr); - write_cpacr(psci_secure_context[index].cpacr); - write_cntfrq_el0(psci_secure_context[index].cntfrq); + write_scr(psci_suspend_context[index].sec_sysregs.scr); + write_cptr(psci_suspend_context[index].sec_sysregs.cptr); + write_cpacr(psci_suspend_context[index].sec_sysregs.cpacr); + write_cntfrq_el0(psci_suspend_context[index].sec_sysregs.cntfrq); /* * Generic management: Now we just need to retrieve the diff --git a/common/psci/psci_common.c b/common/psci/psci_common.c index 969d33c9..705c5d71 100644 --- a/common/psci/psci_common.c +++ b/common/psci/psci_common.c @@ -41,10 +41,10 @@ /******************************************************************************* * Arrays that contains information needs to resume a cpu's execution when woken * out of suspend or off states. 'psci_ns_einfo_idx' keeps track of the next - * free index in the 'psci_ns_entry_info' & 'psci_secure_context' arrays. Each + * free index in the 'psci_ns_entry_info' & 'psci_suspend_context' arrays. Each * cpu is allocated a single entry in each array during startup. ******************************************************************************/ -secure_context psci_secure_context[PSCI_NUM_AFFS]; +suspend_context psci_suspend_context[PSCI_NUM_AFFS]; ns_entry_info psci_ns_entry_info[PSCI_NUM_AFFS]; unsigned int psci_ns_einfo_idx; diff --git a/common/psci/psci_private.h b/common/psci/psci_private.h index 75451676..8016ad29 100644 --- a/common/psci/psci_private.h +++ b/common/psci/psci_private.h @@ -31,6 +31,7 @@ #ifndef __PSCI_PRIVATE_H__ #define __PSCI_PRIVATE_H__ +#include #include #ifndef __ASSEMBLY__ @@ -50,23 +51,6 @@ typedef struct { unsigned int sctlr; } ns_entry_info; -/******************************************************************************* - * - * - ******************************************************************************/ -typedef struct { - unsigned long sctlr; - unsigned long scr; - unsigned long cptr; - unsigned long cpacr; - unsigned long cntfrq; - unsigned long mair; - unsigned long tcr; - unsigned long ttbr; - unsigned long vbar; - unsigned long pstate; -} secure_context; - /******************************************************************************* * The following two data structures hold the topology tree which in turn tracks * the state of the all the affinity instances supported by the platform. @@ -84,6 +68,17 @@ typedef struct { int max; } aff_limits_node; +/******************************************************************************* + * This data structure holds secure world context that needs to be preserved + * across cpu_suspend calls which enter the power down state. + ******************************************************************************/ +typedef struct { + /* Align the suspend level to allow per-cpu lockless access */ + int suspend_level + __attribute__((__aligned__(CACHE_WRITEBACK_GRANULE))); + sysregs_context sec_sysregs; +} suspend_context; + typedef aff_map_node *mpidr_aff_map_nodes[MPIDR_MAX_AFFLVL]; typedef unsigned int (*afflvl_power_on_finisher)(unsigned long, aff_map_node *); @@ -91,7 +86,7 @@ typedef unsigned int (*afflvl_power_on_finisher)(unsigned long, /******************************************************************************* * Data prototypes ******************************************************************************/ -extern secure_context psci_secure_context[PSCI_NUM_AFFS]; +extern suspend_context psci_suspend_context[PSCI_NUM_AFFS]; extern ns_entry_info psci_ns_entry_info[PSCI_NUM_AFFS]; extern unsigned int psci_ns_einfo_idx; extern aff_limits_node psci_aff_limits[MPIDR_MAX_AFFLVL + 1]; diff --git a/include/aarch64/arch.h b/include/aarch64/arch.h index bcde2432..10d2adb7 100644 --- a/include/aarch64/arch.h +++ b/include/aarch64/arch.h @@ -313,6 +313,23 @@ #ifndef __ASSEMBLY__ +/******************************************************************************* + * The following data structure holds the system register context across cpu + * save/restore operations + ******************************************************************************/ +typedef struct { + unsigned long sctlr; + unsigned long scr; + unsigned long cptr; + unsigned long cpacr; + unsigned long cntfrq; + unsigned long mair; + unsigned long tcr; + unsigned long ttbr; + unsigned long vbar; + unsigned long pstate; +} sysregs_context; + /******************************************************************************* * Function prototypes ******************************************************************************/ -- 2.30.2