diff --git a/src/kerninfo.h b/src/kerninfo.h index 04f3b18..6074e26 100644 --- a/src/kerninfo.h +++ b/src/kerninfo.h @@ -6,10 +6,51 @@ #include +void get_vendor(char *vendor) { + unsigned int a[4]; + + asm ( + /* %rbx must be preserved. */ + "mov %%rbx, %%rdi\n" + "cpuid\n" + "xchg %%rdi, %%rbx\n" + : "=a"(a[0]), "=D"(a[1]), "=c"(a[2]), "=d"(a[3]) + : "a"(0) + ); + strncpy(&vendor[0], (char *)&a[1], 4); + strncpy(&vendor[4], (char *)&a[3], 4); + strncpy(&vendor[8], (char *)&a[2], 4); +} + +int is_amd_arch(void) { + static int amd = -1; /* -1: Unknown, 1: Yes, 0: No */ + char vendor[13] = {0}; + + if (amd != -1) + return amd; + + get_vendor(vendor); + amd = strcmp(vendor, "AuthenticAMD") ? 0 : 1; + return amd; +} + void get_pmu_string(char *pmu_name) { FILE *f; size_t retval; + if (is_amd_arch()) { + f = fopen("/sys/bus/event_source/devices/ibs_op", "r"); + if (!f) { + fprintf(stderr, "WARNING: Unable to open '/sys/bus/event_source/devices/ibs_op'. " + "Using software events.\n"); + strcpy(pmu_name, "invalid"); + return; + } + fclose(f); + strcpy(pmu_name, "ibs_op"); + return; + } + f = fopen("/sys/devices/cpu/caps/pmu_name", "r"); if(!f) { fprintf(stderr, "WARNING: Unable to open '/sys/devices/cpu/caps/pmu_name'. Using software events.\n"); diff --git a/src/setup_bpf.h b/src/setup_bpf.h index b5fee31..5e9cd17 100644 --- a/src/setup_bpf.h +++ b/src/setup_bpf.h @@ -147,6 +147,35 @@ static int single_tma_event(struct event *e, struct event *leader, #else +/* Return value: >0: Valid, -1: Error */ +static int get_ibs_op_type(void) { + static int type = -1; /* -1 : Unknown, 0: Failed to read first time, >0: Valid */ + FILE *fp; + int ret; + + if (type != -1) { + if (!type) + return -1; + return type; + } + + fp = fopen("/sys/bus/event_source/devices/ibs_op/type", "r"); + if (!fp) { + fprintf(stderr, "Failed to find ibs_op// pmu sysfs. [%m]\n"); + type = 0; + return -1; + } + + ret = fscanf(fp, "%d", &type); + fclose(fp); + if (ret != 1) { + fprintf(stderr, "Failed to read ibs_op// type. [%m]\n"); + type = 0; + return -1; + } + return type; +} + /** single_insn_event - Handles a single CPU, PMU, socket event. Returns: @@ -177,6 +206,12 @@ static int single_insn_event(int cpu, int pid) { } else if(strncmp(bpf_info->pmu_name, "sapphire_rapids", 7) == 0) { attr.type = PERF_TYPE_RAW; attr.config = 0x00c0; + } else if(strncmp(bpf_info->pmu_name, "ibs_op", 6) == 0) { + attr.type = get_ibs_op_type(); + if (attr.type < 0) + return -1; + attr.config = 0x80000; + attr.exclude_guest = 0; } else { attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_CPU_CLOCK;