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();
+}