cache line locking on AMD x86_64 utilising L3 CAT pseudo-locking
26

Configure Feed

Select the types of activity you want to include in your feed.

icepick / src / topology.c
4.3 kB 185 lines
1#define _GNU_SOURCE 2#include "internal.h" 3#include <stdlib.h> 4#include <string.h> 5#include <cpuid.h> 6#include <sched.h> 7#include <dirent.h> 8#include <stdio.h> 9 10static void cpuid(uint32_t leaf, uint32_t subleaf, 11 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) 12{ 13 __cpuid_count(leaf, subleaf, *eax, *ebx, *ecx, *edx); 14} 15 16static bool detect_cat_support(icepick_topology_t *topo) 17{ 18 uint32_t eax, ebx, ecx, edx; 19 20 cpuid(0x10, 0, &eax, &ebx, &ecx, &edx); 21 if (!(ebx & (1 << 1))) 22 return false; 23 24 cpuid(0x10, 1, &eax, &ebx, &ecx, &edx); 25 26 topo->l3_ways = (eax & 0x1F) + 1; 27 topo->max_clos = (edx & 0xFFFF) + 1; 28 topo->default_way_mask = ebx; 29 30 if (topo->max_clos > MAX_CLOS) 31 topo->max_clos = MAX_CLOS; 32 33 return true; 34} 35 36static void detect_amd_cache_topology(icepick_topology_t *topo) 37{ 38 uint32_t eax, ebx, ecx, edx; 39 40 for (int i = 0; i < 16; i++) { 41 cpuid(0x8000001D, i, &eax, &ebx, &ecx, &edx); 42 43 uint32_t cache_type = eax & 0x1F; 44 if (cache_type == 0) 45 break; 46 47 uint32_t cache_level = (eax >> 5) & 0x7; 48 if (cache_level != 3) 49 continue; 50 51 uint32_t line_size = (ebx & 0xFFF) + 1; 52 uint32_t partitions = ((ebx >> 12) & 0x3FF) + 1; 53 uint32_t ways = ((ebx >> 22) & 0x3FF) + 1; 54 uint32_t sets = ecx + 1; 55 56 topo->l3_size = (size_t)line_size * partitions * ways * sets; 57 topo->l3_ways = ways; 58 topo->way_size = topo->l3_size / topo->l3_ways; 59 break; 60 } 61} 62 63static void detect_intel_cache_topology(icepick_topology_t *topo) 64{ 65 uint32_t eax, ebx, ecx, edx; 66 67 for (int i = 0; i < 16; i++) { 68 cpuid(0x04, i, &eax, &ebx, &ecx, &edx); 69 70 uint32_t cache_type = eax & 0x1F; 71 if (cache_type == 0) 72 break; 73 74 uint32_t cache_level = (eax >> 5) & 0x7; 75 if (cache_level != 3) 76 continue; 77 78 uint32_t line_size = (ebx & 0xFFF) + 1; 79 uint32_t partitions = ((ebx >> 12) & 0x3FF) + 1; 80 uint32_t ways = ((ebx >> 22) & 0x3FF) + 1; 81 uint32_t sets = ecx + 1; 82 83 topo->l3_size = (size_t)line_size * partitions * ways * sets; 84 topo->l3_ways = ways; 85 topo->way_size = topo->l3_size / topo->l3_ways; 86 break; 87 } 88} 89 90static bool is_amd_cpu(void) 91{ 92 uint32_t eax, ebx, ecx, edx; 93 cpuid(0, 0, &eax, &ebx, &ecx, &edx); 94 return (ebx == 0x68747541 && edx == 0x69746E65 && ecx == 0x444D4163); 95} 96 97static int count_ccxs(void) 98{ 99 DIR *dir = opendir("/sys/devices/system/node"); 100 if (!dir) 101 return 1; 102 103 int count = 0; 104 struct dirent *entry; 105 while ((entry = readdir(dir))) { 106 if (strncmp(entry->d_name, "node", 4) == 0) 107 count++; 108 } 109 closedir(dir); 110 111 return count > 0 ? count : 1; 112} 113 114static void detect_numa_topology(icepick_topology_t *topo) 115{ 116 topo->ccx_count = count_ccxs(); 117 if (topo->ccx_count > MAX_CCXS) 118 topo->ccx_count = MAX_CCXS; 119 120 for (unsigned i = 0; i < topo->ccx_count; i++) 121 topo->ccx_numa_node[i] = i; 122} 123 124int icepick_discover_topology(icepick_topology_t **topo) 125{ 126 icepick_topology_t *t = calloc(1, sizeof(*t)); 127 if (!t) 128 return ICEPICK_E_ALLOC; 129 130 t->cat_supported = detect_cat_support(t); 131 if (!t->cat_supported) { 132 free(t); 133 return ICEPICK_E_NO_CAT; 134 } 135 136 if (is_amd_cpu()) 137 detect_amd_cache_topology(t); 138 else 139 detect_intel_cache_topology(t); 140 141 if (t->l3_size == 0 || t->l3_ways == 0) { 142 t->way_size = 2 * 1024 * 1024; 143 t->l3_size = t->way_size * t->l3_ways; 144 } 145 146 detect_numa_topology(t); 147 148 *topo = t; 149 return 0; 150} 151 152void icepick_free_topology(icepick_topology_t *topo) 153{ 154 free(topo); 155} 156 157unsigned icepick_topology_l3_ways(const icepick_topology_t *topo) 158{ 159 return topo->l3_ways; 160} 161 162size_t icepick_topology_l3_size(const icepick_topology_t *topo) 163{ 164 return topo->l3_size; 165} 166 167size_t icepick_topology_way_size(const icepick_topology_t *topo) 168{ 169 return topo->way_size; 170} 171 172unsigned icepick_topology_max_clos(const icepick_topology_t *topo) 173{ 174 return topo->max_clos; 175} 176 177unsigned icepick_topology_ccx_count(const icepick_topology_t *topo) 178{ 179 return topo->ccx_count; 180} 181 182bool icepick_topology_cat_supported(const icepick_topology_t *topo) 183{ 184 return topo->cat_supported; 185}