regression: Add test case 1035 for testing bti

Check that not having appropriate bti launchpads when using
br or blr results in exception getting generated.

Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
diff --git a/host/xtest/Makefile b/host/xtest/Makefile
index 0040914..ca861d4 100644
--- a/host/xtest/Makefile
+++ b/host/xtest/Makefile
@@ -127,6 +127,7 @@
 CFLAGS += -I../../ta/tpm_log_test/include
 CFLAGS += -I../../ta/large/include
 CFLAGS += -I../../ta/supp_plugin/include
+CFLAGS += -I../../ta/bti_test/include
 
 TA_DIR ?= /lib/optee_armtz
 CFLAGS += -DTA_DIR=\"$(TA_DIR)\"
diff --git a/host/xtest/regression_1000.c b/host/xtest/regression_1000.c
index 74101f0..5e68889 100644
--- a/host/xtest/regression_1000.c
+++ b/host/xtest/regression_1000.c
@@ -30,6 +30,7 @@
 #include <ta_sims_keepalive_test.h>
 #include <ta_concurrent.h>
 #include <ta_tpm_log_test.h>
+#include <ta_bti.h>
 #include <ta_supp_plugin.h>
 #include <sdp_basic.h>
 #include <pta_secstor_ta_mgmt.h>
@@ -2504,3 +2505,115 @@
 }
 ADBG_CASE_DEFINE(regression, 1034, xtest_tee_test_1034,
 		 "Test loading a large TA");
+
+struct bti_test {
+	uint32_t cmd;
+	uint32_t func;
+};
+
+#define BTI_TEST(caller_func, bti_func) {	\
+		.cmd = caller_func,		\
+		.func = bti_func,	\
+	}
+
+static const struct bti_test bti_cases_success[] = {
+	BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_C),
+	BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_JC),
+	BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_J),
+	BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_JC),
+	BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_C),
+	BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_J),
+	BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_JC),
+};
+
+static const struct bti_test bti_cases_panic[] = {
+	BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_J),
+	BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_NONE),
+	BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_C),
+	BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_NONE),
+	BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_NONE),
+};
+
+static void get_cpu_feature(bool *bti)
+{
+	TEEC_Session session = {};
+	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+	uint32_t ret_orig = 0;
+
+	op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE,
+					 TEEC_NONE);
+	xtest_teec_open_session(&session, &bti_test_ta_uuid, NULL, &ret_orig);
+
+	TEEC_InvokeCommand(&session, TA_BTI_FEATURE, &op, &ret_orig);
+
+	if(op.params[0].value.a)
+		*bti = true;
+
+	TEEC_CloseSession(&session);
+}
+
+static void xtest_tee_test_1035(ADBG_Case_t *c)
+{
+	TEEC_Session session = {};
+	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+	struct bti_test const *test = NULL;
+	uint32_t ret_orig = 0;
+	TEEC_Result res;
+	unsigned int n = 0;
+	bool cpu_feature_bti = false;
+
+	get_cpu_feature(&cpu_feature_bti);
+
+	op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE,
+					 TEEC_NONE);
+
+	xtest_teec_open_session(&session, &bti_test_ta_uuid, NULL, &ret_orig);
+
+	Do_ADBG_BeginSubCase(c, "BTI Pass Cases");
+	for (n = 0; n < ARRAY_SIZE(bti_cases_success); n++) {
+		test = &bti_cases_success[n];
+
+		Do_ADBG_BeginSubCase(c, "BTI Case %u", n);
+		op.params[0].value.a = test->func;
+
+		ADBG_EXPECT_TEEC_SUCCESS(c,
+			TEEC_InvokeCommand(&session, test->cmd, &op, &ret_orig));
+
+		Do_ADBG_EndSubCase(c, "BTI Case %u", n);
+	}
+	Do_ADBG_EndSubCase(c, "BTI Pass Cases");
+
+	TEEC_CloseSession(&session);
+
+	Do_ADBG_BeginSubCase(c, "BTI Exception Generation");
+	for (n = 0; n < ARRAY_SIZE(bti_cases_panic); n++) {
+		test = &bti_cases_panic[n];
+		res = TEEC_SUCCESS;
+
+#if defined(CFG_TA_BTI)
+		if (cpu_feature_bti)
+			res = TEEC_ERROR_TARGET_DEAD;
+#endif
+		xtest_teec_open_session(&session, &bti_test_ta_uuid,
+					NULL, &ret_orig);
+
+		Do_ADBG_BeginSubCase(c, "BTI Case %u", n);
+		op.params[0].value.a = test->func;
+
+		(void)ADBG_EXPECT_TEEC_RESULT(c, res,
+		       TEEC_InvokeCommand(&session, test->cmd, &op, &ret_orig));
+
+#if defined(CFG_TA_BTI)
+		if (cpu_feature_bti)
+			(void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE,
+							    ret_orig);
+#endif
+
+		Do_ADBG_EndSubCase(c, "BTI Case %u", n);
+
+		TEEC_CloseSession(&session);
+	}
+	Do_ADBG_EndSubCase(c, "BTI Exception Generation");
+
+}
+ADBG_CASE_DEFINE(regression, 1035, xtest_tee_test_1035, "Test BTI");
diff --git a/host/xtest/xtest_test.c b/host/xtest/xtest_test.c
index 7285dd8..5a3a7df 100644
--- a/host/xtest/xtest_test.c
+++ b/host/xtest/xtest_test.c
@@ -22,6 +22,7 @@
 #include <ta_storage.h>
 #include <ta_supp_plugin.h>
 #include <ta_tpm_log_test.h>
+#include <ta_bti.h>
 #include <tee_api_defines.h>
 #include <tee_client_api.h>
 #include <__tee_isocket_defines.h>
@@ -200,3 +201,4 @@
 const TEEC_UUID tpm_log_test_ta_uuid = TA_TPM_LOG_TEST_UUID;
 const TEEC_UUID supp_plugin_test_ta_uuid = TA_SUPP_PLUGIN_UUID;
 const TEEC_UUID large_ta_uuid = TA_LARGE_UUID;
+const TEEC_UUID bti_test_ta_uuid = TA_BTI_UUID;
diff --git a/host/xtest/xtest_test.h b/host/xtest/xtest_test.h
index 22ea877..bb083f7 100644
--- a/host/xtest/xtest_test.h
+++ b/host/xtest/xtest_test.h
@@ -135,6 +135,7 @@
 extern const TEEC_UUID tpm_log_test_ta_uuid;
 extern const TEEC_UUID supp_plugin_test_ta_uuid;
 extern const TEEC_UUID large_ta_uuid;
+extern const TEEC_UUID bti_test_ta_uuid;
 extern char *xtest_tee_name;
 
 #endif /*XTEST_TEST_H*/