fix(serror): use custom argument for incrementing elr_elx
Add a custom argument to increment the elr_elx after handling SError.
In some cases, to prevent re-triggering the instruction, ELR needs
to be incremented by 4. In other cases, it may not be necessary.
This argument is passed to the handler, which then decides whether
to increment elr_elx by setting the passed argument accordingly after
handling the SError.
Change-Id: I404f3c5e24f894502a8d00c73649be0b2dd540fa
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/include/lib/aarch64/serror.h b/include/lib/aarch64/serror.h
index ac25f87..e6aa64f 100644
--- a/include/lib/aarch64/serror.h
+++ b/include/lib/aarch64/serror.h
@@ -7,8 +7,8 @@
#ifndef __SERROR_H__
#define __SERROR_H__
-typedef bool (*exception_handler_t)(void);
-void register_custom_serror_handler(exception_handler_t handler);
+typedef bool (*serr_exception_handler_t)(bool *incr_elr_elx);
+void register_custom_serror_handler(serr_exception_handler_t handler);
void unregister_custom_serror_handler(void);
#endif /* __SERROR_H__ */
diff --git a/lib/exceptions/aarch64/serror.c b/lib/exceptions/aarch64/serror.c
index 437c5d0..a57514b 100644
--- a/lib/exceptions/aarch64/serror.c
+++ b/lib/exceptions/aarch64/serror.c
@@ -9,9 +9,9 @@
#include <debug.h>
#include <serror.h>
-static exception_handler_t custom_serror_handler;
+static serr_exception_handler_t custom_serror_handler;
-void register_custom_serror_handler(exception_handler_t handler)
+void register_custom_serror_handler(serr_exception_handler_t handler)
{
custom_serror_handler = handler;
}
@@ -25,19 +25,15 @@
{
uint64_t elr_elx = IS_IN_EL2() ? read_elr_el2() : read_elr_el1();
bool resume = false;
+ bool incr_elr_elx = false;
if (custom_serror_handler == NULL) {
return false;
}
- resume = custom_serror_handler();
+ resume = custom_serror_handler(&incr_elr_elx);
- /*
- * TODO: if there is a test exepecting an Aync EA and expects to resume,
- * then there needs to be additional info from test handler as to whether
- * elr can be incremented or not.
- */
- if (resume) {
+ if (resume && incr_elr_elx) {
/* Move ELR to next instruction to allow tftf to continue */
if (IS_IN_EL2()) {
write_elr_el2(elr_elx + 4U);
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index cf9cce3..131f49b 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -202,10 +202,14 @@
return false;
}
-static bool realm_serror_handler_doublefault(void)
+static bool realm_serror_handler_doublefault(bool *incr_elr_elx)
{
+ *incr_elr_elx = false;
+
if ((read_sctlr2_el1() & SCTLR2_EASE_BIT) != 0UL) {
/* The serror exception should have been routed here */
+ *incr_elr_elx = true;
+
return true;
}
diff --git a/tftf/tests/misc_tests/test_ras_kfh.c b/tftf/tests/misc_tests/test_ras_kfh.c
index b38d6c4..f92e048 100644
--- a/tftf/tests/misc_tests/test_ras_kfh.c
+++ b/tftf/tests/misc_tests/test_ras_kfh.c
@@ -13,9 +13,10 @@
static volatile uint64_t serror_triggered;
extern void inject_unrecoverable_ras_error(void);
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
{
serror_triggered = 1;
+ *incr_elr_elx = false;
return true;
}
diff --git a/tftf/tests/misc_tests/test_ras_kfh_reflect.c b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
index d24fc47..eb93d72 100644
--- a/tftf/tests/misc_tests/test_ras_kfh_reflect.c
+++ b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
@@ -33,9 +33,10 @@
* One test each to verify reflection in sync and async exception.
*
*/
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
{
serror_triggered = 1;
+ *incr_elr_elx = false;
tftf_testcase_printf("SError event received.\n");
return true;
}