fix(sve): save FPSR/FPCR as part of SVE support

SVE live state consists of Zn vector registers, predicate registers, FFR
and FPSR/FPCR registers. Latter were missed from save/restore
routine - this change intends to fix it.

Signed-off-by: Maksims Svecovs <maksims.svecovs@arm.com>
Change-Id: Ib59369b6e37797428a0cc07a2a0b06015331f981
diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S
index 2482d92..61e638d 100644
--- a/src/arch/aarch64/hypervisor/exceptions.S
+++ b/src/arch/aarch64/hypervisor/exceptions.S
@@ -435,6 +435,12 @@
 	 */
 
 other_world_loop:
+	/* Restore FP status and control registers. */
+	add x18, x19, #VCPU_FPSR
+	ldp x0, x1, [x18]
+	msr fpsr, x0
+	msr fpcr, x1
+
 	/* Check if SVE is implemented. */
 	mrs x0, id_aa64pfr0_el1
 	ubfx x0, x0, ID_AA64PFR0_SVE_SHIFT, ID_AA64PFR0_SVE_LENGTH
@@ -443,9 +449,6 @@
 	/* Restore the other world SIMD context to the other world VM vCPU. */
 	add x18, x19, #VCPU_FREGS
 	simd_op_vectors ldp, x18
-	ldp x0, x1, [x18]
-	msr fpsr, x0
-	msr fpcr, x1
 	b sve_skip_context_restore
 
 	/* Restore the other world SVE context from internal buffer. */
@@ -467,11 +470,11 @@
 	add x20, x18, #SVE_CTX_PREDICATES
 	sve_predicate_op ldr, x20
 
+sve_skip_context_restore:
 	/*
 	 * Prepare arguments from other world VM vCPU.
 	 * x19 holds the other world VM vCPU pointer.
 	 */
-sve_skip_context_restore:
 	ldp x0, x1, [x19, #VCPU_REGS + 8 * 0]
 	ldp x2, x3, [x19, #VCPU_REGS + 8 * 2]
 	ldp x4, x5, [x19, #VCPU_REGS + 8 * 4]
@@ -508,6 +511,12 @@
 	stp x4, x5, [x19, #VCPU_REGS + 8 * 4]
 	stp x6, x7, [x19, #VCPU_REGS + 8 * 6]
 
+	/* Save FP status and control registers. */
+	mrs x0, fpsr
+	mrs x1, fpcr
+	add x18, x19, #VCPU_FPSR
+	stp x0, x1, [x18]
+
 	/* Check if SVE is implemented. */
 	mrs x0, id_aa64pfr0_el1
 	ubfx x0, x0, ID_AA64PFR0_SVE_SHIFT, ID_AA64PFR0_SVE_LENGTH
@@ -516,9 +525,6 @@
 	/* Save the other world SIMD context to the other world VM vCPU. */
 	add x18, x19, #VCPU_FREGS
 	simd_op_vectors stp, x18
-	mrs x0, fpsr
-	mrs x1, fpcr
-	stp x0, x1, [x18]
 	b sve_skip_context_save
 
 	/* Save the other world SVE context to internal buffer. */
diff --git a/src/arch/aarch64/hypervisor/offsets.c b/src/arch/aarch64/hypervisor/offsets.c
index f09fa17..1f20447 100644
--- a/src/arch/aarch64/hypervisor/offsets.c
+++ b/src/arch/aarch64/hypervisor/offsets.c
@@ -21,6 +21,7 @@
 DEFINE_OFFSETOF(VCPU_REGS, struct vcpu, regs)
 DEFINE_OFFSETOF(VCPU_LAZY, struct vcpu, regs.lazy)
 DEFINE_OFFSETOF(VCPU_FREGS, struct vcpu, regs.fp)
+DEFINE_OFFSETOF(VCPU_FPSR, struct vcpu, regs.fpsr)
 #if BRANCH_PROTECTION
 DEFINE_OFFSETOF(VCPU_PAC, struct vcpu, regs.pac)
 #endif