1 // © 2022 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #include <hyptypes.h>
6 
7 #include <hypconstants.h>
8 #include <hypregisters.h>
9 
10 #include <base.h>
11 #include <compiler.h>
12 #include <cpulocal.h>
13 #include <log.h>
14 #include <platform_cpu.h>
15 #include <preempt.h>
16 #include <trace.h>
17 #include <util.h>
18 
19 // FIXME:
20 #if !defined(MODULE_PLATFORM_SOC_QCOM)
21 // Platforms may override this with their own implementation
22 core_id_t WEAK
platform_cpu_get_coreid(MIDR_EL1_t midr)23 platform_cpu_get_coreid(MIDR_EL1_t midr)
24 {
25 	(void)midr;
26 	return CORE_ID_UNKNOWN;
27 }
28 #endif
29 
30 static core_id_t
get_core_id(uint16_t partnum,uint8_t variant,uint8_t revision)31 get_core_id(uint16_t partnum, uint8_t variant, uint8_t revision)
32 {
33 	static const core_id_info_t core_id_map[] = {
34 		{ .part_num = 0xD03U, .core_id = CORE_ID_CORTEX_A53 },
35 		{ .part_num = 0xD05U, .core_id = CORE_ID_CORTEX_A55 },
36 		{ .part_num = 0xD07U, .core_id = CORE_ID_CORTEX_A57 },
37 		{ .part_num = 0xD08U, .core_id = CORE_ID_CORTEX_A72 },
38 		{ .part_num = 0xD09U, .core_id = CORE_ID_CORTEX_A73 },
39 		{ .part_num = 0xD0AU, .core_id = CORE_ID_CORTEX_A75 },
40 		{ .part_num = 0xD0BU, .core_id = CORE_ID_CORTEX_A76 },
41 		{ .part_num = 0xD0CU, .core_id = CORE_ID_NEOVERSE_N1 },
42 		{ .part_num = 0xD0DU, .core_id = CORE_ID_CORTEX_A77 },
43 		{ .part_num = 0xD0EU, .core_id = CORE_ID_CORTEX_A76AE },
44 		{ .part_num = 0xD40U, .core_id = CORE_ID_NEOVERSE_V1 },
45 		{ .part_num = 0xD41U, .core_id = CORE_ID_CORTEX_A78 },
46 		{ .part_num = 0xD42U, .core_id = CORE_ID_CORTEX_A78AE },
47 		{ .part_num = 0xD44U, .core_id = CORE_ID_CORTEX_X1 },
48 		{ .part_num = 0xD46U, .core_id = CORE_ID_CORTEX_A510 },
49 		{ .part_num = 0xD47U, .core_id = CORE_ID_CORTEX_A710 },
50 		{ .part_num = 0xD48U, .core_id = CORE_ID_CORTEX_X2 },
51 		{ .part_num = 0xD49U, .core_id = CORE_ID_NEOVERSE_N2 },
52 		{ .part_num = 0xD4BU, .core_id = CORE_ID_CORTEX_A78C },
53 		{ .part_num = 0xD4DU, .core_id = CORE_ID_CORTEX_A715 },
54 		{ .part_num = 0xD4EU, .core_id = CORE_ID_CORTEX_X3 },
55 		{ .part_num = 0xD80U, .core_id = CORE_ID_CORTEX_A520 },
56 	};
57 	// List of cores that have specific revisions.
58 	// If multiple revisions are assigned different core IDs, then keep
59 	// them sorted by highest (variant_min,revision_min) first.
60 	static const core_id_rev_info_t core_id_rev_map[] = {
61 		{ .part_num	= 0xD81U,
62 		  .core_id	= CORE_ID_CORTEX_A720,
63 		  .variant_min	= 0,
64 		  .revision_min = 1 },
65 		{ .part_num	= 0xD82U,
66 		  .core_id	= CORE_ID_CORTEX_X4,
67 		  .variant_min	= 0,
68 		  .revision_min = 1 }
69 	};
70 
71 	core_id_t coreid;
72 	index_t	  i;
73 
74 	for (i = 0U; i < util_array_size(core_id_map); i++) {
75 		if (partnum == core_id_map[i].part_num) {
76 			coreid = core_id_map[i].core_id;
77 			goto out;
78 		}
79 	}
80 
81 	for (i = 0U; i < util_array_size(core_id_rev_map); i++) {
82 		if ((partnum == core_id_rev_map[i].part_num) ||
83 		    (variant > core_id_rev_map[i].variant_min) ||
84 		    ((variant == core_id_rev_map[i].variant_min) &&
85 		     (revision >= core_id_rev_map[i].revision_min))) {
86 			coreid = core_id_rev_map[i].core_id;
87 			goto out;
88 		}
89 	}
90 
91 	coreid = CORE_ID_UNKNOWN;
92 out:
93 	return coreid;
94 }
95 
96 core_id_t
get_current_core_id(void)97 get_current_core_id(void) REQUIRE_PREEMPT_DISABLED
98 {
99 	core_id_t coreid;
100 
101 	assert_cpulocal_safe();
102 
103 	MIDR_EL1_t midr = register_MIDR_EL1_read();
104 
105 	uint8_t	 implementer = MIDR_EL1_get_Implementer(&midr);
106 	uint16_t partnum     = MIDR_EL1_get_PartNum(&midr);
107 	uint8_t	 variant     = MIDR_EL1_get_Variant(&midr);
108 	uint8_t	 revision    = MIDR_EL1_get_Revision(&midr);
109 
110 	if ((char)implementer == 'A') {
111 		coreid = get_core_id(partnum, variant, revision);
112 	} else {
113 		coreid = CORE_ID_UNKNOWN;
114 	}
115 
116 	if (coreid == CORE_ID_UNKNOWN) {
117 		coreid = platform_cpu_get_coreid(midr);
118 	}
119 
120 #if defined(VERBOSE) && VERBOSE
121 	if (coreid == CORE_ID_UNKNOWN) {
122 		cpu_index_t cpu = cpulocal_get_index();
123 
124 		LOG(DEBUG, WARN,
125 		    "detected unknown core ID, cpu: {:d}, MIDR: {:#08x}", cpu,
126 		    MIDR_EL1_raw(midr));
127 	}
128 #endif
129 
130 	return coreid;
131 }
132