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