Inject data/instruction abort exception instead of unknown reason
When the exception is caused by an instruction or data abort, inject it into
the EL1 instead of the (default) unknown reason. This gives the EL1 more
information and could help in handling or debugging these exceptions.
Bug: 147474217
Change-Id: I4db0c35322e2239ecde8b8144921c364d77bcc86
diff --git a/test/arch/mm_test.c b/test/arch/mm_test.c
index bf0c186..6ea8726 100644
--- a/test/arch/mm_test.c
+++ b/test/arch/mm_test.c
@@ -20,7 +20,7 @@
#include "test/hftest.h"
-/** There must be at least two levels in the page table. */
+/** There must be at least two levels in the page table. */
#define MAX_LEVEL_LOWER_BOUND 1
/**
diff --git a/test/inc/test/vmapi/exception_handler.h b/test/inc/test/vmapi/exception_handler.h
index 07ef312..47de143 100644
--- a/test/inc/test/vmapi/exception_handler.h
+++ b/test/inc/test/vmapi/exception_handler.h
@@ -20,7 +20,11 @@
bool exception_handler_skip_instruction(void);
-bool exception_handler_yield(void);
+bool exception_handler_yield_unknown(void);
+
+bool exception_handler_yield_data_abort(void);
+
+bool exception_handler_yield_instruction_abort(void);
int exception_handler_get_num(void);
diff --git a/test/vmapi/common/BUILD.gn b/test/vmapi/common/BUILD.gn
index 48be642..081c90e 100644
--- a/test/vmapi/common/BUILD.gn
+++ b/test/vmapi/common/BUILD.gn
@@ -21,4 +21,5 @@
"exception_handler.c",
"spci.c",
]
+ include_dirs = [ "//src/arch/aarch64" ]
}
diff --git a/test/vmapi/common/exception_handler.c b/test/vmapi/common/exception_handler.c
index c58a5b8..14fe1e1 100644
--- a/test/vmapi/common/exception_handler.c
+++ b/test/vmapi/common/exception_handler.c
@@ -19,6 +19,7 @@
#include "vmapi/hf/call.h"
#include "../msr.h"
+#include "sysregs.h"
#include "test/hftest.h"
/**
@@ -81,7 +82,7 @@
* EL1 exception handler to use in unit test VMs.
* Yields control back to the hypervisor and sends the number of exceptions.
*/
-bool exception_handler_yield(void)
+static bool exception_handler_yield(void)
{
dlog("%s function is triggered!\n", __func__);
++exception_handler_exception_count;
@@ -93,6 +94,42 @@
}
/**
+ * EL1 exception handler to use in unit test VMs.
+ * Yields control back to the hypervisor and sends the number of exceptions.
+ * Asserts that the Exception Class is Unknown.
+ */
+bool exception_handler_yield_unknown(void)
+{
+ uintreg_t esr_el1 = read_msr(ESR_EL1);
+ EXPECT_EQ(GET_ESR_EC(esr_el1), EC_UNKNOWN);
+ return exception_handler_yield();
+}
+
+/**
+ * EL1 exception handler to use in unit test VMs.
+ * Yields control back to the hypervisor and sends the number of exceptions.
+ * Asserts that the Exception Class is Data Abort (same EL).
+ */
+bool exception_handler_yield_data_abort(void)
+{
+ uintreg_t esr_el1 = read_msr(ESR_EL1);
+ EXPECT_EQ(GET_ESR_EC(esr_el1), EC_DATA_ABORT_SAME_EL);
+ return exception_handler_yield();
+}
+
+/**
+ * EL1 exception handler to use in unit test VMs.
+ * Yields control back to the hypervisor and sends the number of exceptions.
+ * Asserts that the Exception Class is Instruction Abort (same EL).
+ */
+bool exception_handler_yield_instruction_abort(void)
+{
+ uintreg_t esr_el1 = read_msr(ESR_EL1);
+ EXPECT_EQ(GET_ESR_EC(esr_el1), EC_INSTRUCTION_ABORT_SAME_EL);
+ return exception_handler_yield();
+}
+
+/**
* Returns the number of times the instruction handler was invoked.
*/
int exception_handler_get_num(void)
diff --git a/test/vmapi/primary_with_secondaries/services/boot.c b/test/vmapi/primary_with_secondaries/services/boot.c
index a7b9b66..6314c1b 100644
--- a/test/vmapi/primary_with_secondaries/services/boot.c
+++ b/test/vmapi/primary_with_secondaries/services/boot.c
@@ -55,7 +55,7 @@
TEST_SERVICE(boot_memory_underrun)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/*
* Try to read memory below the start of the image. This should result
* in the VM trapping and yielding.
@@ -66,7 +66,7 @@
TEST_SERVICE(boot_memory_overrun)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/*
* Try to read memory above the limit defined by memory_size. This
* should result in the VM trapping and yielding.
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index 38b292d..05272b1 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -80,7 +80,7 @@
SPCI_MEMORY_CACHE_WRITE_BACK, SPCI_MEMORY_OUTER_SHAREABLE);
EXPECT_EQ(spci_mem_donate(msg_size, msg_size, 0).func, SPCI_SUCCESS_32);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/* Try using the memory that isn't valid unless it's been returned. */
page[16] = 123;
@@ -103,7 +103,7 @@
SPCI_MEMORY_CACHE_WRITE_BACK, SPCI_MEMORY_OUTER_SHAREABLE);
EXPECT_EQ(spci_mem_lend(msg_size, msg_size, 0).func, SPCI_SUCCESS_32);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/* Try using the memory that isn't valid unless it's been returned. */
page[633] = 180;
@@ -113,7 +113,7 @@
TEST_SERVICE(spci_memory_return)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/* Loop, giving memory back to the sender. */
for (;;) {
@@ -167,7 +167,7 @@
TEST_SERVICE(spci_donate_check_upper_bound)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
for (;;) {
struct spci_value ret = spci_msg_wait();
@@ -200,7 +200,7 @@
TEST_SERVICE(spci_donate_check_lower_bound)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
for (;;) {
struct spci_value ret = spci_msg_wait();
@@ -248,7 +248,7 @@
EXPECT_EQ(ret.func, SPCI_MEM_DONATE_32);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
ptr = (uint8_t *)constituents[0].address;
@@ -371,7 +371,7 @@
TEST_SERVICE(spci_memory_lend_relinquish)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/* Loop, giving memory back to the sender. */
for (;;) {
@@ -540,7 +540,7 @@
*/
TEST_SERVICE(spci_memory_lend_relinquish_X)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_instruction_abort);
for (;;) {
struct spci_value ret = spci_msg_wait();
@@ -583,7 +583,7 @@
*/
TEST_SERVICE(spci_memory_lend_relinquish_RW)
{
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
for (;;) {
struct spci_value ret = spci_msg_wait();
@@ -652,7 +652,7 @@
EXPECT_EQ(ret.func, SPCI_MEM_LEND_32);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
/* Choose which constituent we want to test. */
index = *(uint8_t *)constituents[0].address;
@@ -680,7 +680,7 @@
struct spci_memory_region_constituent *constituents =
spci_memory_region_get_constituents(memory_region);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
EXPECT_EQ(ret.func, SPCI_MEM_LEND_32);
diff --git a/test/vmapi/primary_with_secondaries/services/unmapped.c b/test/vmapi/primary_with_secondaries/services/unmapped.c
index df00f6c..d4b323c 100644
--- a/test/vmapi/primary_with_secondaries/services/unmapped.c
+++ b/test/vmapi/primary_with_secondaries/services/unmapped.c
@@ -31,7 +31,7 @@
{
/* Not using NULL so static analysis doesn't complain. */
int *p = (int *)1;
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
*p = 12;
FAIL("Exception not generated by invalid access.");
}
@@ -48,7 +48,7 @@
ARRAY_SIZE(constituents), 0, 0, SPCI_MEMORY_RW_X,
SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
SPCI_MEMORY_OUTER_SHAREABLE);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_data_abort);
EXPECT_EQ(spci_mem_donate(msg_size, msg_size, 0).func, SPCI_SUCCESS_32);
@@ -60,7 +60,7 @@
{
/* Not using NULL so static analysis doesn't complain. */
int (*f)(void) = (int (*)(void))4;
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_instruction_abort);
f();
FAIL("Exception not generated by invalid access.");
}
@@ -85,7 +85,7 @@
SPCI_MEMORY_NORMAL_MEM, SPCI_MEMORY_CACHE_WRITE_BACK,
SPCI_MEMORY_OUTER_SHAREABLE);
- exception_setup(NULL, exception_handler_yield);
+ exception_setup(NULL, exception_handler_yield_instruction_abort);
EXPECT_EQ(spci_mem_donate(msg_size, msg_size, 0).func, SPCI_SUCCESS_32);