Move FPEXC32_EL2 to FP Context

The FPEXC32_EL2 register controls SIMD and FP functionality when the
lower ELs are executing in AArch32 mode. It is architecturally mapped
to AArch32 system register FPEXC.

This patch removes FPEXC32_EL2 register from the System Register context
and adds it to the floating-point context. EL3 only saves / restores the
floating-point context if the build option CTX_INCLUDE_FPREGS is set to 1.

The rationale for this change is that if the Secure world is using FP
functionality and EL3 is not managing the FP context, then the Secure
world will save / restore the appropriate FP registers.

NOTE - this is a break in behaviour in the unlikely case that
CTX_INCLUDE_FPREGS is set to 0 and the platform contains an AArch32
Secure Payload that modifies FPEXC, but does not save and restore
this register

Change-Id: Iab80abcbfe302752d52b323b4abcc334b585c184
Signed-off-by: David Cunado <david.cunado@arm.com>
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 34e4dcd..cf32b31 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -46,8 +46,7 @@
 		"tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
 		"mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
 		"vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
-		"cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0",\
-		"isr_el1", ""
+		"cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", ""
 
 panic_msg:
 	.asciz "PANIC in EL3 at x30 = 0x"
@@ -313,9 +312,8 @@
 	mrs	x15, cntv_cval_el0
 	bl	str_in_crash_buf_print
 	mrs	x8, cntkctl_el1
-	mrs	x9, fpexc32_el2
-	mrs	x10, sp_el0
-	mrs	x11, isr_el1
+	mrs	x9, sp_el0
+	mrs	x10, isr_el1
 	bl	str_in_crash_buf_print
 
 	/* Get the cpu specific registers to report */
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 7cc1970..c0ece0b 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -1144,7 +1144,6 @@
     cntv_ctl_el0    :0x0000000000000000
     cntv_cval_el0   :0x0000000000000000
     cntkctl_el1 :0x0000000000000000
-    fpexc32_el2 :0x0000000004000700
     sp_el0  :0x0000000004010780
 
 Guidelines for Reset Handlers
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index a89468d..cf06a64 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -100,8 +100,7 @@
 #define CTX_SPSR_FIQ		U(0xd8)
 #define CTX_DACR32_EL2		U(0xe0)
 #define CTX_IFSR32_EL2		U(0xe8)
-#define CTX_FP_FPEXC32_EL2	U(0xf0)
-#define CTX_TIMER_SYSREGS_OFF	U(0x100) /* Align to the next 16 byte boundary */
+#define CTX_TIMER_SYSREGS_OFF	U(0xf0) /* Align to the next 16 byte boundary */
 #else
 #define CTX_TIMER_SYSREGS_OFF	U(0xc0)  /* Align to the next 16 byte boundary */
 #endif /* __CTX_INCLUDE_AARCH32_REGS__ */
@@ -161,7 +160,12 @@
 #define CTX_FP_Q31		U(0x1f0)
 #define CTX_FP_FPSR		U(0x200)
 #define CTX_FP_FPCR		U(0x208)
-#define CTX_FPREGS_END		U(0x210)
+#if CTX_INCLUDE_AARCH32_REGS
+#define CTX_FP_FPEXC32_EL2	U(0x210)
+#define CTX_FPREGS_END		U(0x220) /* Align to the next 16 byte boundary */
+#else
+#define CTX_FPREGS_END		U(0x210) /* Align to the next 16 byte boundary */
+#endif
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index db16a9f..143da95 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -90,9 +90,6 @@
 	mrs	x15, dacr32_el2
 	mrs	x16, ifsr32_el2
 	stp	x15, x16, [x0, #CTX_DACR32_EL2]
-
-	mrs	x17, fpexc32_el2
-	str	x17, [x0, #CTX_FP_FPEXC32_EL2]
 #endif
 
 	/* Save NS timer registers if the build has instructed so */
@@ -212,9 +209,6 @@
 	ldp	x15, x16, [x0, #CTX_DACR32_EL2]
 	msr	dacr32_el2, x15
 	msr	ifsr32_el2, x16
-
-	ldr	x17, [x0, #CTX_FP_FPEXC32_EL2]
-	msr	fpexc32_el2, x17
 #endif
 	/* Restore NS timer registers if the build has instructed so */
 #if NS_TIMER_SWITCH
@@ -275,6 +269,10 @@
 	mrs	x10, fpcr
 	str	x10, [x0, #CTX_FP_FPCR]
 
+#if CTX_INCLUDE_AARCH32_REGS
+	mrs	x11, fpexc32_el2
+	str	x11, [x0, #CTX_FP_FPEXC32_EL2]
+#endif
 	ret
 endfunc fpregs_context_save
 
@@ -318,6 +316,10 @@
 	ldr	x10, [x0, #CTX_FP_FPCR]
 	msr	fpcr, x10
 
+#if CTX_INCLUDE_AARCH32_REGS
+	ldr	x11, [x0, #CTX_FP_FPEXC32_EL2]
+	msr	fpexc32_el2, x11
+#endif
 	/*
 	 * No explict ISB required here as ERET to
 	 * switch to secure EL1 or non-secure world