Index: lib/libpmc/libpmc.c =================================================================== --- lib/libpmc/libpmc.c +++ lib/libpmc/libpmc.c @@ -76,6 +76,10 @@ static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, struct pmc_op_pmcallocate *_pmc_config); #endif +#if defined(__amd64__) +static int pt_allocate_pmc(enum pmc_event _pe, char *_ctrspec, + struct pmc_op_pmcallocate *_pmc_config); +#endif #if defined(__arm__) #if defined(__XSCALE__) static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec, @@ -87,6 +91,8 @@ #if defined(__aarch64__) static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec, struct pmc_op_pmcallocate *_pmc_config); +static int coresight_allocate_pmc(enum pmc_event _pe, char *_ctrspec, + struct pmc_op_pmcallocate *_pmc_config); #endif #if defined(__mips__) static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec, @@ -239,6 +245,12 @@ __PMC_EV_ALIAS_SKYLAKE_XEON() }; +static const struct pmc_event_descr kabylake_event_table[] = +{ + /* Kabylake events are similar to Skylake */ + __PMC_EV_ALIAS_SKYLAKE() +}; + static const struct pmc_event_descr ivybridge_event_table[] = { __PMC_EV_ALIAS_IVYBRIDGE() @@ -336,6 +348,7 @@ PMC_MDEP_TABLE(broadwell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); PMC_MDEP_TABLE(skylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); PMC_MDEP_TABLE(skylake_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); +PMC_MDEP_TABLE(kabylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP, PMC_CLASS_PT); PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC); PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP); @@ -350,8 +363,8 @@ PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); PMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); PMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7); -PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); -PMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8); +PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8, PMC_CLASS_CORESIGHT); +PMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8, PMC_CLASS_CORESIGHT); PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); PMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K); PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); @@ -365,6 +378,16 @@ __PMC_EV_TSC() }; +static const struct pmc_event_descr pt_event_table[] = +{ + __PMC_EV_PT() +}; + +static const struct pmc_event_descr coresight_event_table[] = +{ + __PMC_EV_CORESIGHT() +}; + #undef PMC_CLASS_TABLE_DESC #define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ static const struct pmc_class_descr NAME##_class_table_descr = \ @@ -392,6 +415,7 @@ PMC_CLASS_TABLE_DESC(broadwell_xeon, IAP, broadwell_xeon, iap); PMC_CLASS_TABLE_DESC(skylake, IAP, skylake, iap); PMC_CLASS_TABLE_DESC(skylake_xeon, IAP, skylake_xeon, iap); +PMC_CLASS_TABLE_DESC(kabylake, IAP, kabylake, iap); PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap); PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap); PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap); @@ -419,6 +443,9 @@ #if defined(__i386__) || defined(__amd64__) PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); #endif +#if defined(__amd64__) +PMC_CLASS_TABLE_DESC(pt, PT, pt, pt); +#endif #if defined(__arm__) #if defined(__XSCALE__) PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale); @@ -429,6 +456,7 @@ #if defined(__aarch64__) PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64); PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64); +PMC_CLASS_TABLE_DESC(coresight, CORESIGHT, coresight, coresight); #endif #if defined(__mips__) PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); @@ -732,6 +760,8 @@ #define skylake_aliases_without_iaf core2_aliases_without_iaf #define skylake_xeon_aliases core2_aliases #define skylake_xeon_aliases_without_iaf core2_aliases_without_iaf +#define kabylake_aliases core2_aliases +#define kabylake_aliases_without_iaf core2_aliases_without_iaf #define ivybridge_aliases core2_aliases #define ivybridge_aliases_without_iaf core2_aliases_without_iaf #define ivybridge_xeon_aliases core2_aliases @@ -1049,7 +1079,8 @@ return (-1); } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE || - cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE_XEON) { + cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE_XEON || + cpu_info.pm_cputype == PMC_CPU_INTEL_KABYLAKE) { if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) { n = pmc_parse_mask(iap_rsp_mask_skylake, p, &rsp); } else @@ -2495,6 +2526,84 @@ } #endif +#if defined(__amd64__) + +#define INTEL_PT_KW_BRANCHES "branches" +#define INTEL_PT_KW_TSC "tsc" +#define INTEL_PT_KW_MTC "mtc" +#define INTEL_PT_KW_DISRETC "disretc" +#define INTEL_PT_KW_ADDRA "addra" +#define INTEL_PT_KW_ADDRB "addrb" + +static int +pt_allocate_pmc(enum pmc_event pe, char *ctrspec, + struct pmc_op_pmcallocate *pmc_config) +{ + struct pmc_md_pt_op_pmcallocate *pm_pt; + uint64_t addr; + uint32_t addrn; + char *p, *q, *e; + + if (pe != PMC_EV_PT_PT) + return (-1); + + pm_pt = (struct pmc_md_pt_op_pmcallocate *)&pmc_config->pm_md.pm_pt; + + addrn = 0; + while ((p = strsep(&ctrspec, ",")) != NULL) { + if (KWMATCH(p, INTEL_PT_KW_BRANCHES)) { + pm_pt->flags |= INTEL_PT_FLAG_BRANCHES; + } + + if (KWMATCH(p, INTEL_PT_KW_TSC)) { + pm_pt->flags |= INTEL_PT_FLAG_TSC; + } + + if (KWMATCH(p, INTEL_PT_KW_MTC)) { + pm_pt->flags |= INTEL_PT_FLAG_MTC; + } + + if (KWMATCH(p, INTEL_PT_KW_DISRETC)) { + pm_pt->flags |= INTEL_PT_FLAG_DISRETC; + } + + if (KWPREFIXMATCH(p, INTEL_PT_KW_ADDRA "=")) { + q = strchr(p, '='); + if (*++q == '\0') /* skip '=' */ + return (-1); + + addr = strtoul(q, &e, 0); + if (e == q || *e != '\0') + return (-1); + pm_pt->ranges[addrn * 2] = addr; + } + + if (KWPREFIXMATCH(p, INTEL_PT_KW_ADDRB "=")) { + q = strchr(p, '='); + if (*++q == '\0') /* skip '=' */ + return (-1); + + addr = strtoul(q, &e, 0); + if (e == q || *e != '\0') + return (-1); + pm_pt->ranges[addrn * 2 + 1] = addr; + + if (pm_pt->ranges[addrn * 2 + 1] < pm_pt->ranges[addrn * 2]) + return (-1); + addrn += 1; + if (addrn > PT_NADDR) + return (-1); + } + }; + + pm_pt->nranges = addrn; + + pmc_config->pm_caps |= PMC_CAP_READ; + + return (0); +} +#endif + static struct pmc_event_alias generic_aliases[] = { EV_ALIAS("instructions", "SOFT-CLOCK.HARD"), EV_ALIAS(NULL, NULL) @@ -2583,6 +2692,61 @@ return (0); } + +#define ARM_CORESIGHT_KW_ADDRA "addra" +#define ARM_CORESIGHT_KW_ADDRB "addrb" + +static int +coresight_allocate_pmc(enum pmc_event pe, char *ctrspec, + struct pmc_op_pmcallocate *pmc_config) +{ + struct pmc_md_coresight_op_pmcallocate *pm_coresight; + uint64_t addr; + uint32_t addrn; + char *p, *q, *e; + + if (pe != PMC_EV_CORESIGHT_CORESIGHT) + return (-1); + + pm_coresight = (struct pmc_md_coresight_op_pmcallocate *)&pmc_config->pm_md.pm_coresight; + + addrn = 0; + while ((p = strsep(&ctrspec, ",")) != NULL) { + if (KWPREFIXMATCH(p, ARM_CORESIGHT_KW_ADDRA "=")) { + q = strchr(p, '='); + if (*++q == '\0') /* skip '=' */ + return (-1); + + addr = strtoul(q, &e, 0); + if (e == q || *e != '\0') + return (-1); + pm_coresight->ranges[addrn * 2] = addr; + } + + if (KWPREFIXMATCH(p, ARM_CORESIGHT_KW_ADDRB "=")) { + q = strchr(p, '='); + if (*++q == '\0') /* skip '=' */ + return (-1); + + addr = strtoul(q, &e, 0); + if (e == q || *e != '\0') + return (-1); + pm_coresight->ranges[addrn * 2 + 1] = addr; + + if (pm_coresight->ranges[addrn * 2 + 1] < pm_coresight->ranges[addrn * 2]) + return (-1); + addrn += 1; + if (addrn > CORESIGHT_NADDR) + return (-1); + } + }; + + pm_coresight->nranges = addrn; + + pmc_config->pm_caps |= PMC_CAP_READ; + + return (0); +} #endif #if defined(__mips__) @@ -2780,7 +2944,8 @@ retval = -1; if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && - mode != PMC_MODE_SC && mode != PMC_MODE_TC) { + mode != PMC_MODE_SC && mode != PMC_MODE_TC && + mode != PMC_MODE_ST && mode != PMC_MODE_TT) { errno = EINVAL; goto out; } @@ -2903,6 +3068,7 @@ int pmc_cpuinfo(const struct pmc_cpuinfo **pci) { + if (pmc_syscall == -1) { errno = ENXIO; return (-1); @@ -3023,6 +3189,10 @@ ev = skylake_xeon_event_table; count = PMC_EVENT_TABLE_SIZE(skylake_xeon); break; + case PMC_CPU_INTEL_KABYLAKE: + ev = kabylake_event_table; + count = PMC_EVENT_TABLE_SIZE(kabylake); + break; case PMC_CPU_INTEL_IVYBRIDGE: ev = ivybridge_event_table; count = PMC_EVENT_TABLE_SIZE(ivybridge); @@ -3086,6 +3256,10 @@ ev = tsc_event_table; count = PMC_EVENT_TABLE_SIZE(tsc); break; + case PMC_CLASS_PT: + ev = pt_event_table; + count = PMC_EVENT_TABLE_SIZE(pt); + break; case PMC_CLASS_K7: ev = k7_event_table; count = PMC_EVENT_TABLE_SIZE(k7); @@ -3136,6 +3310,10 @@ break; } break; + case PMC_CLASS_CORESIGHT: + ev = coresight_event_table; + count = PMC_EVENT_TABLE_SIZE(coresight); + break; case PMC_CLASS_MIPS24K: ev = mips24k_event_table; count = PMC_EVENT_TABLE_SIZE(mips24k); @@ -3184,12 +3362,14 @@ int pmc_flush_logfile(void) { + return (PMC_CALL(FLUSHLOG,0)); } int pmc_close_logfile(void) { + return (PMC_CALL(CLOSELOG,0)); } @@ -3406,6 +3586,12 @@ case PMC_CPU_INTEL_SKYLAKE_XEON: PMC_MDEP_INIT_INTEL_V2(skylake_xeon); break; + case PMC_CPU_INTEL_KABYLAKE: +#if defined(__amd64__) + pmc_class_table[n++] = &pt_class_table_descr; +#endif + PMC_MDEP_INIT_INTEL_V2(kabylake); + break; case PMC_CPU_INTEL_IVYBRIDGE: PMC_MDEP_INIT_INTEL_V2(ivybridge); break; @@ -3455,11 +3641,13 @@ #if defined(__aarch64__) case PMC_CPU_ARMV8_CORTEX_A53: PMC_MDEP_INIT(cortex_a53); - pmc_class_table[n] = &cortex_a53_class_table_descr; + pmc_class_table[n++] = &cortex_a53_class_table_descr; + pmc_class_table[n++] = &coresight_class_table_descr; break; case PMC_CPU_ARMV8_CORTEX_A57: PMC_MDEP_INIT(cortex_a57); - pmc_class_table[n] = &cortex_a57_class_table_descr; + pmc_class_table[n++] = &cortex_a57_class_table_descr; + pmc_class_table[n++] = &coresight_class_table_descr; break; #endif #if defined(__mips__) @@ -3623,6 +3811,11 @@ evfence = skylake_xeon_event_table + PMC_EVENT_TABLE_SIZE(skylake_xeon); break; + case PMC_CPU_INTEL_KABYLAKE: + ev = kabylake_event_table; + evfence = kabylake_event_table + + PMC_EVENT_TABLE_SIZE(kabylake); + break; case PMC_CPU_INTEL_IVYBRIDGE: ev = ivybridge_event_table; evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge); @@ -3715,6 +3908,9 @@ default: /* Unknown CPU type. */ break; } + } else if (pe == PMC_EV_CORESIGHT_CORESIGHT) { + ev = coresight_event_table; + evfence = coresight_event_table + PMC_EVENT_TABLE_SIZE(coresight); } else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) { ev = mips24k_event_table; evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k); @@ -3736,6 +3932,9 @@ } else if (pe == PMC_EV_TSC_TSC) { ev = tsc_event_table; evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); + } else if (pe == PMC_EV_PT_PT) { + ev = pt_event_table; + evfence = pt_event_table + PMC_EVENT_TABLE_SIZE(pt); } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) { ev = soft_event_table; evfence = soft_event_table + soft_event_info.pm_nevent; @@ -3852,6 +4051,68 @@ return (0); } +int +pmc_proc_unsuspend(pmc_id_t pmc, pid_t pid) +{ + struct pmc_op_proc_unsuspend u; + + u.pm_pmcid = pmc; + u.pm_pid = pid; + + return (PMC_CALL(THREAD_UNSUSPEND, &u)); +} + +int +pmc_read_trace(uint32_t cpu, pmc_id_t pmc, + pmc_value_t *cycle, pmc_value_t *offset) +{ + struct pmc_op_trace_read pmc_trace_read; + + pmc_trace_read.pm_pmcid = pmc; + pmc_trace_read.pm_cpu = cpu; + pmc_trace_read.pm_cycle = 0; + pmc_trace_read.pm_offset = 0; + + if (PMC_CALL(TRACE_READ, &pmc_trace_read) < 0) + return (-1); + + *cycle = pmc_trace_read.pm_cycle; + *offset = pmc_trace_read.pm_offset; + + return (0); +} + +int +pmc_trace_config(uint32_t cpu, pmc_id_t pmc, + uint64_t *ranges, uint32_t nranges) +{ + struct pmc_op_trace_config trc; + + trc.pm_pmcid = pmc; + trc.pm_cpu = cpu; + trc.nranges = nranges; + + if (nranges > PMC_FILTER_MAX_IP_RANGES) + return (-1); + + memcpy(&trc.ranges, ranges, sizeof(uint64_t) * 2 * nranges); + + if (PMC_CALL(TRACE_CONFIG, &trc) < 0) + return (-1); + + return (0); +} + +int +pmc_log_kmap(pmc_id_t pmc) +{ + struct pmc_op_simple pmc_log_km; + + pmc_log_km.pm_pmcid = pmc; + + return (PMC_CALL(LOG_KERNEL_MAP, &pmc_log_km)); +} + int pmc_release(pmc_id_t pmc) { Index: lib/libpmc/pmc.h =================================================================== --- lib/libpmc/pmc.h +++ lib/libpmc/pmc.h @@ -77,6 +77,7 @@ int pmc_allocate(const char *_ctrspec, enum pmc_mode _mode, uint32_t _flags, int _cpu, pmc_id_t *_pmcid); int pmc_attach(pmc_id_t _pmcid, pid_t _pid); +int pmc_proc_unsuspend(pmc_id_t pmc, pid_t pid); int pmc_capabilities(pmc_id_t _pmc, uint32_t *_caps); int pmc_configure_logfile(int _fd); int pmc_flush_logfile(void); @@ -88,7 +89,10 @@ int pmc_get_msr(pmc_id_t _pmc, uint32_t *_msr); int pmc_init(void); int pmc_read(pmc_id_t _pmc, pmc_value_t *_value); +int pmc_read_trace(uint32_t cpu, pmc_id_t pmc, pmc_value_t *cycle, pmc_value_t *offset); +int pmc_trace_config(uint32_t cpu, pmc_id_t pmc, uint64_t *ranges, uint32_t nranges); int pmc_release(pmc_id_t _pmc); +int pmc_log_kmap(pmc_id_t pmc); int pmc_rw(pmc_id_t _pmc, pmc_value_t _newvalue, pmc_value_t *_oldvalue); int pmc_set(pmc_id_t _pmc, pmc_value_t _value); int pmc_start(pmc_id_t _pmc); Index: sys/dev/hwpmc/pmc_events.h =================================================================== --- sys/dev/hwpmc/pmc_events.h +++ sys/dev/hwpmc/pmc_events.h @@ -4843,6 +4843,20 @@ #define PMC_EV_TSC_FIRST PMC_EV_TSC_TSC #define PMC_EV_TSC_LAST PMC_EV_TSC_TSC +/* Intel PT */ +#define __PMC_EV_PT() \ + __PMC_EV(PT, PT) + +#define PMC_EV_PT_FIRST PMC_EV_PT_PT +#define PMC_EV_PT_LAST PMC_EV_PT_PT + +/* ARM CORESIGHT */ +#define __PMC_EV_CORESIGHT() \ + __PMC_EV(CORESIGHT, CORESIGHT) + +#define PMC_EV_CORESIGHT_FIRST PMC_EV_CORESIGHT_CORESIGHT +#define PMC_EV_CORESIGHT_LAST PMC_EV_CORESIGHT_CORESIGHT + /* * Software events are dynamically defined. */ @@ -7141,6 +7155,7 @@ * START #EVENTS DESCRIPTION * 0 0x1000 Reserved * 0x1000 0x0001 TSC + * 0x1100 0x0001 PT * 0x2000 0x0080 AMD K7 events * 0x2080 0x0100 AMD K8 events * 0x10000 0x0080 INTEL architectural fixed-function events @@ -7157,11 +7172,14 @@ * 0x13300 0x00FF Freescale e500 events * 0x14000 0x0100 ARMv7 events * 0x14100 0x0100 ARMv8 events + * 0x14200 0x0001 ARM Coresight * 0x20000 0x1000 Software events */ #define __PMC_EVENTS() \ __PMC_EV_BLOCK(TSC, 0x01000) \ __PMC_EV_TSC() \ + __PMC_EV_BLOCK(PT, 0x1100) \ + __PMC_EV_PT() \ __PMC_EV_BLOCK(K7, 0x2000) \ __PMC_EV_K7() \ __PMC_EV_BLOCK(K8, 0x2080) \ @@ -7197,7 +7215,9 @@ __PMC_EV_BLOCK(ARMV7, 0x14000) \ __PMC_EV_ARMV7() \ __PMC_EV_BLOCK(ARMV8, 0x14100) \ - __PMC_EV_ARMV8() + __PMC_EV_ARMV8() \ + __PMC_EV_BLOCK(CORESIGHT, 0x14200) \ + __PMC_EV_CORESIGHT() #define PMC_EVENT_FIRST PMC_EV_TSC_TSC #define PMC_EVENT_LAST PMC_EV_SOFT_LAST