Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 1 | #include <stdint.h> |
| 2 | #include <stddef.h> |
| 3 | #include <stdlib.h> |
| 4 | #include <string.h> |
| 5 | #include <errno.h> |
| 6 | |
| 7 | #include <sched.h> |
| 8 | |
| 9 | #include <cpuinfo.h> |
| 10 | #include <x86/api.h> |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 11 | #include <gpu/api.h> |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 12 | #include <linux/api.h> |
| 13 | #include <api.h> |
| 14 | #include <log.h> |
| 15 | |
| 16 | |
| 17 | static inline uint32_t max(uint32_t a, uint32_t b) { |
| 18 | return a > b ? a : b; |
| 19 | } |
| 20 | |
Marat Dukhan | 77eb941 | 2017-03-04 21:01:16 -0500 | [diff] [blame] | 21 | static inline uint32_t bit_mask(uint32_t bits) { |
| 22 | return (UINT32_C(1) << bits) - UINT32_C(1); |
| 23 | } |
| 24 | |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 25 | static int cmp_x86_processor_by_apic_id(const void* processor_a, const void* processor_b) { |
| 26 | const uint32_t id_a = ((const struct cpuinfo_x86_processor*) processor_a)->topology.apic_id; |
| 27 | const uint32_t id_b = ((const struct cpuinfo_x86_processor*) processor_b)->topology.apic_id; |
| 28 | |
| 29 | if (id_a < id_b) { |
| 30 | return -1; |
| 31 | } else { |
| 32 | return id_a > id_b; |
| 33 | } |
| 34 | } |
| 35 | |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 36 | static void cpuinfo_x86_count_objects( |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 37 | const struct cpuinfo_x86_processor* processors, |
| 38 | uint32_t processors_count, |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 39 | uint32_t cores_count_ptr[restrict static 1], |
| 40 | uint32_t packages_count_ptr[restrict static 1], |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 41 | uint32_t l1i_count_ptr[restrict static 1], |
| 42 | uint32_t l1d_count_ptr[restrict static 1], |
| 43 | uint32_t l2_count_ptr[restrict static 1], |
| 44 | uint32_t l3_count_ptr[restrict static 1], |
| 45 | uint32_t l4_count_ptr[restrict static 1]) |
| 46 | { |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 47 | uint32_t cores_count = 0, packages_count = 0; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 48 | uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 49 | uint32_t last_core_id = UINT32_MAX, last_package_id = UINT32_MAX; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 50 | uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX; |
| 51 | uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX; |
| 52 | for (uint32_t i = 0; i < processors_count; i++) { |
| 53 | const uint32_t apic_id = processors[i].topology.apic_id; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 54 | const uint32_t core_id = |
| 55 | (apic_id >> processors[i].topology.core_bits_offset) & ~bit_mask(processors[i].topology.core_bits_length); |
| 56 | if (core_id != last_core_id) { |
| 57 | last_core_id = core_id; |
| 58 | cores_count++; |
| 59 | } |
| 60 | const uint32_t package_id = apic_id >> |
| 61 | max(processors[i].topology.core_bits_offset + processors[i].topology.core_bits_length, |
| 62 | processors[i].topology.thread_bits_offset + processors[i].topology.thread_bits_length); |
| 63 | if (package_id != last_package_id) { |
| 64 | last_package_id = package_id; |
| 65 | packages_count++; |
| 66 | } |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 67 | if (processors[i].cache.l1i.size != 0) { |
| 68 | const uint32_t l1i_id = apic_id & ~bit_mask(processors[i].cache.l1i.apic_bits); |
| 69 | if (l1i_id != last_l1i_id) { |
| 70 | last_l1i_id = l1i_id; |
| 71 | l1i_count++; |
| 72 | } |
| 73 | } |
| 74 | if (processors[i].cache.l1d.size != 0) { |
| 75 | const uint32_t l1d_id = apic_id & ~bit_mask(processors[i].cache.l1d.apic_bits); |
| 76 | if (l1d_id != last_l1d_id) { |
| 77 | last_l1d_id = l1d_id; |
| 78 | l1d_count++; |
| 79 | } |
| 80 | } |
| 81 | if (processors[i].cache.l2.size != 0) { |
| 82 | const uint32_t l2_id = apic_id & ~bit_mask(processors[i].cache.l2.apic_bits); |
| 83 | if (l2_id != last_l2_id) { |
| 84 | last_l2_id = l2_id; |
| 85 | l2_count++; |
| 86 | } |
| 87 | } |
| 88 | if (processors[i].cache.l3.size != 0) { |
| 89 | const uint32_t l3_id = apic_id & ~bit_mask(processors[i].cache.l3.apic_bits); |
| 90 | if (l3_id != last_l3_id) { |
| 91 | last_l3_id = l3_id; |
| 92 | l3_count++; |
| 93 | } |
| 94 | } |
| 95 | if (processors[i].cache.l4.size != 0) { |
| 96 | const uint32_t l4_id = apic_id & ~bit_mask(processors[i].cache.l4.apic_bits); |
| 97 | if (l4_id != last_l4_id) { |
| 98 | last_l4_id = l4_id; |
| 99 | l4_count++; |
| 100 | } |
| 101 | } |
| 102 | } |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 103 | *cores_count_ptr = cores_count; |
| 104 | *packages_count_ptr = packages_count; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 105 | *l1i_count_ptr = l1i_count; |
| 106 | *l1d_count_ptr = l1d_count; |
| 107 | *l2_count_ptr = l2_count; |
| 108 | *l3_count_ptr = l3_count; |
| 109 | *l4_count_ptr = l4_count; |
| 110 | } |
| 111 | |
Marat Dukhan | a8fb3dd | 2017-08-09 13:49:39 -0700 | [diff] [blame] | 112 | static bool cpuinfo_x86_linux_cpulist_callback(uint32_t cpulist_start, uint32_t cpulist_end, void* context) { |
| 113 | cpu_set_t* cpuset = (cpu_set_t*) context; |
| 114 | for (uint32_t cpu = cpulist_start; cpu < cpulist_end; cpu++) { |
| 115 | CPU_SET((int) cpu, cpuset); |
| 116 | } |
| 117 | return true; |
| 118 | } |
| 119 | |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 120 | void cpuinfo_x86_linux_init(void) { |
| 121 | struct cpuinfo_x86_processor* x86_processors = NULL; |
| 122 | struct cpuinfo_processor* processors = NULL; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 123 | struct cpuinfo_package* packages = NULL; |
| 124 | struct cpuinfo_core* cores = NULL; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 125 | struct cpuinfo_cache* l1i = NULL; |
| 126 | struct cpuinfo_cache* l1d = NULL; |
| 127 | struct cpuinfo_cache* l2 = NULL; |
| 128 | struct cpuinfo_cache* l3 = NULL; |
| 129 | struct cpuinfo_cache* l4 = NULL; |
| 130 | |
| 131 | cpu_set_t old_affinity; |
| 132 | if (sched_getaffinity(0, sizeof(cpu_set_t), &old_affinity) != 0) { |
| 133 | cpuinfo_log_error("sched_getaffinity failed: %s", strerror(errno)); |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | cpu_set_t present_set; |
Marat Dukhan | a8fb3dd | 2017-08-09 13:49:39 -0700 | [diff] [blame] | 138 | CPU_ZERO(&present_set); |
| 139 | cpuinfo_linux_parse_cpulist("/sys/devices/system/cpu/present", cpuinfo_x86_linux_cpulist_callback, &present_set); |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 140 | |
| 141 | cpu_set_t possible_set; |
Marat Dukhan | a8fb3dd | 2017-08-09 13:49:39 -0700 | [diff] [blame] | 142 | CPU_ZERO(&possible_set); |
| 143 | cpuinfo_linux_parse_cpulist("/sys/devices/system/cpu/possible", cpuinfo_x86_linux_cpulist_callback, &possible_set); |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 144 | |
| 145 | cpu_set_t processors_set; |
| 146 | CPU_AND(&processors_set, &present_set, &possible_set); |
| 147 | const uint32_t processors_count = (uint32_t) CPU_COUNT(&processors_set); |
| 148 | cpuinfo_log_debug("detected %"PRIu32" logical processors", processors_count); |
| 149 | |
| 150 | x86_processors = calloc(processors_count, sizeof(struct cpuinfo_x86_processor)); |
| 151 | if (x86_processors == NULL) { |
| 152 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %d x86 logical processors", |
| 153 | processors_count * sizeof(struct cpuinfo_x86_processor), processors_count); |
| 154 | goto cleanup; |
| 155 | } |
| 156 | |
| 157 | int processor_bit = 0; |
| 158 | for (int i = 0; i < processors_count; i++, processor_bit++) { |
| 159 | while (!CPU_ISSET(processor_bit, &processors_set)) { |
| 160 | processor_bit++; |
| 161 | } |
| 162 | cpu_set_t processor_set; |
| 163 | CPU_ZERO(&processor_set); |
| 164 | CPU_SET(processor_bit, &processor_set); |
| 165 | if (sched_setaffinity(0, sizeof(cpu_set_t), &processor_set) != 0) { |
| 166 | cpuinfo_log_error("sched_setaffinity for processor %d (bit %d) failed: %s", |
| 167 | i, processor_bit, strerror(errno)); |
| 168 | goto cleanup; |
| 169 | } |
| 170 | |
| 171 | cpuinfo_x86_init_processor(&x86_processors[i]); |
Marat Dukhan | 15e1df9 | 2017-09-13 11:10:10 -0700 | [diff] [blame] | 172 | x86_processors[i].linux_id = processor_bit; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | qsort(x86_processors, (size_t) processors_count, sizeof(struct cpuinfo_x86_processor), |
| 176 | cmp_x86_processor_by_apic_id); |
| 177 | |
| 178 | processors = calloc((size_t) processors_count, sizeof(struct cpuinfo_processor)); |
| 179 | if (processors == NULL) { |
| 180 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %d logical processors", |
| 181 | (size_t) processors_count * sizeof(struct cpuinfo_processor), processors_count); |
| 182 | goto cleanup; |
| 183 | } |
| 184 | |
| 185 | for (uint32_t i = 0; i < (uint32_t) processors_count; i++) { |
Marat Dukhan | 15e1df9 | 2017-09-13 11:10:10 -0700 | [diff] [blame] | 186 | processors[i].vendor = x86_processors[i].vendor; |
| 187 | processors[i].uarch = x86_processors[i].uarch; |
| 188 | processors[i].linux_id = x86_processors[i].linux_id; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 189 | |
| 190 | /* Initialize topology information */ |
| 191 | const uint32_t apic_id = x86_processors[i].topology.apic_id; |
| 192 | const uint32_t thread_mask = bit_mask(x86_processors[i].topology.thread_bits_length); |
| 193 | const uint32_t core_mask = bit_mask(x86_processors[i].topology.core_bits_length); |
| 194 | const uint32_t package_offset = max( |
| 195 | x86_processors[i].topology.thread_bits_offset, |
| 196 | x86_processors[i].topology.core_bits_offset); |
| 197 | processors[i].topology = (struct cpuinfo_topology) { |
| 198 | .thread_id = (apic_id >> x86_processors[i].topology.thread_bits_offset) & thread_mask, |
| 199 | .core_id = (apic_id >> x86_processors[i].topology.core_bits_offset) & core_mask, |
| 200 | .package_id = apic_id >> package_offset, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 201 | .apic_id = x86_processors[i].topology.apic_id, |
| 202 | }; |
| 203 | } |
| 204 | |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 205 | uint32_t packages_count = 0, cores_count = 0; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 206 | uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 207 | cpuinfo_x86_count_objects(x86_processors, processors_count, |
| 208 | &packages_count, &cores_count, &l1i_count, &l1d_count, &l2_count, &l3_count, &l4_count); |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 209 | |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 210 | cpuinfo_log_debug("detected %"PRIu32" cores caches", cores_count); |
| 211 | cpuinfo_log_debug("detected %"PRIu32" packages caches", packages_count); |
| 212 | cpuinfo_log_debug("detected %"PRIu32" L1I caches", l1i_count); |
| 213 | cpuinfo_log_debug("detected %"PRIu32" L1D caches", l1d_count); |
| 214 | cpuinfo_log_debug("detected %"PRIu32" L2 caches", l2_count); |
| 215 | cpuinfo_log_debug("detected %"PRIu32" L3 caches", l3_count); |
| 216 | cpuinfo_log_debug("detected %"PRIu32" L4 caches", l4_count); |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 217 | |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 218 | cores = calloc(cores_count, sizeof(struct cpuinfo_core)); |
| 219 | if (cores == NULL) { |
| 220 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores", |
| 221 | cores_count * sizeof(struct cpuinfo_core), cores_count); |
| 222 | goto cleanup; |
| 223 | } |
| 224 | packages = calloc(packages_count, sizeof(struct cpuinfo_package)); |
| 225 | if (packages == NULL) { |
| 226 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores", |
| 227 | packages_count * sizeof(struct cpuinfo_package), packages_count); |
| 228 | goto cleanup; |
| 229 | } |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 230 | if (l1i_count != 0) { |
| 231 | l1i = calloc(l1i_count, sizeof(struct cpuinfo_cache)); |
| 232 | if (l1i == NULL) { |
| 233 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1I caches", |
| 234 | l1i_count * sizeof(struct cpuinfo_cache), l1i_count); |
| 235 | goto cleanup; |
| 236 | } |
| 237 | } |
| 238 | if (l1d_count != 0) { |
| 239 | l1d = calloc(l1d_count, sizeof(struct cpuinfo_cache)); |
| 240 | if (l1d == NULL) { |
| 241 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1D caches", |
| 242 | l1d_count * sizeof(struct cpuinfo_cache), l1d_count); |
| 243 | goto cleanup; |
| 244 | } |
| 245 | } |
| 246 | if (l2_count != 0) { |
| 247 | l2 = calloc(l2_count, sizeof(struct cpuinfo_cache)); |
| 248 | if (l2 == NULL) { |
| 249 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L2 caches", |
| 250 | l2_count * sizeof(struct cpuinfo_cache), l2_count); |
| 251 | goto cleanup; |
| 252 | } |
| 253 | } |
| 254 | if (l3_count != 0) { |
| 255 | l3 = calloc(l3_count, sizeof(struct cpuinfo_cache)); |
| 256 | if (l3 == NULL) { |
| 257 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L3 caches", |
| 258 | l3_count * sizeof(struct cpuinfo_cache), l3_count); |
| 259 | goto cleanup; |
| 260 | } |
| 261 | } |
| 262 | if (l4_count != 0) { |
| 263 | l4 = calloc(l4_count, sizeof(struct cpuinfo_cache)); |
| 264 | if (l4 == NULL) { |
| 265 | cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L4 caches", |
| 266 | l4_count * sizeof(struct cpuinfo_cache), l4_count); |
| 267 | goto cleanup; |
| 268 | } |
| 269 | } |
| 270 | |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 271 | uint32_t core_index = UINT32_MAX, package_index = UINT32_MAX; |
| 272 | uint32_t l1i_index = UINT32_MAX, l1d_index = UINT32_MAX, l2_index = UINT32_MAX, l3_index = UINT32_MAX, l4_index = UINT32_MAX; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 273 | uint32_t last_core_id = UINT32_MAX, last_package_id = UINT32_MAX; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 274 | uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX; |
| 275 | uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX; |
| 276 | for (uint32_t i = 0; i < processors_count; i++) { |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 277 | const uint32_t apic_id = x86_processors[i].topology.apic_id; |
| 278 | const uint32_t core_id = |
| 279 | (apic_id >> x86_processors[i].topology.core_bits_offset) & ~bit_mask(x86_processors[i].topology.core_bits_length); |
| 280 | uint32_t new_core = 0; |
| 281 | if (core_id != last_core_id) { |
| 282 | /* new core */ |
| 283 | new_core = 1; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 284 | cores[++core_index] = (struct cpuinfo_core) { |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 285 | .processor_start = i, |
| 286 | .processor_count = 1, |
| 287 | }; |
| 288 | last_core_id = core_id; |
| 289 | } else { |
| 290 | /* another logical processor on the same core */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 291 | cores[core_index].processor_count++; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | const uint32_t package_id = apic_id >> |
| 295 | max(x86_processors[i].topology.core_bits_offset + x86_processors[i].topology.core_bits_length, |
| 296 | x86_processors[i].topology.thread_bits_offset + x86_processors[i].topology.thread_bits_length); |
| 297 | if (package_id != last_package_id) { |
| 298 | /* new package */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 299 | packages[++package_index] = (struct cpuinfo_package) { |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 300 | .processor_start = i, |
| 301 | .processor_count = 1, |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 302 | .core_start = core_index, |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 303 | .core_count = 1, |
| 304 | }; |
| 305 | const uint32_t brand_string_length = cpuinfo_x86_normalize_brand_string(x86_processors[i].brand_string); |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 306 | memcpy(packages[package_index].name, x86_processors[i].brand_string, brand_string_length); |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 307 | if (brand_string_length < CPUINFO_PACKAGE_NAME_MAX) { |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 308 | packages[package_index].name[brand_string_length] = '\0'; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 309 | } |
| 310 | last_package_id = package_id; |
| 311 | } else { |
| 312 | /* another logical processor on the same package */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 313 | packages[package_index].processor_count++; |
| 314 | packages[package_index].core_count += new_core; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | if (x86_processors[i].cache.l1i.size != 0) { |
| 318 | const uint32_t l1i_id = apic_id & ~bit_mask(x86_processors[i].cache.l1i.apic_bits); |
| 319 | processors[i].cache.l1i = &l1i[l1i_index]; |
| 320 | if (l1i_id != last_l1i_id) { |
| 321 | /* new cache */ |
| 322 | last_l1i_id = l1i_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 323 | l1i[++l1i_index] = (struct cpuinfo_cache) { |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 324 | .size = x86_processors[i].cache.l1i.size, |
| 325 | .associativity = x86_processors[i].cache.l1i.associativity, |
| 326 | .sets = x86_processors[i].cache.l1i.sets, |
| 327 | .partitions = x86_processors[i].cache.l1i.partitions, |
| 328 | .line_size = x86_processors[i].cache.l1i.line_size, |
| 329 | .flags = x86_processors[i].cache.l1i.flags, |
| 330 | .processor_start = i, |
| 331 | .processor_count = 1, |
| 332 | }; |
| 333 | } else { |
| 334 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 335 | l1i[l1i_index].processor_count += 1; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 336 | } |
| 337 | } else { |
| 338 | /* reset cache id */ |
| 339 | last_l1i_id = UINT32_MAX; |
| 340 | } |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 341 | if (x86_processors[i].cache.l1i.size != 0) { |
| 342 | const uint32_t l1i_id = apic_id & ~bit_mask(x86_processors[i].cache.l1i.apic_bits); |
| 343 | processors[i].cache.l1i = &l1i[l1i_index]; |
| 344 | if (l1i_id != last_l1i_id) { |
| 345 | /* new cache */ |
| 346 | last_l1i_id = l1i_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 347 | l1i[++l1i_index] = (struct cpuinfo_cache) { |
Marat Dukhan | ab3a127 | 2017-08-25 23:20:07 -0700 | [diff] [blame] | 348 | .size = x86_processors[i].cache.l1i.size, |
| 349 | .associativity = x86_processors[i].cache.l1i.associativity, |
| 350 | .sets = x86_processors[i].cache.l1i.sets, |
| 351 | .partitions = x86_processors[i].cache.l1i.partitions, |
| 352 | .line_size = x86_processors[i].cache.l1i.line_size, |
| 353 | .flags = x86_processors[i].cache.l1i.flags, |
| 354 | .processor_start = i, |
| 355 | .processor_count = 1, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 356 | }; |
| 357 | } else { |
| 358 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 359 | l1i[l1i_index].processor_count += 1; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 360 | } |
| 361 | } else { |
| 362 | /* reset cache id */ |
| 363 | last_l1i_id = UINT32_MAX; |
| 364 | } |
| 365 | if (x86_processors[i].cache.l1d.size != 0) { |
| 366 | const uint32_t l1d_id = apic_id & ~bit_mask(x86_processors[i].cache.l1d.apic_bits); |
| 367 | processors[i].cache.l1d = &l1d[l1d_index]; |
| 368 | if (l1d_id != last_l1d_id) { |
| 369 | /* new cache */ |
| 370 | last_l1d_id = l1d_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 371 | l1d[++l1d_index] = (struct cpuinfo_cache) { |
Marat Dukhan | ab3a127 | 2017-08-25 23:20:07 -0700 | [diff] [blame] | 372 | .size = x86_processors[i].cache.l1d.size, |
| 373 | .associativity = x86_processors[i].cache.l1d.associativity, |
| 374 | .sets = x86_processors[i].cache.l1d.sets, |
| 375 | .partitions = x86_processors[i].cache.l1d.partitions, |
| 376 | .line_size = x86_processors[i].cache.l1d.line_size, |
| 377 | .flags = x86_processors[i].cache.l1d.flags, |
| 378 | .processor_start = i, |
| 379 | .processor_count = 1, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 380 | }; |
| 381 | } else { |
| 382 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 383 | l1d[l1d_index].processor_count += 1; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 384 | } |
| 385 | } else { |
| 386 | /* reset cache id */ |
| 387 | last_l1d_id = UINT32_MAX; |
| 388 | } |
| 389 | if (x86_processors[i].cache.l2.size != 0) { |
| 390 | const uint32_t l2_id = apic_id & ~bit_mask(x86_processors[i].cache.l2.apic_bits); |
| 391 | processors[i].cache.l2 = &l2[l2_index]; |
| 392 | if (l2_id != last_l2_id) { |
| 393 | /* new cache */ |
| 394 | last_l2_id = l2_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 395 | l2[++l2_index] = (struct cpuinfo_cache) { |
Marat Dukhan | ab3a127 | 2017-08-25 23:20:07 -0700 | [diff] [blame] | 396 | .size = x86_processors[i].cache.l2.size, |
| 397 | .associativity = x86_processors[i].cache.l2.associativity, |
| 398 | .sets = x86_processors[i].cache.l2.sets, |
| 399 | .partitions = x86_processors[i].cache.l2.partitions, |
| 400 | .line_size = x86_processors[i].cache.l2.line_size, |
| 401 | .flags = x86_processors[i].cache.l2.flags, |
| 402 | .processor_start = i, |
| 403 | .processor_count = 1, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 404 | }; |
| 405 | } else { |
| 406 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 407 | l2[l2_index].processor_count += 1; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 408 | } |
| 409 | } else { |
| 410 | /* reset cache id */ |
| 411 | last_l2_id = UINT32_MAX; |
| 412 | } |
| 413 | if (x86_processors[i].cache.l3.size != 0) { |
| 414 | const uint32_t l3_id = apic_id & ~bit_mask(x86_processors[i].cache.l3.apic_bits); |
| 415 | processors[i].cache.l3 = &l3[l3_index]; |
| 416 | if (l3_id != last_l3_id) { |
| 417 | /* new cache */ |
| 418 | last_l3_id = l3_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 419 | l3[++l3_index] = (struct cpuinfo_cache) { |
Marat Dukhan | ab3a127 | 2017-08-25 23:20:07 -0700 | [diff] [blame] | 420 | .size = x86_processors[i].cache.l3.size, |
| 421 | .associativity = x86_processors[i].cache.l3.associativity, |
| 422 | .sets = x86_processors[i].cache.l3.sets, |
| 423 | .partitions = x86_processors[i].cache.l3.partitions, |
| 424 | .line_size = x86_processors[i].cache.l3.line_size, |
| 425 | .flags = x86_processors[i].cache.l3.flags, |
| 426 | .processor_start = i, |
| 427 | .processor_count = 1, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 428 | }; |
| 429 | } else { |
| 430 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 431 | l3[l3_index].processor_count += 1; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 432 | } |
| 433 | } else { |
| 434 | /* reset cache id */ |
| 435 | last_l3_id = UINT32_MAX; |
| 436 | } |
| 437 | if (x86_processors[i].cache.l4.size != 0) { |
| 438 | const uint32_t l4_id = apic_id & ~bit_mask(x86_processors[i].cache.l4.apic_bits); |
| 439 | processors[i].cache.l4 = &l4[l4_index]; |
| 440 | if (l4_id != last_l4_id) { |
| 441 | /* new cache */ |
| 442 | last_l4_id = l4_id; |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 443 | l4[++l4_index] = (struct cpuinfo_cache) { |
Marat Dukhan | ab3a127 | 2017-08-25 23:20:07 -0700 | [diff] [blame] | 444 | .size = x86_processors[i].cache.l4.size, |
| 445 | .associativity = x86_processors[i].cache.l4.associativity, |
| 446 | .sets = x86_processors[i].cache.l4.sets, |
| 447 | .partitions = x86_processors[i].cache.l4.partitions, |
| 448 | .line_size = x86_processors[i].cache.l4.line_size, |
| 449 | .flags = x86_processors[i].cache.l4.flags, |
| 450 | .processor_start = i, |
| 451 | .processor_count = 1, |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 452 | }; |
| 453 | } else { |
| 454 | /* another processor sharing the same cache */ |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 455 | l4[l4_index].processor_count += 1; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 456 | } |
| 457 | } else { |
| 458 | /* reset cache id */ |
| 459 | last_l4_id = UINT32_MAX; |
| 460 | } |
| 461 | } |
| 462 | |
Marat Dukhan | fbc4cfc | 2017-09-22 16:45:45 -0700 | [diff] [blame] | 463 | #ifdef __ANDROID__ |
| 464 | cpuinfo_gpu_query_gles2(packages[0].gpu_name); |
| 465 | #endif |
| 466 | |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 467 | /* Commit changes */ |
| 468 | cpuinfo_processors = processors; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 469 | cpuinfo_cores = cores; |
| 470 | cpuinfo_packages = packages; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 471 | cpuinfo_cache[cpuinfo_cache_level_1i] = l1i; |
| 472 | cpuinfo_cache[cpuinfo_cache_level_1d] = l1d; |
| 473 | cpuinfo_cache[cpuinfo_cache_level_2] = l2; |
| 474 | cpuinfo_cache[cpuinfo_cache_level_3] = l3; |
| 475 | cpuinfo_cache[cpuinfo_cache_level_4] = l4; |
| 476 | |
Marat Dukhan | 8ecad1a | 2017-05-08 07:21:57 +0000 | [diff] [blame] | 477 | cpuinfo_processors_count = processors_count; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 478 | cpuinfo_cores_count = cores_count; |
| 479 | cpuinfo_packages_count = packages_count; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 480 | cpuinfo_cache_count[cpuinfo_cache_level_1i] = l1i_count; |
| 481 | cpuinfo_cache_count[cpuinfo_cache_level_1d] = l1d_count; |
| 482 | cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count; |
| 483 | cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count; |
| 484 | cpuinfo_cache_count[cpuinfo_cache_level_4] = l4_count; |
| 485 | |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 486 | processors = NULL; |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 487 | cores = NULL; |
| 488 | packages = NULL; |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 489 | l1i = l1d = l2 = l3 = l4 = NULL; |
| 490 | |
| 491 | cleanup: |
| 492 | if (sched_setaffinity(0, sizeof(cpu_set_t), &old_affinity) != 0) { |
| 493 | cpuinfo_log_warning("could not restore initial process affinity: " |
| 494 | "sched_getaffinity failed: %s", strerror(errno)); |
| 495 | } |
| 496 | |
| 497 | free(x86_processors); |
| 498 | free(processors); |
Marat Dukhan | 43a51cd | 2017-09-22 16:35:05 -0700 | [diff] [blame] | 499 | free(cores); |
| 500 | free(packages); |
Marat Dukhan | 3045d4f | 2017-03-04 01:51:42 -0500 | [diff] [blame] | 501 | free(l1i); |
| 502 | free(l1d); |
| 503 | free(l2); |
| 504 | free(l3); |
| 505 | free(l4); |
| 506 | } |