Trap access to ICC_SRE_EL1 as well.

Bug: 132960440
Change-Id: I3e81ee7bc138f1c2fb411ec6b429b41b9ff630e5
diff --git a/src/arch/aarch64/cpu.c b/src/arch/aarch64/cpu.c
index 5993841..121f355 100644
--- a/src/arch/aarch64/cpu.c
+++ b/src/arch/aarch64/cpu.c
@@ -37,13 +37,19 @@
 {
 #if GIC_VERSION == 3 || GIC_VERSION == 4
 	uint32_t ich_hcr = 0;
+	uint32_t icc_sre_el2 =
+		(1u << 0) | /* SRE, enable ICH_* and ICC_* at EL2. */
+		(0x3 << 1); /* DIB and DFB, disable IRQ/FIQ bypass. */
 
-	if (!is_primary) {
+	if (is_primary) {
+		icc_sre_el2 |= 1u << 3; /* Enable EL1 access to ICC_SRE_EL1. */
+	} else {
 		/* Trap EL1 access to GICv3 system registers. */
 		ich_hcr =
 			(0x1fu << 10); /* TDIR, TSEI, TALL1, TALL0, TC bits. */
 	}
 	r->gic.ich_hcr_el2 = ich_hcr;
+	r->gic.icc_sre_el2 = icc_sre_el2;
 #endif
 }
 
diff --git a/src/arch/aarch64/hypervisor/exceptions.S b/src/arch/aarch64/hypervisor/exceptions.S
index 009dc83..6a8309f 100644
--- a/src/arch/aarch64/hypervisor/exceptions.S
+++ b/src/arch/aarch64/hypervisor/exceptions.S
@@ -322,7 +322,8 @@
 	add x2, x1, #VCPU_GIC
 
 	mrs x3, ich_hcr_el2
-	str x3, [x2, #16 * 0]
+	mrs x4, icc_sre_el2
+	stp x3, x4, [x2, #16 * 0]
 #endif
 
 	/* Save floating point registers. */
@@ -476,8 +477,9 @@
 	/* Offset is too large, so start from a new base. */
 	add x2, x0, #VCPU_GIC
 
-	ldr x3, [x2, #16 * 0]
+	ldp x3, x4, [x2, #16 * 0]
 	msr ich_hcr_el2, x3
+	msr icc_sre_el2, x4
 #endif
 
 	/*
diff --git a/src/arch/aarch64/inc/hf/arch/types.h b/src/arch/aarch64/inc/hf/arch/types.h
index f7a58c4..e4b3c3c 100644
--- a/src/arch/aarch64/inc/hf/arch/types.h
+++ b/src/arch/aarch64/inc/hf/arch/types.h
@@ -114,6 +114,7 @@
 #if GIC_VERSION == 3 || GIC_VERSION == 4
 	struct {
 		uintreg_t ich_hcr_el2;
+		uintreg_t icc_sre_el2;
 	} gic;
 #endif
 
diff --git a/test/vmapi/gicv3/gicv3.c b/test/vmapi/gicv3/gicv3.c
index 47923e0..e6e7435 100644
--- a/test/vmapi/gicv3/gicv3.c
+++ b/test/vmapi/gicv3/gicv3.c
@@ -109,3 +109,19 @@
 	run_res = hf_vcpu_run(SERVICE_VM0, 0);
 	EXPECT_EQ(run_res.code, HF_VCPU_RUN_ABORTED);
 }
+
+/*
+ * Check that an attempt by a secondary VM to write ICC_SRE_EL1 is trapped or
+ * ignored.
+ */
+TEST(system, icc_sre_write_trapped_secondary)
+{
+	struct hf_vcpu_run_return run_res;
+
+	EXPECT_EQ(hf_vm_configure(send_page_addr, recv_page_addr), 0);
+	SERVICE_SELECT(SERVICE_VM0, "write_systemreg_sre", send_buffer);
+
+	run_res = hf_vcpu_run(SERVICE_VM0, 0);
+	EXPECT_TRUE(run_res.code == HF_VCPU_RUN_ABORTED ||
+		    run_res.code == HF_VCPU_RUN_YIELD);
+}
diff --git a/test/vmapi/gicv3/services/systemreg.c b/test/vmapi/gicv3/services/systemreg.c
index 280493e..7535167 100644
--- a/test/vmapi/gicv3/services/systemreg.c
+++ b/test/vmapi/gicv3/services/systemreg.c
@@ -44,3 +44,17 @@
 	write_msr(ICC_CTLR_EL1, 0);
 	FAIL("Writing ICC_CTLR_EL1 didn't trap.");
 }
+
+TEST_SERVICE(write_systemreg_sre)
+{
+	ASSERT_EQ(read_msr(ICC_SRE_EL1), 0x7);
+	/*
+	 * Writing ICC_SRE_EL1 should either trap and abort the VM or be
+	 * ignored.
+	 */
+	write_msr(ICC_SRE_EL1, 0x0);
+	ASSERT_EQ(read_msr(ICC_SRE_EL1), 0x7);
+	write_msr(ICC_SRE_EL1, 0xffffffff);
+	ASSERT_EQ(read_msr(ICC_SRE_EL1), 0x7);
+	spci_yield();
+}