blob: 2f7a340c193c5a87d60a93eac449622a40ee530b [file] [log] [blame]
Manish Pandey0145ec32024-08-12 17:59:54 +01001/*
2 * Copyright (c) 2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
Manish Pandey0145ec32024-08-12 17:59:54 +01006#include <arch.h>
7#include <arch_helpers.h>
8#include <arm_arch_svc.h>
Arvind Ram Prakash81916212024-08-15 15:08:23 -05009#include <events.h>
10#include <plat_topology.h>
11#include <platform.h>
12#include <platform_def.h>
13#include <power_management.h>
14#include <psci.h>
Manish Pandey0145ec32024-08-12 17:59:54 +010015#include <smccc.h>
16#include <sync.h>
Arvind Ram Prakash81916212024-08-15 15:08:23 -050017#include <test_helpers.h>
Manish Pandey0145ec32024-08-12 17:59:54 +010018#include <tftf_lib.h>
Manish Pandey0145ec32024-08-12 17:59:54 +010019
Arvind Ram Prakash81916212024-08-15 15:08:23 -050020static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT];
21
22static volatile bool undef_injection_triggered;
23
24static unsigned int test_result;
25
26static bool trbe_trap_exception_handler(void)
27{
28 uint64_t esr_el2 = read_esr_el2();
29 if (EC_BITS(esr_el2) == EC_UNKNOWN) {
30 undef_injection_triggered = true;
31 return true;
32 }
33
34 return false;
35}
36
37/*
38 * Non-lead cpu function that checks if trblimitr_el1 is accessible,
39 * on affected cores this causes a undef injection and passes.In cores that
40 * are not affected test just passes. It fails in other cases.
41 */
42static test_result_t non_lead_cpu_fn(void)
43{
44 unsigned int mpid = read_mpidr_el1() & MPID_MASK;
45 unsigned int core_pos = platform_get_core_pos(mpid);
46 bool check_if_affected = is_trbe_errata_affected_core();
47
48 test_result = TEST_RESULT_SUCCESS;
49
50 /* Signal to the lead CPU that the calling CPU has entered the test */
51 tftf_send_event(&cpu_has_entered_test[core_pos]);
52
53 read_trblimitr_el1();
54
55 /* Ensure that EL3 still functional */
56 smc_args args;
57 smc_ret_values smc_ret;
58 memset(&args, 0, sizeof(args));
59 args.fid = SMCCC_VERSION;
60 smc_ret = tftf_smc(&args);
61
62 tftf_testcase_printf("SMCCC Version = %d.%d\n",
63 (int)((smc_ret.ret0 >> SMCCC_VERSION_MAJOR_SHIFT) & SMCCC_VERSION_MAJOR_MASK),
64 (int)((smc_ret.ret0 >> SMCCC_VERSION_MINOR_SHIFT) & SMCCC_VERSION_MINOR_MASK));
65
66 if (undef_injection_triggered == true && check_if_affected == true) {
67 test_result = TEST_RESULT_SUCCESS;
68 undef_injection_triggered = false;
69 tftf_testcase_printf("Undef injection triggered for core = %d\n", core_pos);
70 } else if(undef_injection_triggered == false && check_if_affected == false) {
71 test_result = TEST_RESULT_SUCCESS;
72 tftf_testcase_printf("TRB_LIMITR register accessible for core = %d\n", core_pos);
73 } else {
74 test_result = TEST_RESULT_FAIL;
75 }
76
77 return test_result;
78}
79
80/* This function kicks off non-lead cpus and the non-lead cpu function
81 * checks if errata is applied or not using the test.
82 */
Manish Pandey0145ec32024-08-12 17:59:54 +010083test_result_t test_asymmetric_features(void)
84{
Arvind Ram Prakash81916212024-08-15 15:08:23 -050085 unsigned int lead_mpid;
86 unsigned int cpu_mpid, cpu_node;
87 unsigned int core_pos;
88 int psci_ret;
89
90 undef_injection_triggered = false;
91
92 register_custom_sync_exception_handler(trbe_trap_exception_handler);
93
94 lead_mpid = read_mpidr_el1() & MPID_MASK;
95
96 SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
97
98 /* Power on all CPUs */
99 for_each_cpu(cpu_node) {
100 cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
101 /* Skip lead CPU as it is already powered on */
102 if (cpu_mpid == lead_mpid)
103 continue;
104
105 psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) non_lead_cpu_fn, 0);
106 if (psci_ret != PSCI_E_SUCCESS) {
107 tftf_testcase_printf(
108 "Failed to power on CPU 0x%x (%d)\n",
109 cpu_mpid, psci_ret);
110 return TEST_RESULT_SKIPPED;
111 }
112 }
113
114 /* Wait for non-lead CPUs to enter the test */
115 for_each_cpu(cpu_node) {
116 cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
117 /* Skip lead CPU */
118 if (cpu_mpid == lead_mpid)
119 continue;
120
121 core_pos = platform_get_core_pos(cpu_mpid);
122 tftf_wait_for_event(&cpu_has_entered_test[core_pos]);
123 if (test_result == TEST_RESULT_FAIL)
124 break;
125 }
126
127 unregister_custom_sync_exception_handler();
128
129 return test_result;
Manish Pandey0145ec32024-08-12 17:59:54 +0100130}