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.

integrate intel mba via ia32_l2_qos_cfg for memory bandwidth isolation alongside cat

+79 -2
+9 -1
bindings/ocaml/icepick.ml
··· 40 40 let max_clos = foreign "icepick_topology_max_clos" (t @-> returning uint) 41 41 let ccx_count = foreign "icepick_topology_ccx_count" (t @-> returning uint) 42 42 let cat_supported = foreign "icepick_topology_cat_supported" (t @-> returning bool) 43 + let mba_supported = foreign "icepick_topology_mba_supported" (t @-> returning bool) 44 + let mba_is_linear = foreign "icepick_topology_mba_is_linear" (t @-> returning bool) 45 + let max_mba_thrtl = foreign "icepick_topology_max_mba_thrtl" (t @-> returning uint) 43 46 end 44 47 45 48 module Region = struct ··· 67 70 let access_pattern = field t "access_pattern" int 68 71 let stride_bytes = field t "stride_bytes" size_t 69 72 let prime_iterations = field t "prime_iterations" uint 73 + let mba_throttle = field t "mba_throttle" uint 70 74 let () = seal t 71 75 end 72 76 ··· 134 138 let max_clos t = Unsigned.UInt.to_int (C.Topology.max_clos t.ptr) 135 139 let ccx_count t = Unsigned.UInt.to_int (C.Topology.ccx_count t.ptr) 136 140 let cat_supported t = C.Topology.cat_supported t.ptr 141 + let mba_supported t = C.Topology.mba_supported t.ptr 142 + let mba_is_linear t = C.Topology.mba_is_linear t.ptr 143 + let max_mba_thrtl t = Unsigned.UInt.to_int (C.Topology.max_mba_thrtl t.ptr) 137 144 end 138 145 139 146 module Latency_stats = struct ··· 186 193 187 194 let lock topo ~size ~clos ?(numa = -1) ?(huge_pages = true) ?(verify = false) 188 195 ?(prime_strategy = Prime_temporal) ?(access_pattern = Pattern_sequential) 189 - ?(stride = 0) ?(prime_iterations = 3) () = 196 + ?(stride = 0) ?(prime_iterations = 3) ?(mba_throttle = 0) () = 190 197 let cfg = make C.Config.t in 191 198 setf cfg C.Config.size (Unsigned.Size_t.of_int size); 192 199 setf cfg C.Config.clos_id (Unsigned.UInt.of_int clos); ··· 201 208 setf cfg C.Config.access_pattern (access_pattern_to_int access_pattern); 202 209 setf cfg C.Config.stride_bytes (Unsigned.Size_t.of_int stride); 203 210 setf cfg C.Config.prime_iterations (Unsigned.UInt.of_int prime_iterations); 211 + setf cfg C.Config.mba_throttle (Unsigned.UInt.of_int mba_throttle); 204 212 let ptr_ref = allocate C.Region.t (from_voidp void null) in 205 213 let ret = C.lock topo.Topology.ptr (addr cfg) ptr_ref in 206 214 C.check_error ret;
+4 -1
bindings/ocaml/icepick.mli
··· 22 22 val max_clos : t -> int 23 23 val ccx_count : t -> int 24 24 val cat_supported : t -> bool 25 + val mba_supported : t -> bool 26 + val mba_is_linear : t -> bool 27 + val max_mba_thrtl : t -> int 25 28 end 26 29 27 30 module Region : sig ··· 29 32 30 33 val lock : Topology.t -> size:int -> clos:int -> ?numa:int -> ?huge_pages:bool -> ?verify:bool -> 31 34 ?prime_strategy:prime_strategy -> ?access_pattern:access_pattern -> 32 - ?stride:int -> ?prime_iterations:int -> unit -> t 35 + ?stride:int -> ?prime_iterations:int -> ?mba_throttle:int -> unit -> t 33 36 val unlock : t -> unit 34 37 val ptr : t -> nativeint 35 38 val size : t -> int
+4
include/icepick.h
··· 49 49 icepick_access_pattern_t access_pattern; 50 50 size_t stride_bytes; 51 51 unsigned prime_iterations; 52 + unsigned mba_throttle; 52 53 } icepick_config_t; 53 54 54 55 typedef struct { ··· 70 71 unsigned icepick_topology_max_clos(const icepick_topology_t *topo); 71 72 unsigned icepick_topology_ccx_count(const icepick_topology_t *topo); 72 73 bool icepick_topology_cat_supported(const icepick_topology_t *topo); 74 + bool icepick_topology_mba_supported(const icepick_topology_t *topo); 75 + bool icepick_topology_mba_is_linear(const icepick_topology_t *topo); 76 + unsigned icepick_topology_max_mba_thrtl(const icepick_topology_t *topo); 73 77 74 78 int icepick_lock(icepick_topology_t *topo, const icepick_config_t *cfg, icepick_region_t **region); 75 79 int icepick_unlock(icepick_region_t *region);
+12
src/clos.c
··· 83 83 { 84 84 return default_mask; 85 85 } 86 + 87 + int mba_configure(int msr_fd, unsigned clos_id, unsigned throttle) 88 + { 89 + if (clos_id >= MAX_CLOS) 90 + return ICEPICK_E_INVALID; 91 + 92 + if (throttle == 0) 93 + return 0; 94 + 95 + uint32_t msr = MSR_IA32_MBA_THRTL_BASE + clos_id; 96 + return msr_write(msr_fd, msr, throttle); 97 + }
+8
src/internal.h
··· 8 8 9 9 #define MSR_IA32_PQR_ASSOC 0xC8F 10 10 #define MSR_IA32_L3_QOS_MASK_0 0xC90 11 + #define MSR_IA32_L2_QOS_CFG 0xC82 12 + #define MSR_IA32_MBA_THRTL_BASE 0xD50 11 13 12 14 #define CACHE_LINE_SIZE 64 13 15 #define MAX_CLOS 16 ··· 23 25 24 26 struct icepick_topology { 25 27 bool cat_supported; 28 + bool mba_supported; 29 + bool mba_is_linear; 26 30 unsigned l3_ways; 27 31 size_t l3_size; 28 32 size_t way_size; 29 33 unsigned max_clos; 34 + unsigned max_mba_thrtl; 30 35 unsigned ccx_count; 31 36 uint32_t default_way_mask; 32 37 int ccx_numa_node[MAX_CCXS]; ··· 38 43 unsigned clos_id; 39 44 int numa_node; 40 45 uint32_t way_mask; 46 + unsigned mba_throttle; 41 47 icepick_topology_t *topo; 42 48 struct icepick_monitor *monitor; 43 49 icepick_prime_strategy_t prime_strategy; ··· 93 99 icepick_prime_strategy_t strategy, icepick_access_pattern_t pattern, 94 100 size_t stride); 95 101 int monitor_perf_open(int cpu, bool is_amd); 102 + 103 + int mba_configure(int msr_fd, unsigned clos_id, unsigned throttle); 96 104 97 105 #endif
+9
src/lock.c
··· 222 222 r->clos_id = cfg->clos_id; 223 223 r->numa_node = cfg->numa_node; 224 224 r->way_mask = way_mask; 225 + r->mba_throttle = cfg->mba_throttle; 225 226 r->topo = topo; 226 227 r->size = ways_needed * topo->way_size; 227 228 r->monitor = NULL; ··· 263 264 ret = clos_configure_mask(msr_fd, cfg->clos_id, way_mask); 264 265 if (ret < 0) 265 266 goto cleanup; 267 + 268 + if (topo->mba_supported && cfg->mba_throttle > 0) { 269 + ret = mba_configure(msr_fd, cfg->clos_id, cfg->mba_throttle); 270 + if (ret < 0) 271 + goto cleanup; 272 + } 266 273 267 274 ret = clos_associate_thread(msr_fd, cfg->clos_id); 268 275 if (ret < 0) ··· 325 332 if (msr_fd >= 0) { 326 333 clos_release(region->clos_id); 327 334 clos_configure_mask(msr_fd, region->clos_id, 0); 335 + if (region->topo->mba_supported && region->mba_throttle > 0) 336 + mba_configure(msr_fd, region->clos_id, 0); 328 337 clos_configure_mask(msr_fd, 0, clos_get_default_mask()); 329 338 msr_close(msr_fd); 330 339 }
+33
src/topology.c
··· 33 33 return true; 34 34 } 35 35 36 + static bool detect_mba_support(icepick_topology_t *topo) 37 + { 38 + uint32_t eax, ebx, ecx, edx; 39 + 40 + cpuid(0x10, 0, &eax, &ebx, &ecx, &edx); 41 + if (!(ebx & (1 << 3))) 42 + return false; 43 + 44 + cpuid(0x10, 3, &eax, &ebx, &ecx, &edx); 45 + 46 + topo->max_mba_thrtl = (eax & 0xFFF) + 1; 47 + topo->mba_is_linear = (ecx & (1 << 2)) != 0; 48 + 49 + return true; 50 + } 51 + 36 52 static void detect_amd_cache_topology(icepick_topology_t *topo) 37 53 { 38 54 uint32_t eax, ebx, ecx, edx; ··· 133 149 return ICEPICK_E_NO_CAT; 134 150 } 135 151 152 + t->mba_supported = detect_mba_support(t); 153 + 136 154 if (is_amd_cpu()) 137 155 detect_amd_cache_topology(t); 138 156 else ··· 183 201 { 184 202 return topo->cat_supported; 185 203 } 204 + 205 + bool icepick_topology_mba_supported(const icepick_topology_t *topo) 206 + { 207 + return topo->mba_supported; 208 + } 209 + 210 + bool icepick_topology_mba_is_linear(const icepick_topology_t *topo) 211 + { 212 + return topo->mba_is_linear; 213 + } 214 + 215 + unsigned icepick_topology_max_mba_thrtl(const icepick_topology_t *topo) 216 + { 217 + return topo->max_mba_thrtl; 218 + }