Optimize EL3 register state stored in cpu_context structure
authorSoby Mathew <soby.mathew@arm.com>
Fri, 4 Jul 2014 15:02:26 +0000 (16:02 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Thu, 31 Jul 2014 09:09:58 +0000 (10:09 +0100)
This patch further optimizes the EL3 register state stored in
cpu_context. The 2 registers which are removed from cpu_context are:

  * cntfrq_el0 is the system timer register which is writable
    only in EL3 and it can be programmed during cold/warm boot. Hence
    it need not be saved to cpu_context.

  * cptr_el3 controls access to Trace, Floating-point, and Advanced
    SIMD functionality and it is programmed every time during cold
    and warm boot. The current BL3-1 implementation does not need to
    modify the access controls during normal execution and hence
    they are expected to remain static.

Fixes ARM-software/tf-issues#197

Change-Id: I599ceee3b73a7dcfd37069fd41b60e3d397a7b18

bl31/aarch64/context.S
bl31/context_mgmt.c
include/bl31/context.h
include/bl31/context_mgmt.h
services/std_svc/psci/psci_afflvl_suspend.c

index 79b5d19cd6ae86f0b1a0e8fd0a8b14ecaabb1cc0..1117026d29846d4ef329cbf40713d672a8098a5d 100644 (file)
 #include <asm_macros.S>
 #include <context.h>
 
-/* -----------------------------------------------------
- * The following function strictly follows the AArch64
- * PCS to use x9-x17 (temporary caller-saved registers)
- * to save essential EL3 system register context. It
- * assumes that 'x0' is pointing to a 'el1_sys_regs'
- * structure where the register context will be saved.
- * -----------------------------------------------------
- */
-       .global el3_sysregs_context_save
-func el3_sysregs_context_save
-
-       mrs     x10, cptr_el3
-       mrs     x11, cntfrq_el0
-       stp     x10, x11, [x0, #CTX_CPTR_EL3]
-
-       ret
-
-/* -----------------------------------------------------
- * The following function strictly follows the AArch64
- * PCS to use x9-x17 (temporary caller-saved registers)
- * to restore essential EL3 system register context. It
- * assumes that 'x0' is pointing to a 'el1_sys_regs'
- * structure from where the register context will be
- * restored.
- *
- * Note that the sequence differs from that of the save
- * function as we want the MMU to be enabled last
- * -----------------------------------------------------
- */
-       .global el3_sysregs_context_restore
-func el3_sysregs_context_restore
-
-       ldp     x13, x14, [x0, #CTX_CPTR_EL3]
-       msr     cptr_el3, x13
-       msr     cntfrq_el0, x14
-       isb
-
-       ret
-
 /* -----------------------------------------------------
  * The following function strictly follows the AArch64
  * PCS to use x9-x17 (temporary caller-saved registers)
index 4502e5dcb86f62bc4079de0e2fea85f2fc6fa225..489d454444b7d1758a82d76d6c1428914735b6fa 100644 (file)
@@ -259,30 +259,10 @@ void cm_prepare_el3_exit(uint32_t security_state)
 }
 
 /*******************************************************************************
- * The next four functions are used by runtime services to save and restore EL3
- * and EL1 contexts on the 'cpu_context' structure for the specified security
+ * The next four functions are used by runtime services to save and restore
+ * EL1 context on the 'cpu_context' structure for the specified security
  * state.
  ******************************************************************************/
-void cm_el3_sysregs_context_save(uint32_t security_state)
-{
-       cpu_context_t *ctx;
-
-       ctx = cm_get_context(security_state);
-       assert(ctx);
-
-       el3_sysregs_context_save(get_el3state_ctx(ctx));
-}
-
-void cm_el3_sysregs_context_restore(uint32_t security_state)
-{
-       cpu_context_t *ctx;
-
-       ctx = cm_get_context(security_state);
-       assert(ctx);
-
-       el3_sysregs_context_restore(get_el3state_ctx(ctx));
-}
-
 void cm_el1_sysregs_context_save(uint32_t security_state)
 {
        cpu_context_t *ctx;
index 3bf498065e0ab6f952c3b24164643e127b5d162a..0dfebe0bbcc8056c0da90684064fae6ae8fb7718 100644 (file)
@@ -80,9 +80,7 @@
 #define CTX_RUNTIME_SP         0x8
 #define CTX_SPSR_EL3           0x10
 #define CTX_ELR_EL3            0x18
-#define CTX_CPTR_EL3           0x20
-#define CTX_CNTFRQ_EL0         0x28
-#define CTX_EL3STATE_END       0x30
+#define CTX_EL3STATE_END       0x20
 
 /*******************************************************************************
  * Constants that allow assembler code to access members of and the
@@ -323,8 +321,6 @@ CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
 /*******************************************************************************
  * Function prototypes
  ******************************************************************************/
-void el3_sysregs_context_save(el3_state_t *regs);
-void el3_sysregs_context_restore(el3_state_t *regs);
 void el1_sysregs_context_save(el1_sys_regs_t *regs);
 void el1_sysregs_context_restore(el1_sys_regs_t *regs);
 #if CTX_INCLUDE_FPREGS
index 6127b74bae415ee87caa34474a4aaf358db5e738..6e82fb70e879cd641b97a1297402e2244be9b848 100644 (file)
@@ -49,10 +49,8 @@ void cm_set_context_by_mpidr(uint64_t mpidr,
                             void *context,
                             uint32_t security_state);
 static inline void cm_set_context(void *context, uint32_t security_state);
-void cm_el3_sysregs_context_save(uint32_t security_state);
 void cm_init_context(uint64_t mpidr, const struct entry_point_info *ep);
 void cm_prepare_el3_exit(uint32_t security_state);
-void cm_el3_sysregs_context_restore(uint32_t security_state);
 void cm_el1_sysregs_context_save(uint32_t security_state);
 void cm_el1_sysregs_context_restore(uint32_t security_state);
 void cm_set_elr_el3(uint32_t security_state, uint64_t entrypoint);
index 1e60276c09c1016073a26094c8ab2fa52099e796..70f90a1511f8575f8341c97da2a58e2c05af39e4 100644 (file)
@@ -34,6 +34,7 @@
 #include <arch_helpers.h>
 #include <context.h>
 #include <context_mgmt.h>
+#include <platform.h>
 #include <runtime_svc.h>
 #include <stddef.h>
 #include "psci_private.h"
@@ -162,13 +163,6 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node,
        if (rc != PSCI_E_SUCCESS)
                return rc;
 
-       /*
-        * Arch. management: Save the EL3 state in the 'cpu_context'
-        * structure that has been allocated for this cpu, flush the
-        * L1 caches and exit intra-cluster coherency et al
-        */
-       cm_el3_sysregs_context_save(NON_SECURE);
-
        /* Set the secure world (EL3) re-entry point after BL1 */
        psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
 
@@ -414,6 +408,7 @@ static unsigned int psci_afflvl0_suspend_finish(aff_map_node_t *cpu_node)
 {
        unsigned int plat_state, state, rc;
        int32_t suspend_level;
+       uint64_t counter_freq;
 
        assert(cpu_node->level == MPIDR_AFFLVL0);
 
@@ -445,7 +440,10 @@ static unsigned int psci_afflvl0_suspend_finish(aff_map_node_t *cpu_node)
         * structure for this cpu.
         */
        psci_do_pwrup_cache_maintenance();
-       cm_el3_sysregs_context_restore(NON_SECURE);
+
+       /* Re-init the cntfrq_el0 register */
+       counter_freq = plat_get_syscnt_freq();
+       write_cntfrq_el0(counter_freq);
 
        /*
         * Call the cpu suspend finish handler registered by the Secure Payload