1 #include <stdio.h> 2 #include <assert.h> 3 #include <stdint.h> 4 #include <inttypes.h> 5 #include "opcodes.h" 6 7 uint64_t 8 ecag(int ai, int li, int ti) 9 { 10 register uint64_t result asm("2") = 0; 11 register uint64_t input asm("3") = (ai << 4) | (li << 1) | ti; 12 13 asm volatile( ECAG(2,0,3,000,00) 14 : "=d" (result) : "d" (input)); 15 return result; 16 } 17 18 static unsigned 19 get_level_info(uint64_t topology, unsigned level) 20 { 21 return (topology >> (56 - level * 8)) & 0xff; 22 } 23 24 int 25 main(void) 26 { 27 unsigned level; 28 uint64_t topology; 29 30 topology = ecag(0, 0, 0); // get summary 31 32 /* ECAG supports at most 8 levels of cache. Iterate over all of them 33 ignoring those not present. */ 34 for (level = 0; level < 8; level++) { 35 unsigned info = get_level_info(topology, level); 36 37 if ((info & 0xc) == 0) continue; // cache does not exist at this level 38 39 unsigned cache_type = info & 0x3; 40 unsigned cache_scope = (info & 0xc) >> 2; 41 char *type, *scope; 42 43 switch (cache_type) { 44 case 0: type = "separate data and instruction"; break; 45 case 1: type = "instruction"; break; 46 case 2: type = "data"; break; 47 case 3: type = "unified data and instruction"; break; 48 } 49 50 switch (cache_scope) { 51 case 0: assert(0); // should never occur because cache exists 52 case 1: scope = "private"; break; 53 case 2: scope = "shared"; break; 54 case 3: scope = "reserved"; break; 55 } 56 57 printf("L%u topology: %s; %s\n", level+1, type, scope); 58 printf("L%u cache line size data: %"PRId64"\n", level+1, 59 ecag(1, level, 0)); 60 printf("L%u cache line size insn: %"PRId64"\n", level+1, 61 ecag(1, level, 1)); 62 printf("L%u total cachesize data: %"PRId64"\n", level+1, 63 ecag(2, level, 0)); 64 printf("L%u total cachesize insn: %"PRId64"\n", level+1, 65 ecag(2, level, 1)); 66 printf("L%u set. assoc. data: %"PRId64"\n", level+1, 67 ecag(3, level, 0)); 68 printf("L%u set. assoc. insn: %"PRId64"\n", level+1, 69 ecag(3, level, 1)); 70 } 71 72 return 0; 73 } 74