Skip to content

Commit b9da553

Browse files
committed
hwpmc: Initial support for AMD IBS
This patch adds support for AMD IBS. It adds a new class of performance counter that cotains two events: ibs-fetch and ibs-op events. Unlike most existing sampled events, IBS events provide a number of values containing extra information regarding the sample. To support this we use the existing callchain event, and introduce a new flag for multipart payloads. The first 8 bytes of the pc_sample contains a header that defines up to four payloads. Sponsored by: Netflix
1 parent 9352d2f commit b9da553

File tree

14 files changed

+1130
-32
lines changed

14 files changed

+1130
-32
lines changed

lib/libpmc/libpmc.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
#if defined(__amd64__) || defined(__i386__)
5151
static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
5252
struct pmc_op_pmcallocate *_pmc_config);
53-
#endif
54-
#if defined(__amd64__) || defined(__i386__)
53+
static int ibs_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54+
struct pmc_op_pmcallocate *_pmc_config);
5555
static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
5656
struct pmc_op_pmcallocate *_pmc_config);
5757
#endif
@@ -132,6 +132,7 @@ struct pmc_class_descr {
132132

133133
PMC_CLASSDEP_TABLE(iaf, IAF);
134134
PMC_CLASSDEP_TABLE(k8, K8);
135+
PMC_CLASSDEP_TABLE(ibs, IBS);
135136
PMC_CLASSDEP_TABLE(armv7, ARMV7);
136137
PMC_CLASSDEP_TABLE(armv8, ARMV8);
137138
PMC_CLASSDEP_TABLE(cmn600_pmu, CMN600_PMU);
@@ -201,8 +202,7 @@ static const struct pmc_class_descr NAME##_class_table_descr = \
201202

202203
#if defined(__i386__) || defined(__amd64__)
203204
PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
204-
#endif
205-
#if defined(__i386__) || defined(__amd64__)
205+
PMC_CLASS_TABLE_DESC(ibs, IBS, ibs, ibs);
206206
PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
207207
#endif
208208
#if defined(__arm__)
@@ -691,9 +691,49 @@ k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
691691
return (0);
692692
}
693693

694-
#endif
694+
static int
695+
ibs_allocate_pmc(enum pmc_event pe, char *ctrspec,
696+
struct pmc_op_pmcallocate *pmc_config)
697+
{
698+
char *e, *p, *q;
699+
uint64_t ctl;
700+
701+
pmc_config->pm_caps |=
702+
(PMC_CAP_SYSTEM | PMC_CAP_EDGE | PMC_CAP_PRECISE);
703+
pmc_config->pm_md.pm_ibs.ibs_ctl = 0;
704+
705+
/* setup parsing tables */
706+
switch (pe) {
707+
case PMC_EV_IBS_FETCH:
708+
pmc_config->pm_md.pm_ibs.ibs_type = IBS_PMC_FETCH;
709+
break;
710+
case PMC_EV_IBS_OP:
711+
pmc_config->pm_md.pm_ibs.ibs_type = IBS_PMC_OP;
712+
break;
713+
default:
714+
return (-1);
715+
}
716+
717+
/* parse parameters */
718+
while ((p = strsep(&ctrspec, ",")) != NULL) {
719+
if (KWPREFIXMATCH(p, "ctl=")) {
720+
q = strchr(p, '=');
721+
if (*++q == '\0') /* skip '=' */
722+
return (-1);
723+
724+
ctl = strtoull(q, &e, 0);
725+
if (e == q || *e != '\0')
726+
return (-1);
727+
728+
pmc_config->pm_md.pm_ibs.ibs_ctl |= ctl;
729+
} else {
730+
return (-1);
731+
}
732+
}
733+
734+
return (0);
735+
}
695736

696-
#if defined(__i386__) || defined(__amd64__)
697737
static int
698738
tsc_allocate_pmc(enum pmc_event pe, char *ctrspec,
699739
struct pmc_op_pmcallocate *pmc_config)
@@ -1268,6 +1308,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
12681308
ev = k8_event_table;
12691309
count = PMC_EVENT_TABLE_SIZE(k8);
12701310
break;
1311+
case PMC_CLASS_IBS:
1312+
ev = ibs_event_table;
1313+
count = PMC_EVENT_TABLE_SIZE(ibs);
1314+
break;
12711315
case PMC_CLASS_ARMV7:
12721316
switch (cpu_info.pm_cputype) {
12731317
default:
@@ -1471,6 +1515,10 @@ pmc_init(void)
14711515
case PMC_CLASS_K8:
14721516
pmc_class_table[n++] = &k8_class_table_descr;
14731517
break;
1518+
1519+
case PMC_CLASS_IBS:
1520+
pmc_class_table[n++] = &ibs_class_table_descr;
1521+
break;
14741522
#endif
14751523

14761524
case PMC_CLASS_SOFT:
@@ -1676,7 +1724,9 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
16761724
if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
16771725
ev = k8_event_table;
16781726
evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
1679-
1727+
} else if (pe >= PMC_EV_IBS_FIRST && pe <= PMC_EV_IBS_LAST) {
1728+
ev = ibs_event_table;
1729+
evfence = ibs_event_table + PMC_EVENT_TABLE_SIZE(ibs);
16801730
} else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) {
16811731
switch (cpu) {
16821732
case PMC_CPU_ARMV7_CORTEX_A8:

sys/amd64/include/pmc_mdep.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct pmc_mdep;
4141

4242
#include <dev/hwpmc/hwpmc_amd.h>
4343
#include <dev/hwpmc/hwpmc_core.h>
44+
#include <dev/hwpmc/hwpmc_ibs.h>
4445
#include <dev/hwpmc/hwpmc_tsc.h>
4546
#include <dev/hwpmc/hwpmc_uncore.h>
4647

@@ -51,6 +52,7 @@ struct pmc_mdep;
5152
*/
5253
#define PMC_MDEP_CLASS_INDEX_TSC 1
5354
#define PMC_MDEP_CLASS_INDEX_K8 2
55+
#define PMC_MDEP_CLASS_INDEX_IBS 3
5456
#define PMC_MDEP_CLASS_INDEX_P4 2
5557
#define PMC_MDEP_CLASS_INDEX_IAP 2
5658
#define PMC_MDEP_CLASS_INDEX_IAF 3
@@ -62,6 +64,7 @@ struct pmc_mdep;
6264
*
6365
* TSC The timestamp counter
6466
* K8 AMD Athlon64 and Opteron PMCs in 64 bit mode.
67+
* IBS AMD IBS
6568
* PIV Intel P4/HTT and P4/EMT64
6669
* IAP Intel Core/Core2/Atom CPUs in 64 bits mode.
6770
* IAF Intel fixed-function PMCs in Core2 and later CPUs.
@@ -71,6 +74,7 @@ struct pmc_mdep;
7174

7275
union pmc_md_op_pmcallocate {
7376
struct pmc_md_amd_op_pmcallocate pm_amd;
77+
struct pmc_md_ibs_op_pmcallocate pm_ibs;
7478
struct pmc_md_iap_op_pmcallocate pm_iap;
7579
struct pmc_md_ucf_op_pmcallocate pm_ucf;
7680
struct pmc_md_ucp_op_pmcallocate pm_ucp;
@@ -85,6 +89,7 @@ union pmc_md_op_pmcallocate {
8589

8690
union pmc_md_pmc {
8791
struct pmc_md_amd_pmc pm_amd;
92+
struct pmc_md_ibs_pmc pm_ibs;
8893
struct pmc_md_iaf_pmc pm_iaf;
8994
struct pmc_md_iap_pmc pm_iap;
9095
struct pmc_md_ucf_pmc pm_ucf;

sys/conf/files.x86

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ dev/hptrr/hptrr_osm_bsd.c optional hptrr
114114
dev/hptrr/hptrr_config.c optional hptrr
115115
dev/hptrr/$M-elf.hptrr_lib.o optional hptrr
116116
dev/hwpmc/hwpmc_amd.c optional hwpmc
117+
dev/hwpmc/hwpmc_ibs.c optional hwpmc
117118
dev/hwpmc/hwpmc_intel.c optional hwpmc
118119
dev/hwpmc/hwpmc_core.c optional hwpmc
119120
dev/hwpmc/hwpmc_uncore.c optional hwpmc

sys/dev/hwpmc/hwpmc_amd.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ amd_intr(struct trapframe *tf)
536536

537537
pac = amd_pcpu[cpu];
538538

539+
retval = pmc_ibs_intr(tf);
540+
if (retval)
541+
goto done;
542+
539543
/*
540544
* look for all PMCs that have interrupted:
541545
* - look for a running, sampling PMC which has overflowed
@@ -606,6 +610,7 @@ amd_intr(struct trapframe *tf)
606610
}
607611
}
608612

613+
done:
609614
if (retval)
610615
counter_u64_add(pmc_stats.pm_intr_processed, 1);
611616
else
@@ -753,7 +758,7 @@ pmc_amd_initialize(void)
753758
struct pmc_classdep *pcd;
754759
struct pmc_mdep *pmc_mdep;
755760
enum pmc_cputype cputype;
756-
int error, i, ncpus;
761+
int error, i, ncpus, nclasses;
757762
int family, model, stepping;
758763
int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs;
759764
struct amd_descr *d;
@@ -869,10 +874,16 @@ pmc_amd_initialize(void)
869874
M_WAITOK | M_ZERO);
870875

871876
/*
872-
* These processors have two classes of PMCs: the TSC and
873-
* programmable PMCs.
877+
* These processors have two or three classes of PMCs: the TSC,
878+
* programmable PMCs, and AMD IBS.
874879
*/
875-
pmc_mdep = pmc_mdep_alloc(2);
880+
if ((amd_feature2 & AMDID2_IBS) != 0) {
881+
nclasses = 3;
882+
} else {
883+
nclasses = 2;
884+
}
885+
886+
pmc_mdep = pmc_mdep_alloc(nclasses);
876887

877888
ncpus = pmc_cpu_max();
878889

@@ -912,6 +923,12 @@ pmc_amd_initialize(void)
912923

913924
PMCDBG0(MDP, INI, 0, "amd-initialize");
914925

926+
if (nclasses >= 3) {
927+
error = pmc_ibs_initialize(pmc_mdep, ncpus);
928+
if (error != 0)
929+
goto error;
930+
}
931+
915932
return (pmc_mdep);
916933

917934
error:

0 commit comments

Comments
 (0)