Blob Blame History Raw
commit 488227bf2128e8b80f9b7573869fe33fcbd63342
Author: Stephane Eranian <eranian@gmail.com>
Date:   Fri Jun 2 12:09:31 2017 -0700

    add Intel Broadwell server uncore PMUs support
    
    This patch adds Intel Broadwell Server (model 79, 86) uncore PMU
    support.  It adds the following PMUs:
    
    - IMC
    - CBOX
    - HA
    - UBOX
    - SBOX
    - IRP
    - PCU
    - QPI
    - R2PCIE
    - R3QPI
    
    Based on Broadwell Server Uncore Performance Monitoring Reference Manual
    available here:
            http://www.intel.com/content/www/us/en/processors/xeon/xeon-e5-e7-v4-uncore-performance-monitoring.html
    
    Signed-off-by: Stephane Eranian <eranian@gmail.com>

diff --git a/docs/Makefile b/docs/Makefile
index f8f8838..45f3f16 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -81,7 +81,18 @@ ARCH_MAN=libpfm_intel_core.3	\
 	 libpfm_intel_hswep_unc_r2pcie.3 \
 	 libpfm_intel_hswep_unc_r3qpi.3 \
 	 libpfm_intel_hswep_unc_sbo.3 \
-	 libpfm_intel_hswep_unc_ubo.3
+	 libpfm_intel_hswep_unc_ubo.3  \
+	 libpfm_intel_bdx_unc_cbo.3 \
+	 libpfm_intel_bdx_unc_ha.3 \
+	 libpfm_intel_bdx_unc_imc.3 \
+	 libpfm_intel_bdx_unc_irp.3 \
+	 libpfm_intel_bdx_unc_pcu.3 \
+	 libpfm_intel_bdx_unc_qpi.3 \
+	 libpfm_intel_bdx_unc_r2pcie.3 \
+	 libpfm_intel_bdx_unc_r3qpi.3 \
+	 libpfm_intel_bdx_unc_sbo.3 \
+	 libpfm_intel_bdx_unc_ubo.3
+
 
 ifeq ($(CONFIG_PFMLIB_ARCH_I386),y)
 ARCH_MAN += libpfm_intel_p6.3 libpfm_intel_coreduo.3
diff --git a/docs/man3/libpfm_intel_bdx_unc_cbo.3 b/docs/man3/libpfm_intel_bdx_unc_cbo.3
new file mode 100644
index 0000000..668226b
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_cbo.3
@@ -0,0 +1,79 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_cbo - support for Intel Broadwell Server C-Box uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_cbo[0-21]
+.B PMU desc: Intel Broadwell Server C-Box uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server C-Box (coherency engine) uncore PMU.
+This PMU model exists on various Broadwell server models (79, 86) . There is one C-box
+PMU per physical core. Therefore there are up to twenty-one identical C-Box PMU instances
+numbered from 0 to 21. On dual-socket systems, the number refers to the C-Box
+PMU on the socket where the program runs. For instance, if running on CPU18, then
+bdx_unc_cbo0 refers to the C-Box for physical core 0 on socket 1. Conversely,
+if running on CPU0, then the same bdx_unc_cbo0 refers to the C-Box for physical
+core 0 but on socket 0.
+
+Each C-Box PMU implements 4 generic counters and two filter registers used only
+with certain events and umasks.
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell C-Box uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of C-Box cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:255].
+.TP
+.B nf
+Node filter. Certain events, such as UNC_C_LLC_LOOKUP, UNC_C_LLC_VICTIMS, provide a \fBNID\fR umask.
+Sometimes the \fBNID\fR is combined with other filtering capabilities, such as opcodes.
+The node filter is an 8-bit max bitmask. A node corresponds to a processor
+socket. The legal values therefore depend on the underlying hardware configuration. For
+dual-socket systems, the bitmask has two valid bits [0:1].
+.TP
+.B cf
+Core Filter. This is a 5-bit filter which is used to filter based on physical core origin
+of the C-Box request. Possible values are 0-63. If the filter is not specified, then no
+filtering takes place. Bit  0-3 indicate  the physical core id and bit 4 filters on non
+thread-related data.
+.TP
+.B tf
+Thread Filter. This is a 1-bit filter which is used to filter C-Box requests based on logical
+processor (hyper-thread) identification. Possibles values are 0-1. If the filter is not
+specified, then no filtering takes place.
+.TP
+.B nc
+Non-Coherent. This is a 1-bit filter which is used to filter C-Box requests only for the
+TOR_INSERTS and TOR_OCCUPANCY umasks using the OPCODE matcher. If the filter is not
+specified, then no filtering takes place.
+.TP
+.B isoc
+Isochronous. This is a 1-bit filter which is used to filter C-Box requests only for the
+TOR_INSERTS and TOR_OCCUPANCY umasks using the OPCODE matcher. If the filter is not
+specified, then no filtering takes place.
+
+.SH Opcode filtering
+
+Certain events, such as UNC_C_TOR_INSERTS supports opcode matching on the C-BOX transaction
+type. To use this feature, first an opcode matching umask must be selected, e.g., MISS_OPCODE.
+Second, the opcode to match on must be selected via a second umask among the OPC_* umasks.
+For instance, UNC_C_TOR_INSERTS:OPCODE:OPC_RFO, counts the number of TOR insertions for RFO
+transactions.
+
+Opcode matching may be combined with node filtering with certain umasks. In general, the
+filtering support is encoded into the umask name, e.g., NID_OPCODE supports both
+node and opcode filtering. For instance, UNC_C_TOR_INSERTS:NID_OPCODE:OPC_RFO:nf=1.
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_ha.3 b/docs/man3/libpfm_intel_bdx_unc_ha.3
new file mode 100644
index 0000000..b1c0eb2
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_ha.3
@@ -0,0 +1,35 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_ha - support for Intel Broadwell Server Home Agent (HA) uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_ha0, bdx_unc_ha1
+.B PMU desc: Intel Broadwell Server HA uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server Home Agent (HA) uncore PMU.
+This PMU model only exists on various Broadwell models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server HA uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of HA cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:255].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_imc.3 b/docs/man3/libpfm_intel_bdx_unc_imc.3
new file mode 100644
index 0000000..2baa153
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_imc.3
@@ -0,0 +1,34 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_imc - support for Intel Broadwell Server Integrated Memory Controller (IMC)  uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_imc[0-7]
+.B PMU desc: Intel Broadwell Server IMC uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server Integrated Memory Controller (IMC) uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server IMC uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of IMC cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:255].
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_irp.3 b/docs/man3/libpfm_intel_bdx_unc_irp.3
new file mode 100644
index 0000000..d3902c2
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_irp.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_irp - support for Intel Broadwell Server IRP uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_irp
+.B PMU desc: Intel Broadwell Server IRP uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server IRP (IIO coherency) uncore PMU .
+This PMU model only exists various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server IRP uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:255].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_pcu.3 b/docs/man3/libpfm_intel_bdx_unc_pcu.3
new file mode 100644
index 0000000..eb7565a
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_pcu.3
@@ -0,0 +1,50 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_pcu - support for Intel Broadwell Server Power Controller Unit (PCU) uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_pcu
+.B PMU desc: Intel Broadwell Server PCU uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server Power Controller Unit uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server PCU uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of HA cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:15].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+.TP
+.B ff
+Enable frequency band filtering. This modifier applies only to the UNC_P_FREQ_BANDx_CYCLES events, where x is [0-3].
+The modifiers expects an integer in the range [0-255]. The value is interpreted as a frequency value to be
+multiplied by 100Mhz. Thus if the value is 32, then all cycles where the processor is running at 3.2GHz and more are
+counted.
+
+.SH Frequency band filtering
+
+There are 3 events which support frequency band filtering, namely, UNC_P_FREQ_BAND0_CYCLES, UNC_P_FREQ_BAND1_CYCLES,
+UNC_P_FREQ_BAND2_CYCLES, UNC_P_FREQ_BAND3_CYCLES. The frequency filter (available via the ff modifier) is stored into
+a PMU shared register which hold all 4 possible frequency bands, one per event. However, the library generate the
+encoding for each event individually because it processes events one at a time. The caller or the underlying kernel
+interface may have to merge the band filter settings to program the filter register properly.
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_qpi.3 b/docs/man3/libpfm_intel_bdx_unc_qpi.3
new file mode 100644
index 0000000..ef3f318
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_qpi.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_qpi - support for Intel Broadwell Server  QPI uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_qpi0, bdx_unc_qpi1
+.B PMU desc: Intel Broadwell Server QPI uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell Server QPI uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Broadwell server QPI uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of QPI cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:255].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_r2pcie.3 b/docs/man3/libpfm_intel_bdx_unc_r2pcie.3
new file mode 100644
index 0000000..fe8bac5
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_r2pcie.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_r2pcie - support for Intel Broadwell Server R2 PCIe  uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_r2pcie
+.B PMU desc: Intel Broadwell Server  R2 PCIe  uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell server R2 PCIe uncore PMU.
+This PMU model only exists on Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server R2PCIe uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of R2PCIe cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:15].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_r3qpi.3 b/docs/man3/libpfm_intel_bdx_unc_r3qpi.3
new file mode 100644
index 0000000..6fff0b2
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_r3qpi.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_r3qpi - support for Intel Broadwell Server R3QPI uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_r3qpi[0-2]
+.B PMU desc: Intel Broadwell server R3QPI uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell server R3QPI uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server R3PQI  uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of R3QPI cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:15].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_sbo.3 b/docs/man3/libpfm_intel_bdx_unc_sbo.3
new file mode 100644
index 0000000..262e553
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_sbo.3
@@ -0,0 +1,42 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_sbo - support for Intel Broadwell Server S-Box uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_sbo
+.B PMU desc: Intel Broadwell Server S-Box uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell server Ring Transfer unit (S-Box) uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server S-Box uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of HA cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:15].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/docs/man3/libpfm_intel_bdx_unc_ubo.3 b/docs/man3/libpfm_intel_bdx_unc_ubo.3
new file mode 100644
index 0000000..d8fc1ca
--- /dev/null
+++ b/docs/man3/libpfm_intel_bdx_unc_ubo.3
@@ -0,0 +1,36 @@
+.TH LIBPFM 3  "June, 2017" "" "Linux Programmer's Manual"
+.SH NAME
+libpfm_intel_bdx_unc_ubo - support for Intel Broadwell Server U-Box uncore PMU
+.SH SYNOPSIS
+.nf
+.B #include <perfmon/pfmlib.h>
+.sp
+.B PMU name: bdx_unc_ubo
+.B PMU desc: Intel Broadwell Server U-Box uncore PMU
+.sp
+.SH DESCRIPTION
+The library supports the Intel Broadwell server system configuration unit (U-Box) uncore PMU.
+This PMU model only exists on various Broadwell server models (79, 86).
+
+.SH MODIFIERS
+The following modifiers are supported on Intel Broadwell server U-Box uncore PMU:
+.TP
+.B e
+Enable edge detection, i.e., count only when there is a state transition from no occurrence of the event to at least one occurrence. This modifier must be combined with a threshold modifier (t) with a value greater or equal to one.  This is a boolean modifier.
+.TP
+.B t
+Set the threshold value. When set to a non-zero value, the counter counts the number
+of HA cycles in which the number of occurrences of the event is greater or equal to
+the threshold.  This is an integer modifier with values in the range [0:15].
+.TP
+.B i
+Invert the meaning of the threshold or edge filter. If set, the event counts when strictly less
+than N occurrences occur per cycle if threshold is set to N. When invert is set, then threshold
+must be set to non-zero value. If set, the event counts when the event transitions from occurring
+to not occurring (falling edge) when edge detection is set. This is a boolean modifier
+
+.SH AUTHORS
+.nf
+Stephane Eranian <eranian@gmail.com>
+.if
+.PP
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index 89ab973..61a7d90 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -369,8 +369,58 @@ typedef enum {
 	PFM_PMU_INTEL_KNL_UNC_M2PCIE,	/* Intel KnightLanding M2PCIe uncore */
 
 	PFM_PMU_POWER9,			/* IBM POWER9 */
+
+	PFM_PMU_INTEL_BDX_UNC_CB0,	/* Intel Broadwell-X C-Box core 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB1,	/* Intel Broadwell-X C-Box core 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB2,	/* Intel Broadwell-X C-Box core 2 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB3,	/* Intel Broadwell-X C-Box core 3 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB4,	/* Intel Broadwell-X C-Box core 4 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB5,	/* Intel Broadwell-X C-Box core 5 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB6,	/* Intel Broadwell-X C-Box core 6 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB7,	/* Intel Broadwell-X C-Box core 7 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB8,	/* Intel Broadwell-X C-Box core 8 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB9,	/* Intel Broadwell-X C-Box core 9 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB10,	/* Intel Broadwell-X C-Box core 10 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB11,	/* Intel Broadwell-X C-Box core 11 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB12,	/* Intel Broadwell-X C-Box core 12 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB13,	/* Intel Broadwell-X C-Box core 13 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB14,	/* Intel Broadwell-X C-Box core 14 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB15,	/* Intel Broadwell-X C-Box core 15 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB16,	/* Intel Broadwell-X C-Box core 16 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB17,	/* Intel Broadwell-X C-Box core 17 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB18,	/* Intel Broadwell-X C-Box core 18 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB19,	/* Intel Broadwell-X C-Box core 19 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB20,	/* Intel Broadwell-X C-Box core 20 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB21,	/* Intel Broadwell-X C-Box core 21 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB22,	/* Intel Broadwell-X C-Box core 22 uncore */
+	PFM_PMU_INTEL_BDX_UNC_CB23,	/* Intel Broadwell-X C-Box core 23 uncore */
+	PFM_PMU_INTEL_BDX_UNC_HA0,	/* Intel Broadwell-X HA 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_HA1,	/* Intel Broadwell-X HA 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC0,	/* Intel Broadwell-X IMC socket 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC1,	/* Intel Broadwell-X IMC socket 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC2,	/* Intel Broadwell-X IMC socket 2 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC3,	/* Intel Broadwell-X IMC socket 3 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC4,	/* Intel Broadwell-X IMC socket 4 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC5,	/* Intel Broadwell-X IMC socket 5 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC6,	/* Intel Broadwell-X IMC socket 6 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IMC7,	/* Intel Broadwell-X IMC socket 7 uncore */
+	PFM_PMU_INTEL_BDX_UNC_PCU,	/* Intel Broadwell-X PCU uncore */
+	PFM_PMU_INTEL_BDX_UNC_QPI0,	/* Intel Broadwell-X QPI link 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_QPI1,	/* Intel Broadwell-X QPI link 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_QPI2,	/* Intel Broadwell-X QPI link 2 uncore */
+	PFM_PMU_INTEL_BDX_UNC_UBOX,	/* Intel Broadwell-X U-Box uncore */
+	PFM_PMU_INTEL_BDX_UNC_R2PCIE,	/* Intel Broadwell-X R2PCIe uncore */
+	PFM_PMU_INTEL_BDX_UNC_R3QPI0,	/* Intel Broadwell-X R3QPI 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_R3QPI1,	/* Intel Broadwell-X R3QPI 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_R3QPI2,	/* Intel Broadwell-X R3QPI 2 uncore */
+	PFM_PMU_INTEL_BDX_UNC_IRP,	/* Intel Broadwell-X IRP uncore */
+	PFM_PMU_INTEL_BDX_UNC_SB0,	/* Intel Broadwell-X S-Box 0 uncore */
+	PFM_PMU_INTEL_BDX_UNC_SB1,	/* Intel Broadwell-X S-Box 1 uncore */
+	PFM_PMU_INTEL_BDX_UNC_SB2,	/* Intel Broadwell-X S-Box 2 uncore */
+	PFM_PMU_INTEL_BDX_UNC_SB3,	/* Intel Broadwell-X S-Box 3 uncore */
 	/* MUST ADD NEW PMU MODELS HERE */
 
+
 	PFM_PMU_MAX			/* end marker */
 } pfm_pmu_t;
 
diff --git a/lib/Makefile b/lib/Makefile
index f532561..aa21ccb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -91,6 +91,16 @@ SRCS   += pfmlib_amd64.c pfmlib_intel_core.c pfmlib_intel_x86.c \
 	  pfmlib_intel_hswep_unc_r3qpi.c \
 	  pfmlib_intel_hswep_unc_irp.c \
 	  pfmlib_intel_hswep_unc_sbo.c \
+	  pfmlib_intel_bdx_unc_cbo.c \
+	  pfmlib_intel_bdx_unc_ubo.c \
+	  pfmlib_intel_bdx_unc_sbo.c \
+	  pfmlib_intel_bdx_unc_ha.c \
+	  pfmlib_intel_bdx_unc_imc.c \
+	  pfmlib_intel_bdx_unc_irp.c \
+	  pfmlib_intel_bdx_unc_pcu.c \
+	  pfmlib_intel_bdx_unc_qpi.c \
+	  pfmlib_intel_bdx_unc_r2pcie.c \
+	  pfmlib_intel_bdx_unc_r3qpi.c \
 	  pfmlib_intel_knc.c \
 	  pfmlib_intel_slm.c \
 	  pfmlib_intel_knl.c \
@@ -275,6 +285,16 @@ INC_X86= pfmlib_intel_x86_priv.h	\
 	events/intel_hswep_unc_r2pcie_events.h \
 	events/intel_hswep_unc_r3qpi_events.h \
 	events/intel_hswep_unc_irp_events.h \
+	events/intel_bdx_unc_cbo_events.h \
+	events/intel_bdx_unc_ubo_events.h \
+	events/intel_bdx_unc_sbo_events.h \
+	events/intel_bdx_unc_ha_events.h \
+	events/intel_bdx_unc_imc_events.h \
+	events/intel_bdx_unc_irp_events.h \
+	events/intel_bdx_unc_pcu_events.h \
+	events/intel_bdx_unc_qpi_events.h \
+	events/intel_bdx_unc_r2pcie_events.h \
+	events/intel_bdx_unc_r3qpi_events.h \
 	events/intel_knl_unc_imc_events.h \
 	events/intel_knl_unc_edc_events.h \
 	events/intel_knl_unc_cha_events.h \
diff --git a/lib/events/intel_bdx_unc_cbo_events.h b/lib/events/intel_bdx_unc_cbo_events.h
new file mode 100644
index 0000000..7aa362c
--- /dev/null
+++ b/lib/events/intel_bdx_unc_cbo_events.h
@@ -0,0 +1,1167 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_cbo
+ */
+
+#define CBO_FILT_MESIF(a, b, c, d) \
+   { .uname  = "STATE_"#a,\
+     .udesc  = #b" cacheline state",\
+     .ufilters[0] = 1ULL << (17 + (c)),\
+     .grpid = d, \
+   }
+
+#define CBO_FILT_MESIFS(d) \
+   CBO_FILT_MESIF(I, Invalid, 0, d), \
+   CBO_FILT_MESIF(S, Shared, 1, d), \
+   CBO_FILT_MESIF(E, Exclusive, 2, d), \
+   CBO_FILT_MESIF(M, Modified, 3, d), \
+   CBO_FILT_MESIF(F, Forward, 4, d), \
+   CBO_FILT_MESIF(D, Debug, 5, d), \
+   { .uname  = "STATE_MP",\
+     .udesc  = "Cacheline is modified but never written, was forwarded in modified state",\
+     .ufilters[0] = 0x1ULL << (17+6),\
+     .grpid = d, \
+     .uflags = INTEL_X86_NCOMBO, \
+   }, \
+   { .uname  = "STATE_MESIFD",\
+     .udesc  = "Any cache line state",\
+     .ufilters[0] = 0x7fULL << 17,\
+     .grpid = d, \
+     .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL, \
+   }
+
+#define CBO_FILT_OPC(d) \
+   { .uname  = "OPC_RFO",\
+     .udesc  = "Demand data RFO (combine with any OPCODE umask)",\
+     .ufilters[1] = 0x180ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_CRD",\
+     .udesc  = "Demand code read (combine with any OPCODE umask)",\
+     .ufilters[1] = 0x181ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_DRD",\
+     .udesc  = "Demand data read (combine with any OPCODE umask)",\
+     .ufilters[1] = 0x182ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PRD",\
+     .udesc  = "Partial reads (UC) (combine with any OPCODE umask)",\
+     .ufilters[1] = 0x187ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_WCILF",\
+     .udesc  = "Full Stream store (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x18cULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_WCIL",\
+     .udesc  = "Partial Stream store (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x18dULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_WIL",\
+     .udesc  = "Write Invalidate Line (Partial) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x18fULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PF_RFO",\
+     .udesc  = "Prefetch RFO into LLC but do not pass to L2 (includes hints) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x190ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PF_CODE",\
+     .udesc  = "Prefetch code into LLC but do not pass to L2 (includes hints) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x191ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PF_DATA",\
+     .udesc  = "Prefetch data into LLC but do not pass to L2 (includes hints) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x192ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCIWIL",\
+     .udesc  = "PCIe write (partial, non-allocating) - partial line MMIO write transactions from IIO (P2P). Not used for coherent transacions. Uncacheable. (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x193ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCIWIF",\
+     .udesc  = "PCIe write (full, non-allocating) - full line MMIO write transactions from IIO (P2P). Not used for coherent transacions. Uncacheable. (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x194ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCIITOM",\
+     .udesc  = "PCIe write (allocating) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x19cULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCIRDCUR",\
+     .udesc  = "PCIe read current (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x19eULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_WBMTOI",\
+     .udesc  = "Request writeback modified invalidate line (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1c4ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_WBMTOE",\
+     .udesc  = "Request writeback modified set to exclusive (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1c5ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_ITOM",\
+     .udesc  = "Request invalidate line. Request exclusive ownership of the line  (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1c8ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCINSRD",\
+     .udesc  = "PCIe non-snoop read (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1e4ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCINSWR",\
+     .udesc  = "PCIe non-snoop write (partial) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1e5ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }, \
+   { .uname  = "OPC_PCINSWRF",\
+     .udesc  = "PCIe non-snoop write (full) (combine with any OPCODE umask)", \
+     .ufilters[1] = 0x1e6ULL << 20, \
+     .uflags = INTEL_X86_NCOMBO, \
+     .grpid = d, \
+   }
+
+
+static intel_x86_umask_t bdx_unc_c_llc_lookup[]={
+	{ .uname = "ANY",
+	  .ucode = 0x1100,
+	  .udesc = "Cache Lookups -- Any Request",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	  .grpid  = 0,
+	},
+	{ .uname = "DATA_READ",
+	  .ucode = 0x300,
+	  .udesc = "Cache Lookups -- Data Read Request",
+	  .grpid  = 0,
+	},
+	{ .uname = "NID",
+	  .ucode = 0x4100,
+	  .udesc = "Cache Lookups -- Lookups that Match NID",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .grpid  = 1,
+	  .uflags = INTEL_X86_GRP_DFL_NONE
+	},
+	{ .uname = "READ",
+	  .ucode = 0x2100,
+	  .udesc = "Cache Lookups -- Any Read Request",
+	  .grpid  = 0,
+	},
+	{ .uname = "REMOTE_SNOOP",
+	  .ucode = 0x900,
+	  .udesc = "Cache Lookups -- External Snoop Request",
+	  .grpid  = 0,
+	},
+	{ .uname = "WRITE",
+	  .ucode = 0x500,
+	  .udesc = "Cache Lookups -- Write Requests",
+	  .grpid  = 0,
+	},
+	CBO_FILT_MESIFS(2),
+};
+
+static intel_x86_umask_t bdx_unc_c_llc_victims[]={
+	{ .uname = "F_STATE",
+	  .ucode = 0x800,
+	  .udesc = "Lines in Forward state",
+	  .grpid = 0,
+	},
+	{ .uname = "I_STATE",
+	  .ucode = 0x400,
+	  .udesc = "Lines in S State",
+	  .grpid = 0,
+	},
+	{ .uname = "S_STATE",
+	  .ucode = 0x400,
+	  .udesc = "Lines in S state",
+	  .grpid = 0,
+	},
+	{ .uname = "E_STATE",
+	  .ucode = 0x200,
+	  .udesc = "Lines in E state",
+	  .grpid = 0,
+	},
+	{ .uname = "M_STATE",
+	  .ucode = 0x100,
+	  .udesc = "Lines in M state",
+	  .grpid = 0,
+	},
+	{ .uname = "MISS",
+	  .ucode = 0x1000,
+	  .udesc = "Lines Victimized",
+	  .grpid = 0,
+	},
+	{ .uname = "NID",
+	  .ucode = 0x4000,
+	  .udesc = "Lines Victimized -- Victimized Lines that Match NID",
+	  .uflags = INTEL_X86_GRP_DFL_NONE,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .grpid = 1,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_misc[]={
+	{ .uname = "CVZERO_PREFETCH_MISS",
+	  .ucode = 0x2000,
+	  .udesc = "Cbo Misc -- DRd hitting non-M with raw CV=0",
+	},
+	{ .uname = "CVZERO_PREFETCH_VICTIM",
+	  .ucode = 0x1000,
+	  .udesc = "Cbo Misc -- Clean Victim with raw CV=0",
+	},
+	{ .uname = "RFO_HIT_S",
+	  .ucode = 0x800,
+	  .udesc = "Cbo Misc -- RFO HitS",
+	},
+	{ .uname = "RSPI_WAS_FSE",
+	  .ucode = 0x100,
+	  .udesc = "Cbo Misc -- Silent Snoop Eviction",
+	},
+	{ .uname = "STARTED",
+	  .ucode = 0x400,
+	  .udesc = "Cbo Misc -- ",
+	},
+	{ .uname = "WC_ALIASING",
+	  .ucode = 0x200,
+	  .udesc = "Cbo Misc -- Write Combining Aliasing",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_ring_ad_used[]={
+	{ .uname = "ALL",
+	  .ucode = 0xf00,
+	  .udesc = "AD Ring In Use -- All",
+	},
+	{ .uname = "CCW",
+	  .ucode = 0xc00,
+	  .udesc = "AD Ring In Use -- Down",
+	},
+	{ .uname = "CW",
+	  .ucode = 0x300,
+	  .udesc = "AD Ring In Use -- Up",
+	},
+	{ .uname = "DOWN_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "AD Ring In Use -- Down and Even",
+	},
+	{ .uname = "DOWN_ODD",
+	  .ucode = 0x800,
+	  .udesc = "AD Ring In Use -- Down and Odd",
+	},
+	{ .uname = "UP_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "AD Ring In Use -- Up and Even",
+	},
+	{ .uname = "UP_ODD",
+	  .ucode = 0x200,
+	  .udesc = "AD Ring In Use -- Up and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_ring_ak_used[]={
+	{ .uname = "ALL",
+	  .ucode = 0xf00,
+	  .udesc = "AK Ring In Use -- All",
+	},
+	{ .uname = "CCW",
+	  .ucode = 0xc00,
+	  .udesc = "AK Ring In Use -- Down",
+	},
+	{ .uname = "CW",
+	  .ucode = 0x300,
+	  .udesc = "AK Ring In Use -- Up",
+	},
+	{ .uname = "DOWN_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "AK Ring In Use -- Down and Even",
+	},
+	{ .uname = "DOWN_ODD",
+	  .ucode = 0x800,
+	  .udesc = "AK Ring In Use -- Down and Odd",
+	},
+	{ .uname = "UP_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "AK Ring In Use -- Up and Even",
+	},
+	{ .uname = "UP_ODD",
+	  .ucode = 0x200,
+	  .udesc = "AK Ring In Use -- Up and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_ring_bl_used[]={
+	{ .uname = "ALL",
+	  .ucode = 0xf00,
+	  .udesc = "BL Ring in Use -- Down",
+	},
+	{ .uname = "CCW",
+	  .ucode = 0xc00,
+	  .udesc = "BL Ring in Use -- Down",
+	},
+	{ .uname = "CW",
+	  .ucode = 0x300,
+	  .udesc = "BL Ring in Use -- Up",
+	},
+	{ .uname = "DOWN_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "BL Ring in Use -- Down and Even",
+	},
+	{ .uname = "DOWN_ODD",
+	  .ucode = 0x800,
+	  .udesc = "BL Ring in Use -- Down and Odd",
+	},
+	{ .uname = "UP_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "BL Ring in Use -- Up and Even",
+	},
+	{ .uname = "UP_ODD",
+	  .ucode = 0x200,
+	  .udesc = "BL Ring in Use -- Up and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_ring_bounces[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- AD",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x200,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- AK",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- BL",
+	},
+	{ .uname = "IV",
+	  .ucode = 0x1000,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- Snoops of processors cachee.",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_ring_iv_used[]={
+	{ .uname = "ANY",
+	  .ucode = 0xf00,
+	  .udesc = "BL Ring in Use -- Any",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "DN",
+	  .ucode = 0xc00,
+	  .udesc = "BL Ring in Use -- Any",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "DOWN",
+	  .ucode = 0xcc00,
+	  .udesc = "BL Ring in Use -- Down",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "UP",
+	  .ucode = 0x300,
+	  .udesc = "BL Ring in Use -- Any",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_ext_starved[]={
+	{ .uname = "IPQ",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Arbiter Blocking Cycles -- IRQ",
+	},
+	{ .uname = "IRQ",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Arbiter Blocking Cycles -- IPQ",
+	},
+	{ .uname = "ISMQ_BIDS",
+	  .ucode = 0x800,
+	  .udesc = "Ingress Arbiter Blocking Cycles -- ISMQ_BID",
+	},
+	{ .uname = "PRQ",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Arbiter Blocking Cycles -- PRQ",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_inserts[]={
+	{ .uname = "IPQ",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Allocations -- IPQ",
+	},
+	{ .uname = "IRQ",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Allocations -- IRQ",
+	},
+	{ .uname = "IRQ_REJ",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Allocations -- IRQ Rejected",
+	},
+	{ .uname = "PRQ",
+	  .ucode = 0x1000,
+	  .udesc = "Ingress Allocations -- PRQ",
+	},
+	{ .uname = "PRQ_REJ",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Allocations -- PRQ",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_ipq_retry[]={
+	{ .uname = "ADDR_CONFLICT",
+	  .ucode = 0x400,
+	  .udesc = "Probe Queue Retries -- Address Conflict",
+	},
+	{ .uname = "ANY",
+	  .ucode = 0x100,
+	  .udesc = "Probe Queue Retries -- Any Reject",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname = "FULL",
+	  .ucode = 0x200,
+	  .udesc = "Probe Queue Retries -- No Egress Credits",
+	},
+	{ .uname = "QPI_CREDITS",
+	  .ucode = 0x1000,
+	  .udesc = "Probe Queue Retries -- No QPI Credits",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_ipq_retry2[]={
+	{ .uname = "AD_SBO",
+	  .ucode = 0x100,
+	  .udesc = "Probe Queue Retries -- No AD Sbo Credits",
+	},
+	{ .uname = "TARGET",
+	  .ucode = 0x4000,
+	  .udesc = "Probe Queue Retries -- Target Node Filter",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_irq_retry[]={
+	{ .uname = "ADDR_CONFLICT",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Request Queue Rejects -- Address Conflict",
+	},
+	{ .uname = "ANY",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Request Queue Rejects -- Any Reject",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname = "FULL",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Request Queue Rejects -- No Egress Credits",
+	},
+	{ .uname = "IIO_CREDITS",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Request Queue Rejects -- No IIO Credits",
+	},
+	{ .uname = "NID",
+	  .ucode = 0x4000,
+	  .udesc = "Ingress Request Queue Rejects -- ",
+	},
+	{ .uname = "QPI_CREDITS",
+	  .ucode = 0x1000,
+	  .udesc = "Ingress Request Queue Rejects -- No QPI Credits",
+	},
+	{ .uname = "RTID",
+	  .ucode = 0x800,
+	  .udesc = "Ingress Request Queue Rejects -- No RTIDs",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_irq_retry2[]={
+	{ .uname = "AD_SBO",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Request Queue Rejects -- No AD Sbo Credits",
+	},
+	{ .uname = "BL_SBO",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Request Queue Rejects -- No BL Sbo Credits",
+	},
+	{ .uname = "TARGET",
+	  .ucode = 0x4000,
+	  .udesc = "Ingress Request Queue Rejects -- Target Node Filter",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_ismq_retry[]={
+	{ .uname = "ANY",
+	  .ucode = 0x100,
+	  .udesc = "ISMQ Retries -- Any Reject",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname = "FULL",
+	  .ucode = 0x200,
+	  .udesc = "ISMQ Retries -- No Egress Credits",
+	},
+	{ .uname = "IIO_CREDITS",
+	  .ucode = 0x2000,
+	  .udesc = "ISMQ Retries -- No IIO Credits",
+	},
+	{ .uname = "NID",
+	  .ucode = 0x4000,
+	  .udesc = "ISMQ Retries -- ",
+	},
+	{ .uname = "QPI_CREDITS",
+	  .ucode = 0x1000,
+	  .udesc = "ISMQ Retries -- No QPI Credits",
+	},
+	{ .uname = "RTID",
+	  .ucode = 0x800,
+	  .udesc = "ISMQ Retries -- No RTIDs",
+	},
+	{ .uname = "WB_CREDITS",
+	  .ucode = 0x8000,
+	  .udesc = "ISMQ Retries -- ",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_ismq_retry2[]={
+	{ .uname = "AD_SBO",
+	  .ucode = 0x100,
+	  .udesc = "ISMQ Request Queue Rejects -- No AD Sbo Credits",
+	},
+	{ .uname = "BL_SBO",
+	  .ucode = 0x200,
+	  .udesc = "ISMQ Request Queue Rejects -- No BL Sbo Credits",
+	},
+	{ .uname = "TARGET",
+	  .ucode = 0x4000,
+	  .udesc = "ISMQ Request Queue Rejects -- Target Node Filter",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_rxr_occupancy[]={
+	{ .uname = "IPQ",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Occupancy -- IPQ",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "IRQ",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Occupancy -- IRQ",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "IRQ_REJ",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Occupancy -- IRQ Rejected",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "PRQ_REJ",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Occupancy -- PRQ Rejects",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_sbo_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "SBo Credits Acquired -- For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "SBo Credits Acquired -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_sbo_credit_occupancy[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "SBo Credits Occupancy -- For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "SBo Credits Occupancy -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_tor_inserts[]={
+	{ .uname = "ALL",
+	  .ucode = 0x800,
+	  .udesc = "All",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "EVICTION",
+	  .ucode = 0x400,
+	  .udesc = "Evictions",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "LOCAL",
+	  .ucode = 0x2800,
+	  .udesc = "Local Memory",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "LOCAL_OPCODE",
+	  .ucode = 0x2100,
+	  .udesc = "Local Memory - Opcode Matched",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_LOCAL",
+	  .ucode = 0x2a00,
+	  .udesc = "Misses to Local Memory",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_LOCAL_OPCODE",
+	  .ucode = 0x2300,
+	  .udesc = "Misses to Local Memory - Opcode Matched",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_OPCODE",
+	  .ucode = 0x300,
+	  .udesc = "Miss Opcode Match",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_REMOTE",
+	  .ucode = 0x8a00,
+	  .udesc = "Misses to Remote Memory",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_REMOTE_OPCODE",
+	  .ucode = 0x8300,
+	  .udesc = "Misses to Remote Memory - Opcode Matched",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_ALL",
+	  .ucode = 0x4800,
+	  .udesc = "NID Matched",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_EVICTION",
+	  .ucode = 0x4400,
+	  .udesc = "NID Matched Evictions",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_MISS_ALL",
+	  .ucode = 0x4a00,
+	  .udesc = "NID Matched Miss All",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_MISS_OPCODE",
+	  .ucode = 0x4300,
+	  .udesc = "NID and Opcode Matched Miss",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_OPCODE",
+	  .ucode = 0x4100,
+	  .udesc = "NID and Opcode Matched",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_WB",
+	  .ucode = 0x5000,
+	  .udesc = "NID Matched Writebacks",
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "OPCODE",
+	  .ucode = 0x100,
+	  .udesc = "Opcode Match",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "REMOTE",
+	  .ucode = 0x8800,
+	  .udesc = "Remote Memory",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "REMOTE_OPCODE",
+	  .ucode = 0x8100,
+	  .udesc = "Remote Memory - Opcode Matched",
+	  .uflags = INTEL_X86_NCOMBO,
+	  .grpid  = 0,
+	},
+	{ .uname = "WB",
+	  .ucode = 0x1000,
+	  .udesc = "Writebacks",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+ 	CBO_FILT_OPC(1)
+};
+
+static intel_x86_umask_t bdx_unc_c_tor_occupancy[]={
+	{ .uname = "ALL",
+	  .ucode = 0x800,
+	  .udesc = "Any",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL | INTEL_X86_EXCL_GRP_GT,
+	  .grpid  = 0,
+	},
+	{ .uname = "EVICTION",
+	  .ucode = 0x400,
+	  .udesc = "Evictions",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "LOCAL",
+	  .ucode = 0x2800,
+	  .udesc  = "Number of transactions in the TOR that are satisfied by locally homed memory",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "LOCAL_OPCODE",
+	  .ucode = 0x2100,
+	  .udesc = "Local Memory - Opcode Matched",
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_ALL",
+	  .ucode = 0xa00,
+	  .udesc = "Miss All",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "MISS_LOCAL",
+	  .ucode = 0x2a00,
+	  .udesc  = "Number of miss transactions in the TOR that are satisfied by locally homed memory",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "MISS_LOCAL_OPCODE",
+	  .ucode = 0x2300,
+	  .udesc  = "Number of miss opcode-matched transactions inserted into the TOR that are satisfied by locally homed memory",
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_OPCODE",
+	  .ucode = 0x300,
+	  .udesc  = "Number of miss transactions inserted into the TOR that match an opcode (must provide opc_* umask)",
+	  .grpid  = 0,
+	},
+	{ .uname = "MISS_REMOTE_OPCODE",
+	  .ucode = 0x8300,
+	  .udesc  = "Number of miss opcode-matched transactions inserted into the TOR that are satisfied by remote caches or memory",
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_ALL",
+	  .ucode = 0x4800,
+	  .udesc  = "Number of NID-matched transactions inserted into the TOR (must provide nf=X modifier)",
+	  .grpid  = 0,
+	},
+	{ .uname = "NID_EVICTION",
+	  .ucode = 0x4400,
+	  .udesc  = "Number of NID-matched eviction transactions inserted into the TOR (must provide nf=X modifier)",
+	  .grpid  = 0,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "NID_MISS_ALL",
+	  .ucode = 0x4a00,
+	  .udesc  = "Number of NID-matched miss transactions that were inserted into the TOR (must provide nf=X modifier)",
+	  .grpid  = 0,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "NID_MISS_OPCODE",
+	  .ucode = 0x4300,
+	  .udesc  = "Number of NID and opcode matched miss transactions inserted into the TOR (must provide opc_* umask and nf=X modifier)",
+	  .grpid  = 0,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "NID_OPCODE",
+	  .ucode = 0x4100,
+	  .udesc  = "Number of transactions inserted into the TOR that match a NID and opcode (must provide opc_* umask and nf=X modifier)",
+	  .grpid  = 0,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "NID_WB",
+	  .ucode = 0x5000,
+	  .udesc  = "Number of NID-matched write back transactions inserted into the TOR (must provide nf=X modifier)",
+	  .grpid  = 0,
+	  .umodmsk_req = _SNBEP_UNC_ATTR_NF1,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "OPCODE",
+	  .ucode = 0x100,
+	  .udesc  = "Number of transactions inserted into the TOR that match an opcode (must provide opc_* umask)",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "REMOTE",
+	  .ucode = 0x8800,
+	  .udesc  = "Number of transactions inserted into the TOR that are satisfied by remote caches or memory",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "REMOTE_OPCODE",
+	  .ucode = 0x8100,
+	  .udesc  = "Number of opcode-matched transactions inserted into the TOR that are satisfied by remote caches or memory",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "WB",
+	  .ucode = 0x1000,
+	  .udesc  = "Number of write transactions inserted into the TOR",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	{ .uname = "MISS_REMOTE",
+	  .ucode = 0x8a00,
+	  .udesc  = "Number of miss transactions inserted into the TOR that are satisfied by remote caches or memory",
+	  .grpid  = 0,
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_EXCL_GRP_GT,
+	},
+	CBO_FILT_OPC(1)
+};
+
+static intel_x86_umask_t bdx_unc_c_txr_ads_used[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "Onto AD Ring",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x200,
+	  .udesc = "Onto AK Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "Onto BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_c_txr_inserts[]={
+	{ .uname = "AD_CACHE",
+	  .ucode = 0x100,
+	  .udesc = "Egress Allocations -- AD - Cachebo",
+	},
+	{ .uname = "AD_CORE",
+	  .ucode = 0x1000,
+	  .udesc = "Egress Allocations -- AD - Corebo",
+	},
+	{ .uname = "AK_CACHE",
+	  .ucode = 0x200,
+	  .udesc = "Egress Allocations -- AK - Cachebo",
+	},
+	{ .uname = "AK_CORE",
+	  .ucode = 0x2000,
+	  .udesc = "Egress Allocations -- AK - Corebo",
+	},
+	{ .uname = "BL_CACHE",
+	  .ucode = 0x400,
+	  .udesc = "Egress Allocations -- BL - Cacheno",
+	},
+	{ .uname = "BL_CORE",
+	  .ucode = 0x4000,
+	  .udesc = "Egress Allocations -- BL - Corebo",
+	},
+	{ .uname = "IV_CACHE",
+	  .ucode = 0x800,
+	  .udesc = "Egress Allocations -- IV - Cachebo",
+	},
+};
+
+
+static intel_x86_entry_t intel_bdx_unc_c_pe[]={
+  { .name   = "UNC_C_BOUNCE_CONTROL",
+    .code   = 0xa,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_C_CLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "Clock ticks",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_C_COUNTER0_OCCUPANCY",
+    .code   = 0x1f,
+    .desc   = "Since occupancy counts can only be captured in the Cbos 0 counter, this event allows a user to capture occupancy related information by filtering the Cb0 occupancy count captured in Counter 0. The filtering available is found in the control register - threshold, invert and edge detect.   E.g. setting threshold to 1 can effectively monitor how many cycles the monitored queue has an entryy.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_C_FAST_ASSERTED",
+    .code   = 0x9,
+    .desc   = "Counts the number of cycles either the local distress or incoming distress signals are asserted.  Incoming distress includes both up and dn.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_C_LLC_LOOKUP",
+    .code   = 0x34,
+    .desc   = "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2.  This has numerous filters available.  Note the non-standard filtering equation.  This event will count requests that lookup the cache multiple times with multiple increments.  One must ALWAYS set umask bit 0 and select a state or states to match.  Otherwise, the event will count nothing.   CBoGlCtrl[22:18] bits correspond to [FMESI] state.",
+    .modmsk = BDX_UNC_CBO_NID_ATTRS,
+    .flags  = INTEL_X86_NO_AUTOENCODE,
+    .cntmsk = 0xf,
+    .ngrp   = 3,
+    .umasks = bdx_unc_c_llc_lookup,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_llc_lookup),
+  },
+  { .name   = "UNC_C_LLC_VICTIMS",
+    .code   = 0x37,
+    .desc   = "Counts the number of lines that were victimized on a fill.  This can be filtered by the state that the line was in.",
+    .modmsk = BDX_UNC_CBO_NID_ATTRS,
+    .flags  = INTEL_X86_NO_AUTOENCODE,
+    .cntmsk = 0xf,
+    .ngrp   = 2,
+    .umasks = bdx_unc_c_llc_victims,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_llc_victims),
+  },
+  { .name   = "UNC_C_MISC",
+    .code   = 0x39,
+    .desc   = "Miscellaneous events in the Cbo.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_misc,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_misc),
+  },
+  { .name   = "UNC_C_RING_AD_USED",
+    .code   = 0x1b,
+    .desc   = "Counts the number of cycles that the AD ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.  We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_ring_ad_used),
+  },
+  { .name   = "UNC_C_RING_AK_USED",
+    .code   = 0x1c,
+    .desc   = "Counts the number of cycles that the AK ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_ring_ak_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_ring_ak_used),
+  },
+  { .name   = "UNC_C_RING_BL_USED",
+    .code   = 0x1d,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_ring_bl_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_ring_bl_used),
+  },
+  { .name   = "UNC_C_RING_BOUNCES",
+    .code   = 0x5,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_ring_bounces,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_ring_bounces),
+  },
+  { .name   = "UNC_C_RING_IV_USED",
+    .code   = 0x1e,
+    .desc   = "Counts the number of cycles that the IV ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.  There is only 1 IV ring in BDX  Therefore, if one wants to monitor the Even ring, they should select both UP_EVEN and DN_EVEN.  To monitor the Odd ring, they should select both UP_ODD and DN_ DN_ODD.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_ring_iv_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_ring_iv_used),
+  },
+  { .name   = "UNC_C_RING_SRC_THRTL",
+    .code   = 0x7,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_C_RXR_EXT_STARVED",
+    .code   = 0x12,
+    .desc   = "Counts cycles in external starvation.  This occurs when one of the ingress queues is being starved by the other queues.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_ext_starved,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_ext_starved),
+  },
+  { .name   = "UNC_C_RXR_INSERTS",
+    .code   = 0x13,
+    .desc   = "Counts number of allocations per cycle into the specified Ingress queue.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_inserts),
+  },
+  { .name   = "UNC_C_RXR_IPQ_RETRY",
+    .code   = 0x31,
+    .desc   = "Number of times a snoop (probe) request had to retry.  Filters exist to cover some of the common cases retries.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_ipq_retry,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_ipq_retry),
+  },
+  { .name   = "UNC_C_RXR_IPQ_RETRY2",
+    .code   = 0x28,
+    .desc   = "Number of times a snoop (probe) request had to retry.  Filters exist to cover some of the common cases retries.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_ipq_retry2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_ipq_retry2),
+  },
+  { .name   = "UNC_C_RXR_IRQ_RETRY",
+    .code   = 0x32,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_irq_retry,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_irq_retry),
+  },
+  { .name   = "UNC_C_RXR_IRQ_RETRY2",
+    .code   = 0x29,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_irq_retry2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_irq_retry2),
+  },
+  { .name   = "UNC_C_RXR_ISMQ_RETRY",
+    .code   = 0x33,
+    .desc   = "Number of times a transaction flowing through the ISMQ had to retry.  Transaction pass through the ISMQ as responses for requests that already exist in the Cbo.  Some examples include: when data is returned or when snoop responses come back from the cores.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_ismq_retry,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_ismq_retry),
+  },
+  { .name   = "UNC_C_RXR_ISMQ_RETRY2",
+    .code   = 0x2a,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_ismq_retry2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_ismq_retry2),
+  },
+  { .name   = "UNC_C_RXR_OCCUPANCY",
+    .code   = 0x11,
+    .desc   = "Counts number of entries in the specified Ingress queue in each cycle.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_rxr_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_rxr_occupancy),
+  },
+  { .name   = "UNC_C_SBO_CREDITS_ACQUIRED",
+    .code   = 0x3d,
+    .desc   = "Number of Sbo credits acquired in a given cycle, per ring.  Each Cbo is assigned an Sbo it can communicate with.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_sbo_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_sbo_credits_acquired),
+  },
+  { .name   = "UNC_C_SBO_CREDIT_OCCUPANCY",
+    .code   = 0x3e,
+    .desc   = "Number of Sbo credits in use in a given cycle, per ring.  Each Cbo is assigned an Sbo it can communicate with.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_sbo_credit_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_sbo_credit_occupancy),
+  },
+  { .name   = "UNC_C_TOR_INSERTS",
+    .code   = 0x35,
+    .desc   = "Counts the number of entries successfuly inserted into the TOR that match  qualifications specified by the subevent.  There are a number of subevent filters but only a subset of the subevent combinations are valid.  Subevents that require an opcode or NID match require the Cn_MSR_PMON_BOX_FILTER.{opc, nid} field to be set.  If, for example, one wanted to count DRD Local Misses, one should select MISS_OPC_MATCH and set Cn_MSR_PMON_BOX_FILTER.opc  to DRD (0x1(0x182).",
+    .modmsk = BDX_UNC_CBO_NID_ATTRS | _SNBEP_UNC_ATTR_ISOC | _SNBEP_UNC_ATTR_NC,
+    .flags  = INTEL_X86_NO_AUTOENCODE,
+    .cntmsk = 0xf,
+    .ngrp   = 2,
+    .umasks = bdx_unc_c_tor_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_tor_inserts),
+  },
+  { .name   = "UNC_C_TOR_OCCUPANCY",
+    .code   = 0x36,
+    .desc   = "For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent.   There are a number of subevent filters but only a subset of the subevent combinations are valid.  Subevents that require an opcode or NID match require the Cn_MSR_PMON_BOX_FILTER.{opc, nid} field to be set.  If, for example, one wanted to count DRD Local Misses, one should select MISS_OPC_MATCH and set Cn_MSR_PMON_BOX_FILTER.opc to DRD (0x (0x182)",
+    .modmsk = BDX_UNC_CBO_NID_ATTRS | _SNBEP_UNC_ATTR_ISOC | _SNBEP_UNC_ATTR_NC,
+    .flags  = INTEL_X86_NO_AUTOENCODE,
+    .cntmsk = 0x1,
+    .ngrp   = 2,
+    .umasks = bdx_unc_c_tor_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_tor_occupancy),
+  },
+  { .name   = "UNC_C_TXR_ADS_USED",
+    .code   = 0x4,
+    .desc   = "",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_txr_ads_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_txr_ads_used),
+  },
+  { .name   = "UNC_C_TXR_INSERTS",
+    .code   = 0x2,
+    .desc   = "Number of allocations into the Cbo Egress.  The Egress is used to queue up requests destined for the ring.",
+    .modmsk = BDX_UNC_CBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_c_txr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_c_txr_inserts),
+  },
+};
+
diff --git a/lib/events/intel_bdx_unc_ha_events.h b/lib/events/intel_bdx_unc_ha_events.h
new file mode 100644
index 0000000..6266bef
--- /dev/null
+++ b/lib/events/intel_bdx_unc_ha_events.h
@@ -0,0 +1,1159 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_ha
+ */
+
+static intel_x86_umask_t bdx_unc_h_bypass_imc[]={
+	{ .uname = "NOT_TAKEN",
+	  .ucode = 0x200,
+	  .udesc = "HA to iMC Bypass -- Not Taken",
+	},
+	{ .uname = "TAKEN",
+	  .ucode = 0x100,
+	  .udesc = "HA to iMC Bypass -- Taken",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_directory_lookup[]={
+	{ .uname = "NO_SNP",
+	  .ucode = 0x200,
+	  .udesc = "Directory Lookups -- Snoop Not Needed",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x100,
+	  .udesc = "Directory Lookups -- Snoop Needed",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_directory_update[]={
+	{ .uname  = "ANY",
+	  .ucode  = 0x300,
+	  .udesc  = "Directory Updates -- Any Directory Update",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "CLEAR",
+	  .ucode = 0x200,
+	  .udesc = "Directory Updates -- Directory Clear",
+	},
+	{ .uname = "SET",
+	  .ucode = 0x100,
+	  .udesc = "Directory Updates -- Directory Set",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_hitme_hit[]={
+	{ .uname = "ACKCNFLTWBI",
+	  .ucode = 0x400,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is AckCnfltWbI",
+	},
+	{ .uname  = "ALL",
+	  .ucode  = 0xff00,
+	  .udesc  = "Counts Number of Hits in HitMe Cache -- All Requests",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname  = "ALLOCS",
+	  .ucode  = 0x7000,
+	  .udesc  = "Counts Number of Hits in HitMe Cache -- Allocations",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "EVICTS",
+	  .ucode  = 0x4200,
+	  .udesc  = "Counts Number of Hits in HitMe Cache -- Allocations",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "HOM",
+	  .ucode  = 0xf00,
+	  .udesc  = "Counts Number of Hits in HitMe Cache -- HOM Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "INVALS",
+	  .ucode  = 0x2600,
+	  .udesc  = "Counts Number of Hits in HitMe Cache -- Invalidations",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "READ_OR_INVITOE",
+	  .ucode = 0x100,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is RdCode, RdData, RdDataMigratory, RdInvOwn, RdCur or InvItoE",
+	},
+	{ .uname = "RSP",
+	  .ucode = 0x8000,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is RspI, RspIWb, RspS, RspSWb, RspCnflt or RspCnfltWbI",
+	},
+	{ .uname = "RSPFWDI_LOCAL",
+	  .ucode = 0x2000,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is RspIFwd or RspIFwdWb for a local request",
+	},
+	{ .uname = "RSPFWDI_REMOTE",
+	  .ucode = 0x1000,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is RspIFwd or RspIFwdWb for a remote request",
+	},
+	{ .uname = "RSPFWDS",
+	  .ucode = 0x4000,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is RsSFwd or RspSFwdWb",
+	},
+	{ .uname = "WBMTOE_OR_S",
+	  .ucode = 0x800,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is WbMtoE or WbMtoS",
+	},
+	{ .uname = "WBMTOI",
+	  .ucode = 0x200,
+	  .udesc = "Counts Number of Hits in HitMe Cache -- op is WbMtoI",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_hitme_hit_pv_bits_set[]={
+	{ .uname = "ACKCNFLTWBI",
+	  .ucode = 0x400,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is AckCnfltWbI",
+	},
+	{ .uname  = "ALL",
+	  .ucode  = 0xff00,
+	  .udesc  = "Accumulates Number of PV bits set on HitMe Cache Hits -- All Requests",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "HOM",
+	  .ucode = 0xf00,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- HOM Requests",
+	},
+	{ .uname = "READ_OR_INVITOE",
+	  .ucode = 0x100,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is RdCode, RdData, RdDataMigratory, RdInvOwn, RdCur or InvItoE",
+	},
+	{ .uname = "RSP",
+	  .ucode = 0x8000,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is RspI, RspIWb, RspS, RspSWb, RspCnflt or RspCnfltWbI",
+	},
+	{ .uname = "RSPFWDI_LOCAL",
+	  .ucode = 0x2000,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is RspIFwd or RspIFwdWb for a local request",
+	},
+	{ .uname = "RSPFWDI_REMOTE",
+	  .ucode = 0x1000,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is RspIFwd or RspIFwdWb for a remote request",
+	},
+	{ .uname = "RSPFWDS",
+	  .ucode = 0x4000,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is RsSFwd or RspSFwdWb",
+	},
+	{ .uname = "WBMTOE_OR_S",
+	  .ucode = 0x800,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is WbMtoE or WbMtoS",
+	},
+	{ .uname = "WBMTOI",
+	  .ucode = 0x200,
+	  .udesc = "Accumulates Number of PV bits set on HitMe Cache Hits -- op is WbMtoI",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_hitme_lookup[]={
+	{ .uname = "ACKCNFLTWBI",
+	  .ucode = 0x400,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is AckCnfltWbI",
+	},
+	{ .uname  = "ALL",
+	  .ucode  = 0xff00,
+	  .udesc  = "Counts Number of times HitMe Cache is accessed -- All Requests",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "ALLOCS",
+	  .ucode = 0x7000,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- Allocations",
+	},
+	{ .uname  = "HOM",
+	  .ucode  = 0xf00,
+	  .udesc  = "Counts Number of times HitMe Cache is accessed -- HOM Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "INVALS",
+	  .ucode  = 0x2600,
+	  .udesc  = "Counts Number of times HitMe Cache is accessed -- Invalidations",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "READ_OR_INVITOE",
+	  .ucode = 0x100,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is RdCode, RdData, RdDataMigratory, RdInvOwn, RdCur or InvItoE",
+	},
+	{ .uname = "RSP",
+	  .ucode = 0x8000,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is RspI, RspIWb, RspS, RspSWb, RspCnflt or RspCnfltWbI",
+	},
+	{ .uname = "RSPFWDI_LOCAL",
+	  .ucode = 0x2000,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is RspIFwd or RspIFwdWb for a local request",
+	},
+	{ .uname = "RSPFWDI_REMOTE",
+	  .ucode = 0x1000,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is RspIFwd or RspIFwdWb for a remote request",
+	},
+	{ .uname = "RSPFWDS",
+	  .ucode = 0x4000,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is RsSFwd or RspSFwdWb",
+	},
+	{ .uname = "WBMTOE_OR_S",
+	  .ucode = 0x800,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is WbMtoE or WbMtoS",
+	},
+	{ .uname = "WBMTOI",
+	  .ucode = 0x200,
+	  .udesc = "Counts Number of times HitMe Cache is accessed -- op is WbMtoI",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_igr_no_credit_cycles[]={
+	{ .uname = "AD_QPI0",
+	  .ucode = 0x100,
+	  .udesc = "Cycles without QPI Ingress Credits -- AD to QPI Link 0",
+	},
+	{ .uname = "AD_QPI1",
+	  .ucode = 0x200,
+	  .udesc = "Cycles without QPI Ingress Credits -- AD to QPI Link 1",
+	},
+	{ .uname = "AD_QPI2",
+	  .ucode = 0x1000,
+	  .udesc = "Cycles without QPI Ingress Credits -- BL to QPI Link 0",
+	},
+	{ .uname = "BL_QPI0",
+	  .ucode = 0x400,
+	  .udesc = "Cycles without QPI Ingress Credits -- BL to QPI Link 0",
+	},
+	{ .uname = "BL_QPI1",
+	  .ucode = 0x800,
+	  .udesc = "Cycles without QPI Ingress Credits -- BL to QPI Link 1",
+	},
+	{ .uname = "BL_QPI2",
+	  .ucode = 0x2000,
+	  .udesc = "Cycles without QPI Ingress Credits -- BL to QPI Link 1",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_imc_reads[]={
+	{ .uname  = "NORMAL",
+	  .ucode  = 0x100,
+	  .udesc  = "HA to iMC Normal Priority Reads Issued -- Normal Priority",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_imc_writes[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0xf00,
+	  .udesc  = "HA to iMC Full Line Writes Issued -- All Writes",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "FULL",
+	  .ucode = 0x100,
+	  .udesc = "HA to iMC Full Line Writes Issued -- Full Line Non-ISOCH",
+	},
+	{ .uname = "FULL_ISOCH",
+	  .ucode = 0x400,
+	  .udesc = "HA to iMC Full Line Writes Issued -- ISOCH Full Line",
+	},
+	{ .uname = "PARTIAL",
+	  .ucode = 0x200,
+	  .udesc = "HA to iMC Full Line Writes Issued -- Partial Non-ISOCH",
+	},
+	{ .uname = "PARTIAL_ISOCH",
+	  .ucode = 0x800,
+	  .udesc = "HA to iMC Full Line Writes Issued -- ISOCH Partial",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_osb[]={
+	{ .uname = "CANCELLED",
+	  .ucode = 0x1000,
+	  .udesc = "OSB Snoop Broadcast -- Cancelled",
+	},
+	{ .uname = "INVITOE_LOCAL",
+	  .ucode = 0x400,
+	  .udesc = "OSB Snoop Broadcast -- Local InvItoE",
+	},
+	{ .uname = "READS_LOCAL",
+	  .ucode = 0x200,
+	  .udesc = "OSB Snoop Broadcast -- Local Reads",
+	},
+	{ .uname = "READS_LOCAL_USEFUL",
+	  .ucode = 0x2000,
+	  .udesc = "OSB Snoop Broadcast -- Reads Local -  Useful",
+	},
+	{ .uname = "REMOTE",
+	  .ucode = 0x800,
+	  .udesc = "OSB Snoop Broadcast -- Remote",
+	},
+	{ .uname = "REMOTE_USEFUL",
+	  .ucode = 0x4000,
+	  .udesc = "OSB Snoop Broadcast -- Remote - Useful",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_osb_edr[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0x100,
+	  .udesc  = "OSB Early Data Return -- All",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "READS_LOCAL_I",
+	  .ucode = 0x200,
+	  .udesc = "OSB Early Data Return -- Reads to Local  I",
+	},
+	{ .uname = "READS_LOCAL_S",
+	  .ucode = 0x800,
+	  .udesc = "OSB Early Data Return -- Reads to Local S",
+	},
+	{ .uname = "READS_REMOTE_I",
+	  .ucode = 0x400,
+	  .udesc = "OSB Early Data Return -- Reads to Remote I",
+	},
+	{ .uname = "READS_REMOTE_S",
+	  .ucode = 0x1000,
+	  .udesc = "OSB Early Data Return -- Reads to Remote S",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_requests[]={
+	{ .uname = "INVITOE_LOCAL",
+	  .ucode = 0x1000,
+	  .udesc = "Read and Write Requests -- Local InvItoEs",
+	},
+	{ .uname = "INVITOE_REMOTE",
+	  .ucode = 0x2000,
+	  .udesc = "Read and Write Requests -- Remote InvItoEs",
+	},
+	{ .uname  = "READS",
+	  .ucode  = 0x300,
+	  .udesc  = "Read and Write Requests -- Reads",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "READS_LOCAL",
+	  .ucode = 0x100,
+	  .udesc = "Read and Write Requests -- Local Reads",
+	},
+	{ .uname = "READS_REMOTE",
+	  .ucode = 0x200,
+	  .udesc = "Read and Write Requests -- Remote Reads",
+	},
+	{ .uname  = "WRITES",
+	  .ucode  = 0xc00,
+	  .udesc  = "Read and Write Requests -- Writes",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "WRITES_LOCAL",
+	  .ucode = 0x400,
+	  .udesc = "Read and Write Requests -- Local Writes",
+	},
+	{ .uname = "WRITES_REMOTE",
+	  .ucode = 0x800,
+	  .udesc = "Read and Write Requests -- Remote Writes",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_ring_ad_used[]={
+	{ .uname = "CCW",
+	  .ucode = 0xc00,
+	  .udesc = "Counterclockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CCW_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "Counterclockwise and Even",
+	},
+	{ .uname = "CCW_ODD",
+	  .ucode = 0x800,
+	  .udesc = "Counterclockwise and Odd",
+	},
+	{ .uname  = "CW",
+	  .ucode  = 0x300,
+	  .udesc  = "Clockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CW_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "Clockwise and Even",
+	},
+	{ .uname = "CW_ODD",
+	  .ucode = 0x200,
+	  .udesc = "Clockwise and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_rpq_cycles_no_reg_credits[]={
+	{ .uname  = "CHN0",
+	  .ucode  = 0x100,
+	  .udesc  = "iMC RPQ Credits Empty - Regular -- Channel 0",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN1",
+	  .ucode  = 0x200,
+	  .udesc  = "iMC RPQ Credits Empty - Regular -- Channel 1",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN2",
+	  .ucode  = 0x400,
+	  .udesc  = "iMC RPQ Credits Empty - Regular -- Channel 2",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN3",
+	  .ucode  = 0x800,
+	  .udesc  = "iMC RPQ Credits Empty - Regular -- Channel 3",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_sbo0_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_snoops_rsp_after_data[]={
+	{ .uname  = "LOCAL",
+	  .ucode  = 0x100,
+	  .udesc  = "Data beat the Snoop Responses -- Local Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REMOTE",
+	  .ucode  = 0x200,
+	  .udesc  = "Data beat the Snoop Responses -- Remote Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_snoop_cycles_ne[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0x300,
+	  .udesc  = "Cycles with Snoops Outstanding -- All Requests",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "LOCAL",
+	  .ucode = 0x100,
+	  .udesc = "Cycles with Snoops Outstanding -- Local Requests",
+	},
+	{ .uname = "REMOTE",
+	  .ucode = 0x200,
+	  .udesc = "Cycles with Snoops Outstanding -- Remote Requests",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_snoop_occupancy[]={
+	{ .uname  = "LOCAL",
+	  .ucode  = 0x100,
+	  .udesc  = "Tracker Snoops Outstanding Accumulator -- Local Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REMOTE",
+	  .ucode  = 0x200,
+	  .udesc  = "Tracker Snoops Outstanding Accumulator -- Remote Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_snoop_resp[]={
+	{ .uname = "RSPCNFLCT",
+	  .ucode = 0x4000,
+	  .udesc = "Snoop Responses Received -- RSPCNFLCT*",
+	},
+	{ .uname = "RSPI",
+	  .ucode = 0x100,
+	  .udesc = "Snoop Responses Received -- RspI",
+	},
+	{ .uname = "RSPIFWD",
+	  .ucode = 0x400,
+	  .udesc = "Snoop Responses Received -- RspIFwd",
+	},
+	{ .uname = "RSPS",
+	  .ucode = 0x200,
+	  .udesc = "Snoop Responses Received -- RspS",
+	},
+	{ .uname = "RSPSFWD",
+	  .ucode = 0x800,
+	  .udesc = "Snoop Responses Received -- RspSFwd",
+	},
+	{ .uname = "RSP_FWD_WB",
+	  .ucode = 0x2000,
+	  .udesc = "Snoop Responses Received -- Rsp*Fwd*WB",
+	},
+	{ .uname = "RSP_WB",
+	  .ucode = 0x1000,
+	  .udesc = "Snoop Responses Received -- Rsp*WB",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_snp_resp_recv_local[]={
+	{ .uname = "OTHER",
+	  .ucode = 0x8000,
+	  .udesc = "Snoop Responses Received Local -- Other",
+	},
+	{ .uname = "RSPCNFLCT",
+	  .ucode = 0x4000,
+	  .udesc = "Snoop Responses Received Local -- RspCnflct",
+	},
+	{ .uname = "RSPI",
+	  .ucode = 0x100,
+	  .udesc = "Snoop Responses Received Local -- RspI",
+	},
+	{ .uname = "RSPIFWD",
+	  .ucode = 0x400,
+	  .udesc = "Snoop Responses Received Local -- RspIFwd",
+	},
+	{ .uname = "RSPS",
+	  .ucode = 0x200,
+	  .udesc = "Snoop Responses Received Local -- RspS",
+	},
+	{ .uname = "RSPSFWD",
+	  .ucode = 0x800,
+	  .udesc = "Snoop Responses Received Local -- RspSFwd",
+	},
+	{ .uname = "RSPxFWDxWB",
+	  .ucode = 0x2000,
+	  .udesc = "Snoop Responses Received Local -- Rsp*FWD*WB",
+	},
+	{ .uname = "RSPxWB",
+	  .ucode = 0x1000,
+	  .udesc = "Snoop Responses Received Local -- Rsp*WB",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_stall_no_sbo_credit[]={
+	{ .uname = "SBO0_AD",
+	  .ucode = 0x100,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, AD Ring",
+	},
+	{ .uname = "SBO0_BL",
+	  .ucode = 0x400,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, BL Ring",
+	},
+	{ .uname = "SBO1_AD",
+	  .ucode = 0x200,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, AD Ring",
+	},
+	{ .uname = "SBO1_BL",
+	  .ucode = 0x800,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tad_requests_g0[]={
+	{ .uname  = "REGION0",
+	  .ucode  = 0x100,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 0",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION1",
+	  .ucode  = 0x200,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 1",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION2",
+	  .ucode  = 0x400,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 2",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION3",
+	  .ucode  = 0x800,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 3",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION4",
+	  .ucode  = 0x1000,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 4",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION5",
+	  .ucode  = 0x2000,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 5",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION6",
+	  .ucode  = 0x4000,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 6",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION7",
+	  .ucode  = 0x8000,
+	  .udesc  = "HA Requests to a TAD Region - Group 0 -- TAD Region 7",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tad_requests_g1[]={
+	{ .uname  = "REGION10",
+	  .ucode  = 0x400,
+	  .udesc  = "HA Requests to a TAD Region - Group 1 -- TAD Region 10",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION11",
+	  .ucode  = 0x800,
+	  .udesc  = "HA Requests to a TAD Region - Group 1 -- TAD Region 11",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION8",
+	  .ucode  = 0x100,
+	  .udesc  = "HA Requests to a TAD Region - Group 1 -- TAD Region 8",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REGION9",
+	  .ucode  = 0x200,
+	  .udesc  = "HA Requests to a TAD Region - Group 1 -- TAD Region 9",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tracker_cycles_full[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0x200,
+	  .udesc  = "Tracker Cycles Full -- Cycles Completely Used",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname = "GP",
+	  .ucode = 0x100,
+	  .udesc = "Tracker Cycles Full -- Cycles GP Completely Used",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tracker_cycles_ne[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0x300,
+	  .udesc  = "Tracker Cycles Not Empty -- All Requests",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "LOCAL",
+	  .ucode = 0x100,
+	  .udesc = "Tracker Cycles Not Empty -- Local Requests",
+	},
+	{ .uname = "REMOTE",
+	  .ucode = 0x200,
+	  .udesc = "Tracker Cycles Not Empty -- Remote Requests",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tracker_occupancy[]={
+	{ .uname = "INVITOE_LOCAL",
+	  .ucode = 0x4000,
+	  .udesc = "Tracker Occupancy Accumultor -- Local InvItoE Requests",
+	},
+	{ .uname = "INVITOE_REMOTE",
+	  .ucode = 0x8000,
+	  .udesc = "Tracker Occupancy Accumultor -- Remote InvItoE Requests",
+	},
+	{ .uname = "READS_LOCAL",
+	  .ucode = 0x400,
+	  .udesc = "Tracker Occupancy Accumultor -- Local Read Requests",
+	},
+	{ .uname = "READS_REMOTE",
+	  .ucode = 0x800,
+	  .udesc = "Tracker Occupancy Accumultor -- Remote Read Requests",
+	},
+	{ .uname = "WRITES_LOCAL",
+	  .ucode = 0x1000,
+	  .udesc = "Tracker Occupancy Accumultor -- Local Write Requests",
+	},
+	{ .uname = "WRITES_REMOTE",
+	  .ucode = 0x2000,
+	  .udesc = "Tracker Occupancy Accumultor -- Remote Write Requests",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_tracker_pending_occupancy[]={
+	{ .uname  = "LOCAL",
+	  .ucode  = 0x100,
+	  .udesc  = "Data Pending Occupancy Accumultor -- Local Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "REMOTE",
+	  .ucode  = 0x200,
+	  .udesc  = "Data Pending Occupancy Accumultor -- Remote Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_txr_ad_cycles_full[]={
+	{ .uname = "ALL",
+	  .ucode = 0x300,
+	  .udesc = "All",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname = "SCHED0",
+	  .ucode = 0x100,
+	  .udesc = "Scheduler 0",
+	},
+	{ .uname = "SCHED1",
+	  .ucode = 0x200,
+	  .udesc = "Scheduler 1",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_txr_bl[]={
+	{ .uname = "DRS_CACHE",
+	  .ucode = 0x100,
+	  .udesc = "Outbound DRS Ring Transactions to Cache -- Data to Cache",
+	},
+	{ .uname = "DRS_CORE",
+	  .ucode = 0x200,
+	  .udesc = "Outbound DRS Ring Transactions to Cache -- Data to Core",
+	},
+	{ .uname = "DRS_QPI",
+	  .ucode = 0x400,
+	  .udesc = "Outbound DRS Ring Transactions to Cache -- Data to QPI",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_txr_starved[]={
+	{ .uname = "AK",
+	  .ucode = 0x100,
+	  .udesc = "Injection Starvation -- For AK Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "Injection Starvation -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_h_wpq_cycles_no_reg_credits[]={
+	{ .uname  = "CHN0",
+	  .ucode  = 0x100,
+	  .udesc  = "HA iMC CHN0 WPQ Credits Empty - Regular -- Channel 0",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN1",
+	  .ucode  = 0x200,
+	  .udesc  = "HA iMC CHN0 WPQ Credits Empty - Regular -- Channel 1",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN2",
+	  .ucode  = 0x400,
+	  .udesc  = "HA iMC CHN0 WPQ Credits Empty - Regular -- Channel 2",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CHN3",
+	  .ucode  = 0x800,
+	  .udesc  = "HA iMC CHN0 WPQ Credits Empty - Regular -- Channel 3",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_h_pe[]={
+  /* ADDR_OPC_MATCH not supported (linux kernel has no support for HA OPC yet*/
+  { .name   = "UNC_H_BT_CYCLES_NE",
+    .code   = 0x42,
+    .desc   = "Cycles the Backup Tracker (BT) is not empty. The BT is the actual HOM tracker in IVT.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_BT_OCCUPANCY",
+    .code   = 0x43,
+    .desc   = "Accumulates the occupancy of te HA BT pool in every cycle. This can be used with the 'not empty' stat to calculate the average queue occupancy or the 'allocations' stat to calculate average queue latency. HA BTs are allocated as son as a request enters the HA and are released after the snoop response and data return and the response is returned to the ring",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_BYPASS_IMC",
+    .code   = 0x14,
+    .desc   = "Counts the number of times when the HA was able to bypass was attempted.  This is a latency optimization for situations when there is light loadings on the memory subsystem.  This can be filted by when the bypass was taken and when it was not.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_bypass_imc,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_bypass_imc),
+  },
+  { .name   = "UNC_H_CONFLICT_CYCLES",
+    .code   = 0xb,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+
+  { .name   = "UNC_H_CLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "Counts the number of uclks in the HA.  This will be slightly different than the count in the Ubox because of enable/freeze delays.  The HA is on the other side of the die from the fixed Ubox uclk counter, so the drift could be somewhat larger than in units that are closer like the QPI Agent.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_DIRECT2CORE_COUNT",
+    .code   = 0x11,
+    .desc   = "Number of Direct2Core messages sent",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_DIRECT2CORE_CYCLES_DISABLED",
+    .code   = 0x12,
+    .desc   = "Number of cycles in which Direct2Core was disabled",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_DIRECT2CORE_TXN_OVERRIDE",
+    .code   = 0x13,
+    .desc   = "Number of Reads where Direct2Core overridden",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_DIRECTORY_LAT_OPT",
+    .code   = 0x41,
+    .desc   = "Directory Latency Optimization Data Return Path Taken. When directory mode is enabled and the directory retuned for a read is Dir=I, then data can be returned using a faster path if certain conditions are met (credits, free pipeline, etc).",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_DIRECTORY_LOOKUP",
+    .code   = 0xc,
+    .desc   = "Counts the number of transactions that looked up the directory.  Can be filtered by requests that had to snoop and those that did not have to.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_directory_lookup,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_directory_lookup),
+  },
+  { .name   = "UNC_H_DIRECTORY_UPDATE",
+    .code   = 0xd,
+    .desc   = "Counts the number of directory updates that were required.  These result in writes to the memory controller.  This can be filtered by directory sets and directory clears.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_directory_update,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_directory_update),
+  },
+  { .name   = "UNC_H_HITME_HIT",
+    .code   = 0x71,
+    .desc   = "",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_hitme_hit,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_hitme_hit),
+  },
+  { .name   = "UNC_H_HITME_HIT_PV_BITS_SET",
+    .code   = 0x72,
+    .desc   = "",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_hitme_hit_pv_bits_set,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_hitme_hit_pv_bits_set),
+  },
+  { .name   = "UNC_H_HITME_LOOKUP",
+    .code   = 0x70,
+    .desc   = "",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_hitme_lookup,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_hitme_lookup),
+  },
+  { .name   = "UNC_H_IGR_NO_CREDIT_CYCLES",
+    .code   = 0x22,
+    .desc   = "Counts the number of cycles when the HA does not have credits to send messages to the QPI Agent.  This can be filtered by the different credit pools and the different links.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_igr_no_credit_cycles,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_igr_no_credit_cycles),
+  },
+  { .name   = "UNC_H_IMC_READS",
+    .code   = 0x17,
+    .desc   = "Count of the number of reads issued to any of the memory controller channels.  This can be filtered by the priority of the reads.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_imc_reads,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_imc_reads),
+  },
+  { .name   = "UNC_H_IMC_RETRY",
+    .code   = 0x1e,
+    .desc   = "",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_H_IMC_WRITES",
+    .code   = 0x1a,
+    .desc   = "Counts the total number of full line writes issued from the HA into the memory controller.  This counts for all four channels.  It can be filtered by full/partial and ISOCH/non-ISOCH.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_imc_writes,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_imc_writes),
+  },
+  { .name   = "UNC_H_OSB",
+    .code   = 0x53,
+    .desc   = "Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_osb,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_osb),
+  },
+  { .name   = "UNC_H_OSB_EDR",
+    .code   = 0x54,
+    .desc   = "Counts the number of transactions that broadcast snoop due to OSB, but found clean data in memory and was able to do early data return",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_osb_edr,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_osb_edr),
+  },
+  { .name   = "UNC_H_REQUESTS",
+    .code   = 0x1,
+    .desc   = "Counts the total number of read requests made into the Home Agent. Reads include all read opcodes (including RFO).  Writes include all writes (streaming, evictions, HitM, etc).",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_requests,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_requests),
+  },
+  { .name   = "UNC_H_RING_AD_USED",
+    .code   = 0x3e,
+    .desc   = "Counts the number of cycles that the AD ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_ring_ad_used),
+  },
+  { .name   = "UNC_H_RING_AK_USED",
+    .code   = 0x3f,
+    .desc   = "Counts the number of cycles that the AK ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_ring_ad_used),
+  },
+  { .name   = "UNC_H_RING_BL_USED",
+    .code   = 0x40,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_ring_ad_used),
+  },
+  { .name   = "UNC_H_RPQ_CYCLES_NO_REG_CREDITS",
+    .code   = 0x15,
+    .desc   = "Counts the number of cycles when there are no regular credits available for posting reads from the HA into the iMC.  In order to send reads into the memory controller, the HA must first acquire a credit for the iMCs RPQ (read pending queue).  This queue is broken into regular credits/buffers that are used by general reads, and special requests such as ISOCH reads.  This count only tracks the regular credits  Common high banwidth workloads should be able to make use of all of the regular buffers, but it will be difficult (and uncommon) to make use of both the regular and special buffers at the same time.  One can filter based on the memory controller channel.  One or more channels can be tracked at a given iven time.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_rpq_cycles_no_reg_credits,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_rpq_cycles_no_reg_credits),
+  },
+  { .name   = "UNC_H_SBO0_CREDITS_ACQUIRED",
+    .code   = 0x68,
+    .desc   = "Number of Sbo 0 credits acquired in a given cycle, per ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_H_SBO0_CREDIT_OCCUPANCY",
+    .code   = 0x6a,
+    .desc   = "Number of Sbo 0 credits in use in a given cycle, per ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_H_SBO1_CREDITS_ACQUIRED",
+    .code   = 0x69,
+    .desc   = "Number of Sbo 1 credits acquired in a given cycle, per ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_H_SBO1_CREDIT_OCCUPANCY",
+    .code   = 0x6b,
+    .desc   = "Number of Sbo 1 credits in use in a given cycle, per ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_H_SNOOPS_RSP_AFTER_DATA",
+    .code   = 0xa,
+    .desc   = "Counts the number of reads when the snoop was on the critical path to the data return.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_snoops_rsp_after_data,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_snoops_rsp_after_data),
+  },
+  { .name   = "UNC_H_SNOOP_CYCLES_NE",
+    .code   = 0x8,
+    .desc   = "Counts cycles when one or more snoops are outstanding.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_snoop_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_snoop_cycles_ne),
+  },
+  { .name   = "UNC_H_SNOOP_OCCUPANCY",
+    .code   = 0x9,
+    .desc   = "Accumulates the occupancy of either the local HA tracker pool that have snoops pending in every cycle.    This can be used in conjection with the not empty stat to calculate average queue occupancy or the allocations stat in order to calculate average queue latency.  HA trackers are allocated as soon as a request enters the HA if an HT (HomeTracker) entry is available and this occupancy is decremented when all the snoop responses have retureturned.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_snoop_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_snoop_occupancy),
+  },
+  { .name   = "UNC_H_SNOOP_RESP",
+    .code   = 0x21,
+    .desc   = "Counts the total number of RspI snoop responses received.  Whenever a snoops are issued, one or more snoop responses will be returned depending on the topology of the system.   In systems larger than 2s, when multiple snoops are returned this will count all the snoops that are received.  For example, if 3 snoops were issued and returned RspI, RspS, and RspSFwd; then each of these sub-events would increment by 1.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_snoop_resp,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_snoop_resp),
+  },
+  { .name   = "UNC_H_SNP_RESP_RECV_LOCAL",
+    .code   = 0x60,
+    .desc   = "Number of snoop responses received for a Local  request",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_snp_resp_recv_local,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_snp_resp_recv_local),
+  },
+  { .name   = "UNC_H_STALL_NO_SBO_CREDIT",
+    .code   = 0x6c,
+    .desc   = "Number of cycles Egress is stalled waiting for an Sbo credit to become available.  Per Sbo, per Ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_stall_no_sbo_credit,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_stall_no_sbo_credit),
+  },
+  { .name   = "UNC_H_TAD_REQUESTS_G0",
+    .code   = 0x1b,
+    .desc   = "Counts the number of HA requests to a given TAD region.  There are up to 11 TAD (target address decode) regions in each home agent.  All requests destined for the memory controller must first be decoded to determine which TAD region they are in.  This event is filtered based on the TAD region ID, and covers regions 0 to 7.  This event is useful for understanding how applications are using the memory that is spread across the different memory regions.  It is particularly useful for Monroe systems that use the TAD to enable individual channels to enter self-refresh to save powewer.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tad_requests_g0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tad_requests_g0),
+  },
+  { .name   = "UNC_H_TAD_REQUESTS_G1",
+    .code   = 0x1c,
+    .desc   = "Counts the number of HA requests to a given TAD region.  There are up to 11 TAD (target address decode) regions in each home agent.  All requests destined for the memory controller must first be decoded to determine which TAD region they are in.  This event is filtered based on the TAD region ID, and covers regions 8 to 10.  This event is useful for understanding how applications are using the memory that is spread across the different memory regions.  It is particularly useful for Monroe systems that use the TAD to enable individual channels to enter self-refresh to save powewer.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tad_requests_g1,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tad_requests_g1),
+  },
+  { .name   = "UNC_H_TRACKER_CYCLES_FULL",
+    .code   = 0x2,
+    .desc   = "Counts the number of cycles when the local HA tracker pool is completely used.  This can be used with edge detect to identify the number of situations when the pool became fully utilized.  This should not be confused with RTID credit usage -- which must be tracked inside each cbo individually -- but represents the actual tracker buffer structure.  In other words, the system could be starved for RTIDs but not fill up the HA trackers.  HA trackers are allocated as soon as a request enters the HA and is released after the snoop response and data return (or post in the case of a write) and the response is returned on the ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tracker_cycles_full,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tracker_cycles_full),
+  },
+  { .name   = "UNC_H_TRACKER_CYCLES_NE",
+    .code   = 0x3,
+    .desc   = "Counts the number of cycles when the local HA tracker pool is not empty.  This can be used with edge detect to identify the number of situations when the pool became empty.  This should not be confused with RTID credit usage -- which must be tracked inside each cbo individually -- but represents the actual tracker buffer structure.  In other words, this buffer could be completely empty, but there may still be credits in use by the CBos.  This stat can be used in conjunction with the occupancy accumulation stat in order to calculate average queue occpancy.  HA trackers are allocated as soon as a request enters the HA if an HT (Home Tracker) entry is available and is released after the snoop response and data return (or post in the case of a write) and the response is returned on the ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tracker_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tracker_cycles_ne),
+  },
+  { .name   = "UNC_H_TRACKER_OCCUPANCY",
+    .code   = 0x4,
+    .desc   = "Accumulates the occupancy of the local HA tracker pool in every cycle.  This can be used in conjection with the not empty stat to calculate average queue occupancy or the allocations stat in order to calculate average queue latency.  HA trackers are allocated as soon as a request enters the HA if a HT (Home Tracker) entry is available and is released after the snoop response and data return (or post in the case of a write) and the response is returned on the rhe ring.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tracker_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tracker_occupancy),
+  },
+  { .name   = "UNC_H_TRACKER_PENDING_OCCUPANCY",
+    .code   = 0x5,
+    .desc   = "Accumulates the number of transactions that have data from the memory controller until they get scheduled to the Egress.  This can be used to calculate the queuing latency for two things.  (1) If the system is waiting for snoops, this will increase.  (2) If the system cant schedule to the Egress because of either (a) Egress Credits or (b) QPI BL IGR credits for remote requestss.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_tracker_pending_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_tracker_pending_occupancy),
+  },
+  { .name   = "UNC_H_TXR_AD_CYCLES_FULL",
+    .code   = 0x2a,
+    .desc   = "AD Egress Full",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_txr_ad_cycles_full,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_txr_ad_cycles_full),
+  },
+  { .name   = "UNC_H_TXR_AK_CYCLES_FULL",
+    .code   = 0x32,
+    .desc   = "AK Egress Full",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_txr_ad_cycles_full,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_txr_ad_cycles_full), /* shared */
+  },
+  { .name   = "UNC_H_TXR_BL",
+    .code   = 0x10,
+    .desc   = "Counts the number of DRS messages sent out on the BL ring.   This can be filtered by the destination.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_txr_bl,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_txr_bl),
+  },
+  { .name   = "UNC_H_TXR_BL_CYCLES_FULL",
+    .code   = 0x36,
+    .desc   = "BL Egress Full",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_txr_ad_cycles_full,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_txr_ad_cycles_full), /* shared */
+  },
+  { .name   = "UNC_H_TXR_STARVED",
+    .code   = 0x6d,
+    .desc   = "Counts injection starvation.  This starvation is triggered when the Egress cannot send a transaction onto the ring for a long period of time.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_txr_starved,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_txr_starved),
+  },
+  { .name   = "UNC_H_WPQ_CYCLES_NO_REG_CREDITS",
+    .code   = 0x18,
+    .desc   = "Counts the number of cycles when there are no regular credits available for posting writes from the HA into the iMC.  In order to send writes into the memory controller, the HA must first acquire a credit for the iMCs WPQ (write pending queue).  This queue is broken into regular credits/buffers that are used by general writes, and special requests such as ISOCH writes.  This count only tracks the regular credits  Common high banwidth workloads should be able to make use of all of the regular buffers, but it will be difficult (and uncommon) to make use of both the regular and special buffers at the same time.  One can filter based on the memory controller channel.  One or more channels can be tracked at a given iven time.",
+    .modmsk = BDX_UNC_HA_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_h_wpq_cycles_no_reg_credits,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_h_wpq_cycles_no_reg_credits),
+  },
+};
diff --git a/lib/events/intel_bdx_unc_imc_events.h b/lib/events/intel_bdx_unc_imc_events.h
new file mode 100644
index 0000000..1a2292e
--- /dev/null
+++ b/lib/events/intel_bdx_unc_imc_events.h
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_imc
+ */
+
+static intel_x86_umask_t bdx_unc_m_act_count[]={
+	{ .uname = "BYP",
+	  .ucode = 0x800,
+	  .udesc = "DRAM Activate Count -- Activate due to Write",
+	},
+	{ .uname = "RD",
+	  .ucode = 0x100,
+	  .udesc = "DRAM Activate Count -- Activate due to Read",
+	},
+	{ .uname = "WR",
+	  .ucode = 0x200,
+	  .udesc = "DRAM Activate Count -- Activate due to Write",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_byp_cmds[]={
+	{ .uname = "ACT",
+	  .ucode = 0x100,
+	  .udesc = "ACT command issued by 2 cycle bypass",
+	},
+	{ .uname = "CAS",
+	  .ucode = 0x200,
+	  .udesc = "CAS command issued by 2 cycle bypass",
+	},
+	{ .uname = "PRE",
+	  .ucode = 0x400,
+	  .udesc = "PRE command issued by 2 cycle bypass",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_cas_count[]={
+	{ .uname  = "ALL",
+	  .ucode  = 0xf00,
+	  .udesc  = "DRAM RD_CAS and WR_CAS Commands. All DRAM WR_CAS (w/ and w/out auto-pre)",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname = "RD",
+	  .ucode = 0x300,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. All DRAM Reads (RD_CAS + Underfills)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "RD_REG",
+	  .ucode = 0x100,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. All DRAM RD_CAS (w/ and w/out auto-pre)",
+	},
+	{ .uname = "RD_RMM",
+	  .ucode = 0x2000,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. Read CAS issued in RMM",
+	},
+	{ .uname = "RD_UNDERFILL",
+	  .ucode = 0x200,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. Underfill Read Issued",
+	},
+	{ .uname = "RD_WMM",
+	  .ucode = 0x1000,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. Read CAS issued in WMM",
+	},
+	{ .uname  = "WR",
+	  .ucode  = 0xc00,
+	  .udesc  = "DRAM RD_CAS and WR_CAS Commands. All DRAM WR_CAS (both Modes)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "WR_RMM",
+	  .ucode = 0x800,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. DRAM WR_CAS (w/ and w/out auto-pre) in Read Major Mode",
+	},
+	{ .uname = "WR_WMM",
+	  .ucode = 0x400,
+	  .udesc = "DRAM RD_CAS and WR_CAS Commands. DRAM WR_CAS (w/ and w/out auto-pre) in Write Major Mode",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_dram_refresh[]={
+	{ .uname = "HIGH",
+	  .ucode = 0x400,
+	  .udesc = "Number of DRAM Refreshes Issued",
+	},
+	{ .uname = "PANIC",
+	  .ucode = 0x200,
+	  .udesc = "Number of DRAM Refreshes Issued",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_major_modes[]={
+	{ .uname = "ISOCH",
+	  .ucode = 0x800,
+	  .udesc = "Cycles in a Major Mode -- Isoch Major Mode",
+	},
+	{ .uname = "PARTIAL",
+	  .ucode = 0x400,
+	  .udesc = "Cycles in a Major Mode -- Partial Major Mode",
+	},
+	{ .uname = "READ",
+	  .ucode = 0x100,
+	  .udesc = "Cycles in a Major Mode -- Read Major Mode",
+	},
+	{ .uname = "WRITE",
+	  .ucode = 0x200,
+	  .udesc = "Cycles in a Major Mode -- Write Major Mode",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_power_cke_cycles[]={
+	{ .uname  = "RANK0",
+	  .ucode  = 0x100,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK1",
+	  .ucode  = 0x200,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK2",
+	  .ucode  = 0x400,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK3",
+	  .ucode  = 0x800,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK4",
+	  .ucode  = 0x1000,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK5",
+	  .ucode  = 0x2000,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK6",
+	  .ucode  = 0x4000,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RANK7",
+	  .ucode  = 0x8000,
+	  .udesc  = "CKE_ON_CYCLES by Rank -- DIMM ID",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_power_throttle_cycles[]={
+	{ .uname = "RANK0",
+	  .ucode = 0x100,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK1",
+	  .ucode = 0x200,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK2",
+	  .ucode = 0x400,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK3",
+	  .ucode = 0x800,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK4",
+	  .ucode = 0x1000,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK5",
+	  .ucode = 0x2000,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK6",
+	  .ucode = 0x4000,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+	{ .uname = "RANK7",
+	  .ucode = 0x8000,
+	  .udesc = "Throttle Cycles for Rank 0 -- DIMM ID",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_preemption[]={
+	{ .uname = "RD_PREEMPT_RD",
+	  .ucode = 0x100,
+	  .udesc = "Read Preemption Count -- Read over Read Preemption",
+	},
+	{ .uname = "RD_PREEMPT_WR",
+	  .ucode = 0x200,
+	  .udesc = "Read Preemption Count -- Read over Write Preemption",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_pre_count[]={
+	{ .uname = "BYP",
+	  .ucode = 0x1000,
+	  .udesc = "DRAM Precharge commands. -- Precharge due to bypass",
+	},
+	{ .uname = "PAGE_CLOSE",
+	  .ucode = 0x200,
+	  .udesc = "DRAM Precharge commands. -- Precharge due to timer expiration",
+	},
+	{ .uname = "PAGE_MISS",
+	  .ucode = 0x100,
+	  .udesc = "DRAM Precharge commands. -- Precharges due to page miss",
+	},
+	{ .uname = "RD",
+	  .ucode = 0x400,
+	  .udesc = "DRAM Precharge commands. -- Precharge due to read",
+	},
+	{ .uname = "WR",
+	  .ucode = 0x800,
+	  .udesc = "DRAM Precharge commands. -- Precharge due to write",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_rd_cas_prio[]={
+	{ .uname = "HIGH",
+	  .ucode = 0x400,
+	  .udesc = "Read CAS issued with HIGH priority",
+	},
+	{ .uname = "LOW",
+	  .ucode = 0x100,
+	  .udesc = "Read CAS issued with LOW priority",
+	},
+	{ .uname = "MED",
+	  .ucode = 0x200,
+	  .udesc = "Read CAS issued with MEDIUM priority",
+	},
+	{ .uname = "PANIC",
+	  .ucode = 0x800,
+	  .udesc = "Read CAS issued with PANIC NON ISOCH priority (starved)",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_rd_cas_rank0[]={
+	{ .uname  = "ALLBANKS",
+	  .ucode  = 0x1000,
+	  .udesc  = "Access to Rank 0 -- All Banks",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK0",
+	  .ucode  = 0x0,
+	  .udesc  = "Access to Rank 0 -- Bank 0",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK1",
+	  .ucode  = 0x100,
+	  .udesc  = "Access to Rank 0 -- Bank 1",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK10",
+	  .ucode  = 0xa00,
+	  .udesc  = "Access to Rank 0 -- Bank 10",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK11",
+	  .ucode  = 0xb00,
+	  .udesc  = "Access to Rank 0 -- Bank 11",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK12",
+	  .ucode  = 0xc00,
+	  .udesc  = "Access to Rank 0 -- Bank 12",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK13",
+	  .ucode  = 0xd00,
+	  .udesc  = "Access to Rank 0 -- Bank 13",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK14",
+	  .ucode  = 0xe00,
+	  .udesc  = "Access to Rank 0 -- Bank 14",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK15",
+	  .ucode  = 0xf00,
+	  .udesc  = "Access to Rank 0 -- Bank 15",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK2",
+	  .ucode  = 0x200,
+	  .udesc  = "Access to Rank 0 -- Bank 2",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK3",
+	  .ucode  = 0x300,
+	  .udesc  = "Access to Rank 0 -- Bank 3",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK4",
+	  .ucode  = 0x400,
+	  .udesc  = "Access to Rank 0 -- Bank 4",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK5",
+	  .ucode  = 0x500,
+	  .udesc  = "Access to Rank 0 -- Bank 5",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK6",
+	  .ucode  = 0x600,
+	  .udesc  = "Access to Rank 0 -- Bank 6",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK7",
+	  .ucode  = 0x700,
+	  .udesc  = "Access to Rank 0 -- Bank 7",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK8",
+	  .ucode  = 0x800,
+	  .udesc  = "Access to Rank 0 -- Bank 8",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANK9",
+	  .ucode  = 0x900,
+	  .udesc  = "Access to Rank 0 -- Bank 9",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANKG0",
+	  .ucode  = 0x1100,
+	  .udesc  = "Access to Rank 0 -- Bank Group 0 (Banks 0-3)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANKG1",
+	  .ucode  = 0x1200,
+	  .udesc  = "Access to Rank 0 -- Bank Group 1 (Banks 4-7)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANKG2",
+	  .ucode  = 0x1300,
+	  .udesc  = "Access to Rank 0 -- Bank Group 2 (Banks 8-11)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "BANKG3",
+	  .ucode  = 0x1400,
+	  .udesc  = "Access to Rank 0 -- Bank Group 3 (Banks 12-15)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_rd_cas_rank2[]={
+	{ .uname  = "BANK0",
+	  .ucode  = 0x0,
+	  .udesc  = "RD_CAS Access to Rank 2 -- Bank 0",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_vmse_wr_push[]={
+	{ .uname = "RMM",
+	  .ucode = 0x200,
+	  .udesc = "VMSE WR PUSH issued -- VMSE write PUSH issued in RMM",
+	},
+	{ .uname = "WMM",
+	  .ucode = 0x100,
+	  .udesc = "VMSE WR PUSH issued -- VMSE write PUSH issued in WMM",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_m_wmm_to_rmm[]={
+	{ .uname = "LOW_THRESH",
+	  .ucode = 0x100,
+	  .udesc = "Transition from WMM to RMM because of low threshold -- Transition from WMM to RMM because of starve counter",
+	},
+	{ .uname = "STARVE",
+	  .ucode = 0x200,
+	  .udesc = "Transition from WMM to RMM because of low threshold -- ",
+	},
+	{ .uname = "VMSE_RETRY",
+	  .ucode = 0x400,
+	  .udesc = "Transition from WMM to RMM because of low threshold -- ",
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_m_pe[]={
+  { .name   = "UNC_M_CLOCKTICKS",
+    .desc   = "IMC Uncore clockticks (fixed counter)",
+    .modmsk = 0x0,
+    .cntmsk = 0x100000000ull,
+    .code   = 0xff, /* perf pseudo encoding for fixed counter */
+    .flags  = INTEL_X86_FIXED,
+  },
+  { .name   = "UNC_M_ACT_COUNT",
+    .code   = 0x1,
+    .desc   = "Counts the number of DRAM Activate commands sent on this channel.  Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS.  One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_act_count,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_act_count),
+  },
+  { .name   = "UNC_M_BYP_CMDS",
+    .code   = 0xa1,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_byp_cmds,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_byp_cmds),
+  },
+  { .name   = "UNC_M_CAS_COUNT",
+    .code   = 0x4,
+    .desc   = "DRAM RD_CAS and WR_CAS Commands",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_cas_count,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_cas_count),
+  },
+  { .name   = "UNC_M_DCLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_DRAM_PRE_ALL",
+    .code   = 0x6,
+    .desc   = "Counts the number of times that the precharge all command was sent.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_DRAM_REFRESH",
+    .code   = 0x5,
+    .desc   = "Counts the number of refreshes issued.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_dram_refresh,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_dram_refresh),
+  },
+  { .name   = "UNC_M_ECC_CORRECTABLE_ERRORS",
+    .code   = 0x9,
+    .desc   = "Counts the number of ECC errors detected and corrected by the iMC on this channel.  This counter is only useful with ECC DRAM devices.  This count will increment one time for each correction regardless of the number of bits corrected.  The iMC can correct up to 4 bit errors in independent channel mode and 8 bit erros in lockstep mode.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_MAJOR_MODES",
+    .code   = 0x7,
+    .desc   = "Counts the total number of cycles spent in a major mode (selected by a filter) on the given channel.   Major modea are channel-wide, and not a per-rank (or dimm or bank) mode.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_major_modes,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_major_modes),
+  },
+  { .name   = "UNC_M_POWER_CHANNEL_DLLOFF",
+    .code   = 0x84,
+    .desc   = "Number of cycles when all the ranks in the channel are in CKE Slow (DLLOFF) mode.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_POWER_CHANNEL_PPD",
+    .code   = 0x85,
+    .desc   = "Number of cycles when all the ranks in the channel are in PPD mode.  If IBT=off is enabled, then this can be used to count those cycles.  If it is not enabled, then this can count the number of cycles when that could have been taken advantage of.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_POWER_CKE_CYCLES",
+    .code   = 0x83,
+    .desc   = "Number of cycles spent in CKE ON mode.  The filter allows you to select a rank to monitor.  If multiple ranks are in CKE ON mode at one time, the counter will ONLY increment by one rather than doing accumulation.  Multiple counters will need to be used to track multiple ranks simultaneously.  There is no distinction between the different CKE modes (APD, PPDS, PPDF).  This can be determined based on the system programming.  These events should commonly be used with Invert to get the number of cycles in power saving mode.  Edge Detect is also useful here.  Make sure that you do NOT use Invert with Edge Detect (this just confuses the system and is not necessary).",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_power_cke_cycles,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_power_cke_cycles),
+  },
+  { .name   = "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
+    .code   = 0x86,
+    .desc   = "Counts the number of cycles when the iMC is in critical thermal throttling.  When this happens, all traffic is blocked.  This should be rare unless something bad is going on in the platform.  There is no filtering by rank for this event.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_POWER_PCU_THROTTLING",
+    .code   = 0x42,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_POWER_SELF_REFRESH",
+    .code   = 0x43,
+    .desc   = "Counts the number of cycles when the iMC is in self-refresh and the iMC still has a clock.  This happens in some package C-states.  For example, the PCU may ask the iMC to enter self-refresh even though some of the cores are still processing.  One use of this is for Monroe technology.  Self-refresh is required during package C3 and C6, but there is no clock in the iMC at this time, so it is not possible to count these cases.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_POWER_THROTTLE_CYCLES",
+    .code   = 0x41,
+    .desc   = "Counts the number of cycles while the iMC is being throttled by either thermal constraints or by the PCU throttling.  It is not possible to distinguish between the two.  This can be filtered by rank.  If multiple ranks are selected and are being throttled at the same time, the counter will only increment by 1.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_power_throttle_cycles,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_power_throttle_cycles),
+  },
+  { .name   = "UNC_M_PREEMPTION",
+    .code   = 0x8,
+    .desc   = "Counts the number of times a read in the iMC preempts another read or write.  Generally reads to an open page are issued ahead of requests to closed pages.  This improves the page hit rate of the system.  However, high priority requests can cause pages of active requests to be closed in order to get them out.  This will reduce the latency of the high-priority request at the expense of lower bandwidth and increased overall average latency.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_preemption,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_preemption),
+  },
+  { .name   = "UNC_M_PRE_COUNT",
+    .code   = 0x2,
+    .desc   = "Counts the number of DRAM Precharge commands sent on this channel.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_pre_count,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_pre_count),
+  },
+  { .name   = "UNC_M_RD_CAS_PRIO",
+    .code   = 0xa0,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_prio,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_prio),
+  },
+  { .name   = "UNC_M_RD_CAS_RANK0",
+    .code   = 0xb0,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0),
+  },
+  { .name   = "UNC_M_RD_CAS_RANK1",
+    .code   = 0xb1,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_RD_CAS_RANK2",
+    .code   = 0xb2,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank2),
+  },
+  { .name   = "UNC_M_RD_CAS_RANK4",
+    .code   = 0xb4,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_RD_CAS_RANK5",
+    .code   = 0xb5,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_RD_CAS_RANK6",
+    .code   = 0xb6,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_RD_CAS_RANK7",
+    .code   = 0xb7,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_RPQ_CYCLES_NE",
+    .code   = 0x11,
+    .desc   = "Counts the number of cycles that the Read Pending Queue is not empty.  This can then be used to calculate the average occupancy (in conjunction with the Read Pending Queue Occupancy count).  The RPQ is used to schedule reads out to the memory controller and to track the requests.  Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC.  They deallocate after the CAS command has been issued to memory.  This filter is to be used in conjunction with the occupancy filter so that one can correctly track the average occupancies for schedulable entries and scheduled requests.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_RPQ_INSERTS",
+    .code   = 0x10,
+    .desc   = "Counts the number of allocations into the Read Pending Queue.  This queue is used to schedule reads out to the memory controller and to track the requests.  Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC.  They deallocate after the CAS command has been issued to memory.  This includes both ISOCH and non-ISOCH requests.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_VMSE_MXB_WR_OCCUPANCY",
+    .code   = 0x91,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_VMSE_WR_PUSH",
+    .code   = 0x90,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_vmse_wr_push,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_vmse_wr_push),
+  },
+  { .name   = "UNC_M_WMM_TO_RMM",
+    .code   = 0xc0,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_wmm_to_rmm,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_wmm_to_rmm),
+  },
+  { .name   = "UNC_M_WPQ_CYCLES_FULL",
+    .code   = 0x22,
+    .desc   = "Counts the number of cycles when the Write Pending Queue is full.  When the WPQ is full, the HA will not be able to issue any additional read requests into the iMC.  This count should be similar count in the HA which tracks the number of cycles that the HA has no WPQ credits, just somewhat smaller to account for the credit return overhead.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_WPQ_CYCLES_NE",
+    .code   = 0x21,
+    .desc   = "Counts the number of cycles that the Write Pending Queue is not empty.  This can then be used to calculate the average queue occupancy (in conjunction with the WPQ Occupancy Accumulation count).  The WPQ is used to schedule write out to the memory controller and to track the writes.  Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC.  They deallocate after being issued to DRAM.  Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC.  This is not to be confused with actually performing the write to DRAM.  Therefore, the average latency for this queue is actually not useful for deconstruction intermediate write latencieies.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_WPQ_READ_HIT",
+    .code   = 0x23,
+    .desc   = "Counts the number of times a request hits in the WPQ (write-pending queue).  The iMC allows writes and reads to pass up other writes to different addresses.  Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address.  When reads hit, they are able to directly pull their data from the WPQ instead of going to memory.  Writes that hit will overwrite the existing data.  Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_WPQ_WRITE_HIT",
+    .code   = 0x24,
+    .desc   = "Counts the number of times a request hits in the WPQ (write-pending queue).  The iMC allows writes and reads to pass up other writes to different addresses.  Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address.  When reads hit, they are able to directly pull their data from the WPQ instead of going to memory.  Writes that hit will overwrite the existing data.  Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_WRONG_MM",
+    .code   = 0xc1,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_M_WR_CAS_RANK0",
+    .code   = 0xb8,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0),
+  },
+  { .name   = "UNC_M_WR_CAS_RANK1",
+    .code   = 0xb9,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_WR_CAS_RANK4",
+    .code   = 0xbc,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_WR_CAS_RANK5",
+    .code   = 0xbd,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_WR_CAS_RANK6",
+    .code   = 0xbe,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+  { .name   = "UNC_M_WR_CAS_RANK7",
+    .code   = 0xbf,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_IMC_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_m_rd_cas_rank0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_m_rd_cas_rank0), /* shared */
+  },
+};
+
diff --git a/lib/events/intel_bdx_unc_irp_events.h b/lib/events/intel_bdx_unc_irp_events.h
new file mode 100644
index 0000000..1882a64
--- /dev/null
+++ b/lib/events/intel_bdx_unc_irp_events.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_irp
+ */
+
+static intel_x86_umask_t bdx_unc_i_cache_total_occupancy[]={
+	{ .uname  = "ANY",
+	  .ucode  = 0x100,
+	  .udesc  = "Total Write Cache Occupancy -- Any Source",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname  = "SOURCE",
+	  .ucode  = 0x200,
+	  .udesc  = "Total Write Cache Occupancy -- Select Source",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_i_coherent_ops[]={
+	{ .uname  = "CLFLUSH",
+	  .ucode  = 0x8000,
+	  .udesc  = "Coherent Ops -- CLFlush",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CRD",
+	  .ucode  = 0x200,
+	  .udesc  = "Coherent Ops -- CRd",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "DRD",
+	  .ucode  = 0x400,
+	  .udesc  = "Coherent Ops -- DRd",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "PCIDCAHINT",
+	  .ucode  = 0x2000,
+	  .udesc  = "Coherent Ops -- PCIDCAHin5t",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "PCIRDCUR",
+	  .ucode  = 0x100,
+	  .udesc  = "Coherent Ops -- PCIRdCur",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "PCITOM",
+	  .ucode  = 0x1000,
+	  .udesc  = "Coherent Ops -- PCIItoM",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "RFO",
+	  .ucode  = 0x800,
+	  .udesc  = "Coherent Ops -- RFO",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "WBMTOI",
+	  .ucode  = 0x4000,
+	  .udesc  = "Coherent Ops -- WbMtoI",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_i_misc0[]={
+	{ .uname  = "2ND_ATOMIC_INSERT",
+	  .ucode  = 0x1000,
+	  .udesc  = "Misc Events - Set 0 -- Cache Inserts of Atomic Transactions as Secondary",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "2ND_RD_INSERT",
+	  .ucode  = 0x400,
+	  .udesc  = "Misc Events - Set 0 -- Cache Inserts of Read Transactions as Secondary",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "2ND_WR_INSERT",
+	  .ucode  = 0x800,
+	  .udesc  = "Misc Events - Set 0 -- Cache Inserts of Write Transactions as Secondary",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "FAST_REJ",
+	  .ucode  = 0x200,
+	  .udesc  = "Misc Events - Set 0 -- Fastpath Rejects",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "FAST_REQ",
+	  .ucode  = 0x100,
+	  .udesc  = "Misc Events - Set 0 -- Fastpath Requests",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "FAST_XFER",
+	  .ucode  = 0x2000,
+	  .udesc  = "Misc Events - Set 0 -- Fastpath Transfers From Primary to Secondary",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "PF_ACK_HINT",
+	  .ucode  = 0x4000,
+	  .udesc  = "Misc Events - Set 0 -- Prefetch Ack Hints From Primary to Secondary",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "PF_TIMEOUT",
+	  .ucode  = 0x8000,
+	  .udesc  = "Misc Events - Set 0 -- Prefetch TimeOut",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_i_misc1[]={
+	{ .uname  = "DATA_THROTTLE",
+	  .ucode  = 0x8000,
+	  .udesc  = "Misc Events - Set 1 -- Data Throttled",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "LOST_FWD",
+	  .ucode  = 0x1000,
+	  .udesc  = "Misc Events - Set 1 -- ",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SEC_RCVD_INVLD",
+	  .ucode  = 0x2000,
+	  .udesc  = "Misc Events - Set 1 -- Received Invalid",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SEC_RCVD_VLD",
+	  .ucode  = 0x4000,
+	  .udesc  = "Misc Events - Set 1 -- Received Valid",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SLOW_I",
+	  .ucode  = 0x100,
+	  .udesc  = "Misc Events - Set 1 -- Slow Transfer of I Line",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SLOW_S",
+	  .ucode  = 0x200,
+	  .udesc  = "Misc Events - Set 1 -- Slow Transfer of S Line",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SLOW_E",
+	  .ucode  = 0x400,
+	  .udesc  = "Misc Events - Set 1 -- Slow Transfer of E Line",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SLOW_M",
+	  .ucode  = 0x800,
+	  .udesc  = "Misc Events - Set 1 -- Slow Transfer of M Line",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_i_snoop_resp[]={
+	{ .uname = "HIT_ES",
+	  .ucode = 0x400,
+	  .udesc = "Snoop Responses -- Hit E or S",
+	},
+	{ .uname = "HIT_I",
+	  .ucode = 0x200,
+	  .udesc = "Snoop Responses -- Hit I",
+	},
+	{ .uname = "HIT_M",
+	  .ucode = 0x800,
+	  .udesc = "Snoop Responses -- Hit M",
+	},
+	{ .uname = "MISS",
+	  .ucode = 0x100,
+	  .udesc = "Snoop Responses -- Miss",
+	},
+	{ .uname = "SNPCODE",
+	  .ucode = 0x1000,
+	  .udesc = "Snoop Responses -- SnpCode",
+	},
+	{ .uname = "SNPDATA",
+	  .ucode = 0x2000,
+	  .udesc = "Snoop Responses -- SnpData",
+	},
+	{ .uname = "SNPINV",
+	  .ucode = 0x4000,
+	  .udesc = "Snoop Responses -- SnpInv",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_i_transactions[]={
+	{ .uname = "ATOMIC",
+	  .ucode = 0x1000,
+	  .udesc = "Inbound Transaction Count -- Atomic",
+	},
+	{ .uname = "ORDERINGQ",
+	  .ucode = 0x4000,
+	  .udesc = "Inbound Transaction Count -- Select Source via IRP orderingQ register",
+	},
+	{ .uname = "OTHER",
+	  .ucode = 0x2000,
+	  .udesc = "Inbound Transaction Count -- Other",
+	},
+	{ .uname = "RD_PREF",
+	  .ucode = 0x400,
+	  .udesc = "Inbound Transaction Count -- Read Prefetches",
+	},
+	{ .uname = "READS",
+	  .ucode = 0x100,
+	  .udesc = "Inbound Transaction Count -- Reads",
+	},
+	{ .uname = "WRITES",
+	  .ucode = 0x200,
+	  .udesc = "Inbound Transaction Count -- Writes",
+	},
+	{ .uname = "WR_PREF",
+	  .ucode = 0x800,
+	  .udesc = "Inbound Transaction Count -- Write Prefetches",
+	},
+};
+
+
+static intel_x86_entry_t intel_bdx_unc_i_pe[]={
+  { .name   = "UNC_I_CACHE_TOTAL_OCCUPANCY",
+    .code   = 0x12,
+    .desc   = "Accumulates the number of reads and writes that are outstanding in the uncore in each cycle.  This is effectively the sum of the READ_OCCUPANCY and WRITE_OCCUPANCY events.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_cache_total_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_cache_total_occupancy),
+  },
+  { .name   = "UNC_I_CLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "Number of clocks in the IRP.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_COHERENT_OPS",
+    .code   = 0x13,
+    .desc   = "Counts the number of coherency related operations servied by the IRP",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_coherent_ops,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_coherent_ops),
+  },
+  { .name   = "UNC_I_MISC0",
+    .code   = 0x14,
+    .desc   = "",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_misc0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_misc0),
+  },
+  { .name   = "UNC_I_MISC1",
+    .code   = 0x15,
+    .desc   = "",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_misc1,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_misc1),
+  },
+  { .name   = "UNC_I_RXR_AK_INSERTS",
+    .code   = 0xa,
+    .desc   = "Counts the number of allocations into the AK Ingress.  This queue is where the IRP receives responses from R2PCIe (the ring).",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_DRS_CYCLES_FULL",
+    .code   = 0x4,
+    .desc   = "Counts the number of cycles when the BL Ingress is full.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_DRS_INSERTS",
+    .code   = 0x1,
+    .desc   = "Counts the number of allocations into the BL Ingress.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_DRS_OCCUPANCY",
+    .code   = 0x7,
+    .desc   = "Accumulates the occupancy of the BL Ingress in each cycles.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCB_CYCLES_FULL",
+    .code   = 0x5,
+    .desc   = "Counts the number of cycles when the BL Ingress is full.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCB_INSERTS",
+    .code   = 0x2,
+    .desc   = "Counts the number of allocations into the BL Ingress.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCB_OCCUPANCY",
+    .code   = 0x8,
+    .desc   = "Accumulates the occupancy of the BL Ingress in each cycles.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCS_CYCLES_FULL",
+    .code   = 0x6,
+    .desc   = "Counts the number of cycles when the BL Ingress is full.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCS_INSERTS",
+    .code   = 0x3,
+    .desc   = "Counts the number of allocations into the BL Ingress.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_RXR_BL_NCS_OCCUPANCY",
+    .code   = 0x9,
+    .desc   = "Accumulates the occupancy of the BL Ingress in each cycles.  This queue is where the IRP receives data from R2PCIe (the ring).  It is used for data returns from read requets as well as outbound MMIO writes.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_SNOOP_RESP",
+    .code   = 0x17,
+    .desc   = "",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_snoop_resp,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_snoop_resp),
+  },
+  { .name   = "UNC_I_TRANSACTIONS",
+    .code   = 0x16,
+    .desc   = "Counts the number of Inbound transactions from the IRP to the Uncore.  This can be filtered based on request type in addition to the source queue.  Note the special filtering equation.  We do OR-reduction on the request type.  If the SOURCE bit is set, then we also do AND qualification based on the source portItID.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_i_transactions,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_i_transactions),
+  },
+  { .name   = "UNC_I_TXR_AD_STALL_CREDIT_CYCLES",
+    .code   = 0x18,
+    .desc   = "Counts the number times when it is not possible to issue a request to the R2PCIe because there are no AD Egress Credits available.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_TXR_BL_STALL_CREDIT_CYCLES",
+    .code   = 0x19,
+    .desc   = "Counts the number times when it is not possible to issue data to the R2PCIe because there are no BL Egress Credits available.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_TXR_DATA_INSERTS_NCB",
+    .code   = 0xe,
+    .desc   = "Counts the number of requests issued to the switch (towards the devices).",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_TXR_DATA_INSERTS_NCS",
+    .code   = 0xf,
+    .desc   = "Counts the number of requests issued to the switch (towards the devices).",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+  { .name   = "UNC_I_TXR_REQUEST_OCCUPANCY",
+    .code   = 0xd,
+    .desc   = "Accumultes the number of outstanding outbound requests from the IRP to the switch (towards the devices).  This can be used in conjuection with the allocations event in order to calculate average latency of outbound requests.",
+    .modmsk = BDX_UNC_IRP_ATTRS,
+    .cntmsk = 0x3,
+  },
+};
diff --git a/lib/events/intel_bdx_unc_pcu_events.h b/lib/events/intel_bdx_unc_pcu_events.h
new file mode 100644
index 0000000..24b0bd5
--- /dev/null
+++ b/lib/events/intel_bdx_unc_pcu_events.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_pcu
+ */
+
+static intel_x86_umask_t bdx_unc_p_power_state_occupancy[]={
+	{ .uname = "CORES_C0",
+	  .ucode = 0x4000,
+	  .udesc = "Number of cores in C-State -- C0 and C1",
+	},
+	{ .uname = "CORES_C3",
+	  .ucode = 0x8000,
+	  .udesc = "Number of cores in C-State -- C3",
+	},
+	{ .uname = "CORES_C6",
+	  .ucode = 0xc000,
+	  .udesc = "Number of cores in C-State -- C6 and C7",
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_p_pe[]={
+  { .name   = "UNC_P_CLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "The PCU runs off a fixed 1 GHz clock.  This event counts the number of pclk cycles measured while the counter was enabled.  The pclk, like the Memory Controllers dclk, counts at a constant rate making it a good measure of actual wall timee.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE0_TRANSITION_CYCLES",
+    .code   = 0x60,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE10_TRANSITION_CYCLES",
+    .code   = 0x6a,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE11_TRANSITION_CYCLES",
+    .code   = 0x6b,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE12_TRANSITION_CYCLES",
+    .code   = 0x6c,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE13_TRANSITION_CYCLES",
+    .code   = 0x6d,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE14_TRANSITION_CYCLES",
+    .code   = 0x6e,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE15_TRANSITION_CYCLES",
+    .code   = 0x6f,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE16_TRANSITION_CYCLES",
+    .code   = 0x70,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE17_TRANSITION_CYCLES",
+    .code   = 0x71,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE1_TRANSITION_CYCLES",
+    .code   = 0x61,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE2_TRANSITION_CYCLES",
+    .code   = 0x62,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE3_TRANSITION_CYCLES",
+    .code   = 0x63,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE4_TRANSITION_CYCLES",
+    .code   = 0x64,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE5_TRANSITION_CYCLES",
+    .code   = 0x65,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE6_TRANSITION_CYCLES",
+    .code   = 0x66,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE7_TRANSITION_CYCLES",
+    .code   = 0x67,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE8_TRANSITION_CYCLES",
+    .code   = 0x68,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_CORE9_TRANSITION_CYCLES",
+    .code   = 0x69,
+    .desc   = "Number of cycles spent performing core C state transitions.  There is one event per core.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE0",
+    .code   = 0x30,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE1",
+    .code   = 0x31,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE10",
+    .code   = 0x3a,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE11",
+    .code   = 0x3b,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE12",
+    .code   = 0x3c,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE13",
+    .code   = 0x3d,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE14",
+    .code   = 0x3e,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE15",
+    .code   = 0x3f,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE16",
+    .code   = 0x40,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE17",
+    .code   = 0x41,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE2",
+    .code   = 0x32,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE3",
+    .code   = 0x33,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE4",
+    .code   = 0x34,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE5",
+    .code   = 0x35,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE6",
+    .code   = 0x36,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE7",
+    .code   = 0x37,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE8",
+    .code   = 0x38,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_DEMOTIONS_CORE9",
+    .code   = 0x39,
+    .desc   = "Counts the number of times when a configurable cores had a C-state demotion",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
+    .code   = 0x4,
+    .desc   = "Counts the number of cycles when thermal conditions are the upper limit on frequency.  This is related to the THERMAL_THROTTLE CYCLES_ABOVE_TEMP event, which always counts cycles when we are above the thermal temperature.  This event (STRONGEST_UPPER_LIMIT) is sampled at the output of the algorithm that determines the actual frequency, while THERMAL_THROTTLE looks at the input.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_FREQ_MAX_OS_CYCLES",
+    .code   = 0x6,
+    .desc   = "Counts the number of cycles when the OS is the upper limit on frequency.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_FREQ_MAX_POWER_CYCLES",
+    .code   = 0x5,
+    .desc   = "Counts the number of cycles when power is the upper limit on frequency.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_FREQ_MIN_IO_P_CYCLES",
+    .code   = 0x73,
+    .desc   = "Counts the number of cycles when IO P Limit is preventing us from dropping the frequency lower.  This algorithm monitors the needs to the IO subsystem on both local and remote sockets and will maintain a frequency high enough to maintain good IO BW.  This is necessary for when all the IA cores on a socket are idle but a user still would like to maintain high IO Bandwidth.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_FREQ_TRANS_CYCLES",
+    .code   = 0x74,
+    .desc   = "Counts the number of cycles when the system is changing frequency.  This can not be filtered by thread ID.  One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_MEMORY_PHASE_SHEDDING_CYCLES",
+    .code   = 0x2f,
+    .desc   = "Counts the number of cycles that the PCU has triggered memory phase shedding.  This is a mode that can be run in the iMC physicals that saves power at the expense of additional latency.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_POWER_STATE_OCCUPANCY",
+    .code   = 0x80,
+    .desc   = "This is an occupancy event that tracks the number of cores that are in the chosen C-State.  It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_p_power_state_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_p_power_state_occupancy),
+  },
+  { .name   = "UNC_P_PROCHOT_EXTERNAL_CYCLES",
+    .code   = 0xa,
+    .desc   = "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_PROCHOT_INTERNAL_CYCLES",
+    .code   = 0x9,
+    .desc   = "Counts the number of cycles that we are in Interal PROCHOT mode.  This mode is triggered when a sensor on the die determines that we are too hot and must throttle to avoid damaging the chip.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_TOTAL_TRANSITION_CYCLES",
+    .code   = 0x72,
+    .desc   = "Number of cycles spent performing core C state transitions across all cores.",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_BANDWIDTH_MAX_RANGE",
+    .code   = 0x7e,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_TRANSITIONS_DOWN",
+    .code   = 0x7c,
+    .desc   = "Ring GV down due to low traffic",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_TRANSITIONS_IO_P_LIMIT",
+    .code   = 0x7d,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_TRANSITIONS_NO_CHANGE",
+    .code   = 0x79,
+    .desc   = "Ring GV with same final and inital frequency",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_TRANSITIONS_UP_RING",
+    .code   = 0x7a,
+    .desc   = "Ring GV up due to high ring traffic",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_UFS_TRANSITIONS_UP_STALL",
+    .code   = 0x7b,
+    .desc   = "Ring GV up due to high core stalls",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_P_VR_HOT_CYCLES",
+    .code   = 0x42,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_PCU_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name = "UNC_P_FREQ_BAND0_CYCLES",
+    .desc = "Frequency Residency",
+    .code = 0xb,
+    .cntmsk = 0xf,
+    .flags = INTEL_X86_NO_AUTOENCODE,
+    .modmsk = BDX_UNC_PCU_BAND_ATTRS,
+    .modmsk_req = _SNBEP_UNC_ATTR_FF,
+  },
+  { .name = "UNC_P_FREQ_BAND1_CYCLES",
+    .desc = "Frequency Residency",
+    .code = 0xc,
+    .cntmsk = 0xf,
+    .flags = INTEL_X86_NO_AUTOENCODE,
+    .modmsk = BDX_UNC_PCU_BAND_ATTRS,
+    .modmsk_req = _SNBEP_UNC_ATTR_FF,
+  },
+  { .name = "UNC_P_FREQ_BAND2_CYCLES",
+    .desc = "Frequency Residency",
+    .code = 0xd,
+    .cntmsk = 0xf,
+    .flags = INTEL_X86_NO_AUTOENCODE,
+    .modmsk = BDX_UNC_PCU_BAND_ATTRS,
+    .modmsk_req = _SNBEP_UNC_ATTR_FF,
+  },
+  { .name = "UNC_P_FREQ_BAND3_CYCLES",
+    .desc = "Frequency Residency",
+    .code = 0xe,
+    .cntmsk = 0xf,
+    .flags = INTEL_X86_NO_AUTOENCODE,
+    .modmsk = BDX_UNC_PCU_BAND_ATTRS,
+    .modmsk_req = _SNBEP_UNC_ATTR_FF,
+  },
+  { .name = "UNC_P_FIVR_PS_PS0_CYCLES",
+    .desc = "Cycles spent in phase-shedding power state 0",
+    .code = 0x75,
+    .cntmsk = 0xf,
+    .modmsk = BDX_UNC_PCU_ATTRS,
+  },
+  { .name = "UNC_P_FIVR_PS_PS1_CYCLES",
+    .desc = "Cycles spent in phase-shedding power state 1",
+    .code = 0x76,
+    .cntmsk = 0xf,
+    .modmsk = BDX_UNC_PCU_ATTRS,
+  },
+  { .name = "UNC_P_FIVR_PS_PS2_CYCLES",
+    .desc = "Cycles spent in phase-shedding power state 2",
+    .code = 0x77,
+    .cntmsk = 0xf,
+    .modmsk = BDX_UNC_PCU_ATTRS,
+  },
+  { .name = "UNC_P_FIVR_PS_PS3_CYCLES",
+    .desc = "Cycles spent in phase-shedding power state 3",
+    .code = 0x78,
+    .cntmsk = 0xf,
+    .modmsk = BDX_UNC_PCU_ATTRS,
+  },
+};
diff --git a/lib/events/intel_bdx_unc_qpi_events.h b/lib/events/intel_bdx_unc_qpi_events.h
new file mode 100644
index 0000000..18c010a
--- /dev/null
+++ b/lib/events/intel_bdx_unc_qpi_events.h
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_qpi
+ */
+
+static intel_x86_umask_t bdx_unc_q_direct2core[]={
+	{ .uname = "FAILURE_CREDITS",
+	  .ucode = 0x200,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - Egress Credits",
+	},
+	{ .uname = "FAILURE_CREDITS_MISS",
+	  .ucode = 0x2000,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - Egress and RBT Miss",
+	},
+	{ .uname = "FAILURE_CREDITS_RBT",
+	  .ucode = 0x800,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - Egress and RBT Invalid",
+	},
+	{ .uname = "FAILURE_CREDITS_RBT_MISS",
+	  .ucode = 0x8000,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - Egress and RBT Miss, Invalid",
+	},
+	{ .uname = "FAILURE_MISS",
+	  .ucode = 0x1000,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - RBT Miss",
+	},
+	{ .uname = "FAILURE_RBT_HIT",
+	  .ucode = 0x400,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - RBT Invalid",
+	},
+	{ .uname = "FAILURE_RBT_MISS",
+	  .ucode = 0x4000,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Failure - RBT Miss and Invalid",
+	},
+	{ .uname = "SUCCESS_RBT_HIT",
+	  .ucode = 0x100,
+	  .udesc = "Direct 2 Core Spawning -- Spawn Success",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_rxl_credits_consumed_vn0[]={
+	{ .uname = "DRS",
+	  .ucode = 0x100,
+	  .udesc = "VN0 Credit Consumed -- DRS",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x800,
+	  .udesc = "VN0 Credit Consumed -- HOM",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x200,
+	  .udesc = "VN0 Credit Consumed -- NCB",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x400,
+	  .udesc = "VN0 Credit Consumed -- NCS",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x2000,
+	  .udesc = "VN0 Credit Consumed -- NDR",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x1000,
+	  .udesc = "VN0 Credit Consumed -- SNP",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_rxl_flits_g1[]={
+	{ .uname  = "DRS",
+	  .ucode  = 0x1800,
+	  .udesc  = "Flits Received - Group 1 -- DRS Flits (both Header and Data)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "DRS_DATA",
+	  .ucode = 0x800,
+	  .udesc = "Flits Received - Group 1 -- DRS Data Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "DRS_NONDATA",
+	  .ucode = 0x1000,
+	  .udesc = "Flits Received - Group 1 -- DRS Header Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x600,
+	  .udesc = "Flits Received - Group 1 -- HOM Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "HOM_NONREQ",
+	  .ucode = 0x400,
+	  .udesc = "Flits Received - Group 1 -- HOM Non-Request Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "HOM_REQ",
+	  .ucode = 0x200,
+	  .udesc = "Flits Received - Group 1 -- HOM Request Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x100,
+	  .udesc = "Flits Received - Group 1 -- SNP Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_rxl_flits_g2[]={
+	{ .uname  = "NCB",
+	  .ucode  = 0xc00,
+	  .udesc  = "Flits Received - Group 2 -- Non-Coherent Rx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCB_DATA",
+	  .ucode  = 0x400,
+	  .udesc  = "Flits Received - Group 2 -- Non-Coherent data Rx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCB_NONDATA",
+	  .ucode  = 0x800,
+	  .udesc  = "Flits Received - Group 2 -- Non-Coherent non-data Rx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCS",
+	  .ucode  = 0x1000,
+	  .udesc  = "Flits Received - Group 2 -- Non-Coherent standard Rx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NDR_AD",
+	  .ucode  = 0x100,
+	  .udesc  = "Flits Received - Group 2 -- Non-Data Response Rx Flits - AD",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NDR_AK",
+	  .ucode  = 0x200,
+	  .udesc  = "Flits Received - Group 2 -- Non-Data Response Rx Flits - AK",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_rxl_inserts_drs[]={
+	{ .uname = "VN0",
+	  .ucode = 0x100,
+	  .udesc = "for VN0",
+	},
+	{ .uname = "VN1",
+	  .ucode = 0x200,
+	  .udesc = "for VN1",
+	},
+};
+
+static const intel_x86_umask_t bdx_unc_q_rxl_flits_g0[]={
+	{ .uname = "IDLE",
+	  .udesc  = "Number of data flits over QPI that do not hold payload. When QPI is not in a power saving state, it continuously transmits flits across the link. When there are no protocol flits to send, it will send IDLE and NULL flits across",
+	  .ucode  = 0x200,
+	  .uflags = INTEL_X86_NCOMBO,
+  },
+	{ .uname = "DATA",
+	  .udesc  = "Number of data flits over QPI",
+	  .ucode  = 0x200,
+	  .uflags = INTEL_X86_NCOMBO,
+  },
+	{ .uname = "NON_DATA",
+	  .udesc  = "Number of non-NULL non-data flits over QPI",
+	  .ucode  = 0x400,
+	  .uflags = INTEL_X86_NCOMBO,
+  },
+};
+
+static intel_x86_umask_t bdx_unc_q_txl_flits_g0[]={
+	{ .uname  = "DATA",
+	  .ucode  = 0x200,
+	  .udesc  = "Flits Transferred - Group 0 -- Data Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NON_DATA",
+	  .ucode  = 0x400,
+	  .udesc  = "Flits Transferred - Group 0 -- Non-Data protocol Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_txl_flits_g1[]={
+	{ .uname  = "DRS",
+	  .ucode  = 0x1800,
+	  .udesc  = "Flits Transferred - Group 1 -- DRS Flits (both Header and Data)",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "DRS_DATA",
+	  .ucode  = 0x800,
+	  .udesc  = "Flits Transferred - Group 1 -- DRS Data Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "DRS_NONDATA",
+	  .ucode  = 0x1000,
+	  .udesc  = "Flits Transferred - Group 1 -- DRS Header Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "HOM",
+	  .ucode  = 0x600,
+	  .udesc  = "Flits Transferred - Group 1 -- HOM Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "HOM_NONREQ",
+	  .ucode  = 0x400,
+	  .udesc  = "Flits Transferred - Group 1 -- HOM Non-Request Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "HOM_REQ",
+	  .ucode  = 0x200,
+	  .udesc  = "Flits Transferred - Group 1 -- HOM Request Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "SNP",
+	  .ucode  = 0x100,
+	  .udesc  = "Flits Transferred - Group 1 -- SNP Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_txl_flits_g2[]={
+	{ .uname  = "NCB",
+	  .ucode  = 0xc00,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Coherent Bypass Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCB_DATA",
+	  .ucode  = 0x400,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Coherent data Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCB_NONDATA",
+	  .ucode  = 0x800,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Coherent non-data Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NCS",
+	  .ucode  = 0x1000,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Coherent standard Tx Flits",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NDR_AD",
+	  .ucode  = 0x100,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Data Response Tx Flits - AD",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "NDR_AK",
+	  .ucode  = 0x200,
+	  .udesc  = "Flits Transferred - Group 2 -- Non-Data Response Tx Flits - AK",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_q_txr_bl_drs_credit_acquired[]={
+	{ .uname  = "VN0",
+	  .ucode  = 0x100,
+	  .udesc  = "R3QPI Egress Credit Occupancy - DRS -- for VN0",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "VN1",
+	  .ucode  = 0x200,
+	  .udesc  = "R3QPI Egress Credit Occupancy - DRS -- for VN1",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "VN_SHR",
+	  .ucode  = 0x400,
+	  .udesc  = "R3QPI Egress Credit Occupancy - DRS -- for Shared VN",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_q_pe[]={
+  { .name   = "UNC_Q_CLOCKTICKS",
+    .code   = 0x14,
+    .desc   = "Counts the number of clocks in the QPI LL.  This clock runs at 1/4th the GT/s speed of the QPI link.  For example, a 4GT/s link will have qfclk or 1GHz.  BDX does not support dynamic link speeds, so this frequency is fixexed.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_CTO_COUNT",
+    .code   = 0x38 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of CTO (cluster trigger outs) events that were asserted across the two slots.  If both slots trigger in a given cycle, the event will increment by 2.  You can use edge detect to count the number of cases when both events triggered.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_DIRECT2CORE",
+    .code   = 0x13,
+    .desc   = "Counts the number of DRS packets that we attempted to do direct2core on.  There are 4 mutually exlusive filters.  Filter [0] can be used to get successful spawns, while [1:3] provide the different failure cases.  Note that this does not count packets that are not candidates for Direct2Core.  The only candidates for Direct2Core are DRS packets destined for Cbos.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_direct2core,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_direct2core),
+  },
+  { .name   = "UNC_Q_L1_POWER_CYCLES",
+    .code   = 0x12,
+    .desc   = "Number of QPI qfclk cycles spent in L1 power mode.  L1 is a mode that totally shuts down a QPI link.  Use edge detect to count the number of instances when the QPI link entered L1.  Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another. Because L1 totally shuts down the link, it takes a good amount of time to exit this mode.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL0P_POWER_CYCLES",
+    .code   = 0x10,
+    .desc   = "Number of QPI qfclk cycles spent in L0p power mode.  L0p is a mode where we disable 1/2 of the QPI lanes, decreasing our bandwidth in order to save power.  It increases snoop and data transfer latencies and decreases overall bandwidth.  This mode can be very useful in NUMA optimized workloads that largely only utilize QPI for snoops and their responses.  Use edge detect to count the number of instances when the QPI link entered L0p.  Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL0_POWER_CYCLES",
+    .code   = 0xf,
+    .desc   = "Number of QPI qfclk cycles spent in L0 power mode in the Link Layer.  L0 is the default mode which provides the highest performance with the most power.  Use edge detect to count the number of instances that the link entered L0.  Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.  The phy layer  sometimes leaves L0 for training, which will not be captured by this event.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_BYPASSED",
+    .code   = 0x9,
+    .desc   = "Counts the number of times that an incoming flit was able to bypass the flit buffer and pass directly across the BGF and into the Egress.  This is a latency optimization, and should generally be the common case.  If this value is less than the number of flits transfered, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_CREDITS_CONSUMED_VN0",
+    .code   = 0x1e | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of times that an RxQ VN0 credit was consumed (i.e. message uses a VN0 credit for the Rx Buffer).  This includes packets that went through the RxQ and those that were bypasssed.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_credits_consumed_vn0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_credits_consumed_vn0),
+  },
+  { .name   = "UNC_Q_RXL_CREDITS_CONSUMED_VN1",
+    .code   = 0x39 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of times that an RxQ VN1 credit was consumed (i.e. message uses a VN1 credit for the Rx Buffer).  This includes packets that went through the RxQ and those that were bypasssed.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_credits_consumed_vn0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_credits_consumed_vn0),
+  },
+  { .name   = "UNC_Q_RXL_CREDITS_CONSUMED_VNA",
+    .code   = 0x1d | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of times that an RxQ VNA credit was consumed (i.e. message uses a VNA credit for the Rx Buffer).  This includes packets that went through the RxQ and those that were bypasssed.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_CYCLES_NE",
+    .code   = 0xa,
+    .desc   = "Counts the number of cycles that the QPI RxQ was not empty.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy Accumulator event to calculate the average occupancy.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_FLITS_G0",
+    .code   = 0x1,
+    .desc   = "Counts the number of flits received from the QPI Link.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_flits_g0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_flits_g0),
+  },
+  { .name   = "UNC_Q_RXL_FLITS_G1",
+    .code   = 0x2 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of flits received from the QPI Link.  This is one of three groups that allow us to track flits.  It includes filters for SNP, HOM, and DRS message classes.  Each flit is made up of 80 bits of information (in addition to some ECC data).  In full-width (L0) mode, flits are made up of four fits, each of which contains 20 bits of data (along with some additional ECC data).   In half-width (L0p) mode, the fits are only 10 bits, and therefore it takes twice as many fits to transmit a flit.  When one talks about QPI speed (for example, 8.0 GT/s), the transfers here refer to fits.  Therefore, in L0, the system will transfer 1 flit at the rate of 1/4th the QPI speed.  One can calculate the bandwidth of the link by taking: flits*80b/time.  Note that this is not the same as data bandwidth.  For example, when we are transfering a 64B cacheline across QPI, we will break it into 9 flits -- 1 with header information and 8 with 64 bits of actual data and an additional 16 bits of other information.  To calculate data bandwidth, one should therefore do: datld therefore do: data flits * 8B / time.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_flits_g1,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_flits_g1),
+  },
+  { .name   = "UNC_Q_RXL_FLITS_G2",
+    .code   = 0x3 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of flits received from the QPI Link.  This is one of three groups that allow us to track flits.  It includes filters for NDR, NCB, and NCS message classes.  Each flit is made up of 80 bits of information (in addition to some ECC data).  In full-width (L0) mode, flits are made up of four fits, each of which contains 20 bits of data (along with some additional ECC data).   In half-width (L0p) mode, the fits are only 10 bits, and therefore it takes twice as many fits to transmit a flit.  When one talks about QPI speed (for example, 8.0 GT/s), the transfers here refer to fits.  Therefore, in L0, the system will transfer 1 flit at the rate of 1/4th the QPI speed.  One can calculate the bandwidth of the link by taking: flits*80b/time.  Note that this is not the same as data bandwidth.  For example, when we are transfering a 64B cacheline across QPI, we will break it into 9 flits -- 1 with header information and 8 with 64 bits of actual data and an additional 16 bits of other information.  To calculate data bandwidth, one should therefore do: datld therefore do: data flits * 8B / time.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_flits_g2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_flits_g2),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS",
+    .code   = 0x8,
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_DRS",
+    .code   = 0x9 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only DRS flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_HOM",
+    .code   = 0xc | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only HOM flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_NCB",
+    .code   = 0xa | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only NCB flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_NCS",
+    .code   = 0xb | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only NCS flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_NDR",
+    .code   = 0xe | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only NDR flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_INSERTS_SNP",
+    .code   = 0xd | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of allocations into the QPI Rx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.  This monitors only SNP flits.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY",
+    .code   = 0xb,
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_DRS",
+    .code   = 0x15 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors DRS flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_HOM",
+    .code   = 0x18 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors HOM flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_NCB",
+    .code   = 0x16 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors NCB flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_NCS",
+    .code   = 0x17 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors NCS flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_NDR",
+    .code   = 0x1a | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors NDR flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_RXL_OCCUPANCY_SNP",
+    .code   = 0x19 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Accumulates the number of elements in the QPI RxQ in each cycle.  Generally, when data is transmitted across QPI, it will bypass the RxQ and pass directly to the ring interface.  If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency.  This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.  This monitors SNP flits only.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXL0P_POWER_CYCLES",
+    .code   = 0xd,
+    .desc   = "Number of QPI qfclk cycles spent in L0p power mode.  L0p is a mode where we disable 1/2 of the QPI lanes, decreasing our bandwidth in order to save power.  It increases snoop and data transfer latencies and decreases overall bandwidth.  This mode can be very useful in NUMA optimized workloads that largely only utilize QPI for snoops and their responses.  Use edge detect to count the number of instances when the QPI link entered L0p.  Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXL0_POWER_CYCLES",
+    .code   = 0xc,
+    .desc   = "Number of QPI qfclk cycles spent in L0 power mode in the Link Layer.  L0 is the default mode which provides the highest performance with the most power.  Use edge detect to count the number of instances that the link entered L0.  Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.  The phy layer  sometimes leaves L0 for training, which will not be captured by this event.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXL_BYPASSED",
+    .code   = 0x5,
+    .desc   = "Counts the number of times that an incoming flit was able to bypass the Tx flit buffer and pass directly out the QPI Link. Generally, when data is transmitted across QPI, it will bypass the TxQ and pass directly to the link.  However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXL_CYCLES_NE",
+    .code   = 0x6,
+    .desc   = "Counts the number of cycles when the TxQ is not empty. Generally, when data is transmitted across QPI, it will bypass the TxQ and pass directly to the link.  However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXL_FLITS_G0",
+    .code   = 0x0,
+    .desc   = "Counts the number of flits transmitted across the QPI Link.  It includes filters for Idle, protocol, and Data Flits.  Each flit is made up of 80 bits of information (in addition to some ECC data).  In full-width (L0) mode, flits are made up of four fits, each of which contains 20 bits of data (along with some additional ECC data).   In half-width (L0p) mode, the fits are only 10 bits, and therefore it takes twice as many fits to transmit a flit.  When one talks about QPI speed (for example, 8.0 GT/s), the transfers here refer to fits.  Therefore, in L0, the system will transfer 1 flit at the rate of 1/4th the QPI speed.  One can calculate the bandwidth of the link by taking: flits*80b/time.  Note that this is not the same as data bandwidth.  For example, when we are transfering a 64B cacheline across QPI, we will break it into 9 flits -- 1 with header information and 8 with 64 bits of actual data and an additional 16 bits of other information.  To calculate data bandwidth, one should therefore do: data flits * 8B / time (for L0) or 4B instfor L0) or 4B instead of 8B for L0p.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_txl_flits_g0,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_txl_flits_g0),
+  },
+  { .name   = "UNC_Q_TXL_FLITS_G1",
+    .code   = 0x0 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of flits transmitted across the QPI Link.  It includes filters for Idle, protocol, and Data Flits.  Each flit is made up of 80 bits of information (in addition to some ECC data).  In full-width (L0) mode, flits are made up of four fits, each of which contains 20 bits of data (along with some additional ECC data).   In half-width (L0p) mode, the fits are only 10 bits, and therefore it takes twice as many fits to transmit a flit.  When one talks about QPI speed (for example, 8.0 GT/s), the transfers here refer to fits.  Therefore, in L0, the system will transfer 1 flit at the rate of 1/4th the QPI speed.  One can calculate the bandwidth of the link by taking: flits*80b/time.  Note that this is not the same as data bandwidth.  For example, when we are transfering a 64B cacheline across QPI, we will break it into 9 flits -- 1 with header information and 8 with 64 bits of actual data and an additional 16 bits of other information.  To calculate data bandwidth, one should therefore do: data flits * 8B / time (for L0) or 4B instfor L0) or 4B instead of 8B for L0p.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_txl_flits_g1,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_txl_flits_g1),
+  },
+  { .name   = "UNC_Q_TXL_FLITS_G2",
+    .code   = 0x1 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Counts the number of flits trasmitted across the QPI Link.  This is one of three groups that allow us to track flits.  It includes filters for NDR, NCB, and NCS message classes.  Each flit is made up of 80 bits of information (in addition to some ECC data).  In full-width (L0) mode, flits are made up of four fits, each of which contains 20 bits of data (along with some additional ECC data).   In half-width (L0p) mode, the fits are only 10 bits, and therefore it takes twice as many fits to transmit a flit.  When one talks about QPI speed (for example, 8.0 GT/s), the transfers here refer to fits.  Therefore, in L0, the system will transfer 1 flit at the rate of 1/4th the QPI speed.  One can calculate the bandwidth of the link by taking: flits*80b/time.  Note that this is not the same as data bandwidth.  For example, when we are transfering a 64B cacheline across QPI, we will break it into 9 flits -- 1 with header information and 8 with 64 bits of actual data and an additional 16 bits of other information.  To calculate data bandwidth, one should therefore do: datld therefore do: data flits * 8B / time.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_txl_flits_g2,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_txl_flits_g2),
+  },
+  { .name   = "UNC_Q_TXL_INSERTS",
+    .code   = 0x4,
+    .desc   = "Number of allocations into the QPI Tx Flit Buffer.  Generally, when data is transmitted across QPI, it will bypass the TxQ and pass directly to the link.  However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link.  This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXL_OCCUPANCY",
+    .code   = 0x7,
+    .desc   = "Accumulates the number of flits in the TxQ.  Generally, when data is transmitted across QPI, it will bypass the TxQ and pass directly to the link.  However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link. This can be used with the cycles not empty event to track average occupancy, or the allocations event to track average lifetime in the TxQ.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXR_AD_HOM_CREDIT_ACQUIRED",
+    .code   = 0x26 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of link layer credits into the R3 (for transactions across the BGF) acquired each cycle. Flow Control FIFO for Home messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AD_HOM_CREDIT_OCCUPANCY",
+    .code   = 0x22 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of link layer credits into the R3 (for transactions across the BGF) available in each cycle.  Flow Control FIFO for HOM messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AD_NDR_CREDIT_ACQUIRED",
+    .code   = 0x28 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of link layer credits into the R3 (for transactions across the BGF) acquired each cycle.  Flow Control FIFO for NDR messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AD_NDR_CREDIT_OCCUPANCY",
+    .code   = 0x24 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of link layer credits into the R3 (for transactions across the BGF) available in each cycle. Flow Control FIFO  for NDR messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AD_SNP_CREDIT_ACQUIRED",
+    .code   = 0x27 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of link layer credits into the R3 (for transactions across the BGF) acquired each cycle.  Flow Control FIFO for Snoop messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AD_SNP_CREDIT_OCCUPANCY",
+    .code   = 0x23 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of link layer credits into the R3 (for transactions across the BGF) available in each cycle.  Flow Control FIFO fro Snoop messages on AD.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_AK_NDR_CREDIT_ACQUIRED",
+    .code   = 0x29 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of credits into the R3 (for transactions across the BGF) acquired each cycle. Local NDR message class to AK Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXR_AK_NDR_CREDIT_OCCUPANCY",
+    .code   = 0x25 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of credits into the R3 (for transactions across the BGF) available in each cycle.  Local NDR message class to AK Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_TXR_BL_DRS_CREDIT_ACQUIRED",
+    .code   = 0x2a | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of credits into the R3 (for transactions across the BGF) acquired each cycle. DRS message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_txr_bl_drs_credit_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_txr_bl_drs_credit_acquired),
+  },
+  { .name   = "UNC_Q_TXR_BL_DRS_CREDIT_OCCUPANCY",
+    .code   = 0x1f | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of credits into the R3 (for transactions across the BGF) available in each cycle.  DRS message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_txr_bl_drs_credit_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_txr_bl_drs_credit_acquired),
+  },
+  { .name   = "UNC_Q_TXR_BL_NCB_CREDIT_ACQUIRED",
+    .code   = 0x2b | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of credits into the R3 (for transactions across the BGF) acquired each cycle. NCB message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_BL_NCB_CREDIT_OCCUPANCY",
+    .code   = 0x20 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of credits into the R3 (for transactions across the BGF) available in each cycle.  NCB message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_BL_NCS_CREDIT_ACQUIRED",
+    .code   = 0x2c | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of credits into the R3 (for transactions across the BGF) acquired each cycle. NCS message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_TXR_BL_NCS_CREDIT_OCCUPANCY",
+    .code   = 0x21 | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Occupancy event that tracks the number of credits into the R3 (for transactions across the BGF) available in each cycle.  NCS message class to BL Egress.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_q_rxl_inserts_drs,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_q_rxl_inserts_drs),
+  },
+  { .name   = "UNC_Q_VNA_CREDIT_RETURNS",
+    .code   = 0x1c | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of VNA credits returned.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_Q_VNA_CREDIT_RETURN_OCCUPANCY",
+    .code   = 0x1b | (1 << 21), /* extra ev_sel_ext bit set */
+    .desc   = "Number of VNA credits in the Rx side that are waitng to be returned back across the link.",
+    .modmsk = BDX_UNC_QPI_ATTRS,
+    .cntmsk = 0xf,
+  },
+};
diff --git a/lib/events/intel_bdx_unc_r2pcie_events.h b/lib/events/intel_bdx_unc_r2pcie_events.h
new file mode 100644
index 0000000..5ce8845
--- /dev/null
+++ b/lib/events/intel_bdx_unc_r2pcie_events.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_r2pcie
+ */
+
+static intel_x86_umask_t bdx_unc_r2_iio_credit[]={
+	{ .uname = "ISOCH_QPI0",
+	  .ucode = 0x400,
+	  .udesc = "TBD",
+	},
+	{ .uname = "ISOCH_QPI1",
+	  .ucode = 0x800,
+	  .udesc = "TBD",
+	},
+	{ .uname = "PRQ_QPI0",
+	  .ucode = 0x100,
+	  .udesc = "TBD",
+	},
+	{ .uname = "PRQ_QPI1",
+	  .ucode = 0x200,
+	  .udesc = "TBD",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_ring_ad_used[]={
+	{ .uname  = "CCW",
+	  .ucode  = 0xc00,
+	  .udesc  = "Counterclockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CCW_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "Counterclockwise and Even",
+	},
+	{ .uname = "CCW_ODD",
+	  .ucode = 0x800,
+	  .udesc = "Counterclockwise and Odd",
+	},
+	{ .uname  = "CW",
+	  .ucode  = 0x300,
+	  .udesc  = "Clockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CW_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "Clockwise and Even",
+	},
+	{ .uname = "CW_ODD",
+	  .ucode = 0x200,
+	  .udesc = "Clockwise and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_ring_ak_bounces[]={
+	{ .uname = "DN",
+	  .ucode = 0x200,
+	  .udesc = "AK Ingress Bounced -- Dn",
+	},
+	{ .uname = "UP",
+	  .ucode = 0x100,
+	  .udesc = "AK Ingress Bounced -- Up",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_ring_iv_used[]={
+	{ .uname  = "ANY",
+	  .ucode  = 0xf00,
+	  .udesc  = "Any directions",
+	  .uflags = INTEL_X86_DFL,
+	},
+	{ .uname  = "CCW",
+	  .ucode  = 0xc00,
+	  .udesc  = "Counterclockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname  = "CW",
+	  .ucode  = 0x300,
+	  .udesc  = "Clockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_rxr_cycles_ne[]={
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "NCB",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "NCS",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_rxr_occupancy[]={
+	{ .uname  = "DRS",
+	  .ucode  = 0x800,
+	  .udesc  = "Ingress Occupancy Accumulator -- DRS",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_sbo0_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "SBo0 Credits Acquired -- For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "SBo0 Credits Acquired -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_stall_no_sbo_credit[]={
+	{ .uname = "SBO0_AD",
+	  .ucode = 0x100,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, AD Ring",
+	},
+	{ .uname = "SBO0_BL",
+	  .ucode = 0x400,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, BL Ring",
+	},
+	{ .uname = "SBO1_AD",
+	  .ucode = 0x200,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, AD Ring",
+	},
+	{ .uname = "SBO1_BL",
+	  .ucode = 0x800,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_txr_cycles_full[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "Egress Cycles Full -- AD",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x200,
+	  .udesc = "Egress Cycles Full -- AK",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "Egress Cycles Full -- BL",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_txr_cycles_ne[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "Egress Cycles Not Empty -- AD",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x200,
+	  .udesc = "Egress Cycles Not Empty -- AK",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "Egress Cycles Not Empty -- BL",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r2_txr_nack_cw[]={
+	{ .uname = "DN_AD",
+	  .ucode = 0x100,
+	  .udesc = "Egress CCW NACK -- AD CCW",
+	},
+	{ .uname = "DN_AK",
+	  .ucode = 0x400,
+	  .udesc = "Egress CCW NACK -- AK CCW",
+	},
+	{ .uname = "DN_BL",
+	  .ucode = 0x200,
+	  .udesc = "Egress CCW NACK -- BL CCW",
+	},
+	{ .uname = "UP_AD",
+	  .ucode = 0x800,
+	  .udesc = "Egress CCW NACK -- AK CCW",
+	},
+	{ .uname = "UP_AK",
+	  .ucode = 0x2000,
+	  .udesc = "Egress CCW NACK -- BL CW",
+	},
+	{ .uname = "UP_BL",
+	  .ucode = 0x1000,
+	  .udesc = "Egress CCW NACK -- BL CCW",
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_r2_pe[]={
+  { .name   = "UNC_R2_CLOCKTICKS",
+    .code   = 0x1,
+    .desc   = "Counts the number of uclks in the R2PCIe uclk domain.  This could be slightly different than the count in the Ubox because of enable/freeze delays.  However, because the R2PCIe is close to the Ubox, they generally should not diverge by more than a handful of cycles.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_R2_IIO_CREDIT",
+    .code   = 0x2d,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_iio_credit,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_iio_credit),
+  },
+  { .name   = "UNC_R2_RING_AD_USED",
+    .code   = 0x7,
+    .desc   = "Counts the number of cycles that the AD ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_ring_ad_used),
+  },
+  { .name   = "UNC_R2_RING_AK_BOUNCES",
+    .code   = 0x12,
+    .desc   = "Counts the number of times when a request destined for the AK ingress bounced.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_ring_ak_bounces,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_ring_ak_bounces),
+  },
+  { .name   = "UNC_R2_RING_AK_USED",
+    .code   = 0x8,
+    .desc   = "Counts the number of cycles that the AK ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_ring_ad_used),
+  },
+  { .name   = "UNC_R2_RING_BL_USED",
+    .code   = 0x9,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_ring_ad_used),
+  },
+  { .name   = "UNC_R2_RING_IV_USED",
+    .code   = 0xa,
+    .desc   = "Counts the number of cycles that the IV ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_ring_iv_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_ring_iv_used),
+  },
+  { .name   = "UNC_R2_RXR_CYCLES_NE",
+    .code   = 0x10,
+    .desc   = "Counts the number of cycles when the R2PCIe Ingress is not empty.  This tracks one of the three rings that are used by the R2PCIe agent.  This can be used in conjunction with the R2PCIe Ingress Occupancy Accumulator event in order to calculate average queue occupancy.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_rxr_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_rxr_cycles_ne),
+  },
+  { .name   = "UNC_R2_RXR_INSERTS",
+    .code   = 0x11,
+    .desc   = "Counts the number of allocations into the R2PCIe Ingress.  This tracks one of the three rings that are used by the R2PCIe agent.  This can be used in conjunction with the R2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_rxr_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_rxr_cycles_ne),
+  },
+  { .name   = "UNC_R2_RXR_OCCUPANCY",
+    .code   = 0x13,
+    .desc   = "Accumulates the occupancy of a given R2PCIe Ingress queue in each cycles.  This tracks one of the three ring Ingress buffers.  This can be used with the R2PCIe Ingress Not Empty event to calculate average occupancy or the R2PCIe Ingress Allocations event in order to calculate average queuing latency.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_rxr_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_rxr_occupancy),
+  },
+  { .name   = "UNC_R2_SBO0_CREDITS_ACQUIRED",
+    .code   = 0x28,
+    .desc   = "Number of Sbo 0 credits acquired in a given cycle, per ring.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_R2_STALL_NO_SBO_CREDIT",
+    .code   = 0x2c,
+    .desc   = "Number of cycles Egress is stalled waiting for an Sbo credit to become available.  Per Sbo, per Ring.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_stall_no_sbo_credit,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_stall_no_sbo_credit),
+  },
+  { .name   = "UNC_R2_TXR_CYCLES_FULL",
+    .code   = 0x25,
+    .desc   = "Counts the number of cycles when the R2PCIe Egress buffer is full.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_txr_cycles_full,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_txr_cycles_full),
+  },
+  { .name   = "UNC_R2_TXR_CYCLES_NE",
+    .code   = 0x23,
+    .desc   = "Counts the number of cycles when the R2PCIe Egress is not empty.  This tracks one of the three rings that are used by the R2PCIe agent.  This can be used in conjunction with the R2PCIe Egress Occupancy Accumulator event in order to calculate average queue occupancy.  Only a single Egress queue can be tracked at any given time.  It is not possible to filter based on direction or polarity.",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_txr_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_txr_cycles_ne),
+  },
+  { .name   = "UNC_R2_TXR_NACK_CW",
+    .code   = 0x26,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_R2PCIE_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r2_txr_nack_cw,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r2_txr_nack_cw),
+  },
+};
diff --git a/lib/events/intel_bdx_unc_r3qpi_events.h b/lib/events/intel_bdx_unc_r3qpi_events.h
new file mode 100644
index 0000000..5c0b561
--- /dev/null
+++ b/lib/events/intel_bdx_unc_r3qpi_events.h
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_r3qpi
+ */
+
+static intel_x86_umask_t bdx_unc_r3_c_hi_ad_credits_empty[]={
+	{ .uname = "CBO10",
+	  .ucode = 0x400,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO11",
+	  .ucode = 0x800,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO12",
+	  .ucode = 0x1000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO13",
+	  .ucode = 0x2000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO14_16",
+	  .ucode = 0x4000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO8",
+	  .ucode = 0x100,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO9",
+	  .ucode = 0x200,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO_15_17",
+	  .ucode = 0x8000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_c_lo_ad_credits_empty[]={
+	{ .uname = "CBO0",
+	  .ucode = 0x100,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO1",
+	  .ucode = 0x200,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO2",
+	  .ucode = 0x400,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO3",
+	  .ucode = 0x800,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO4",
+	  .ucode = 0x1000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO5",
+	  .ucode = 0x2000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO6",
+	  .ucode = 0x4000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+	{ .uname = "CBO7",
+	  .ucode = 0x8000,
+	  .udesc = "CBox AD Credits Empty",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_ha_r2_bl_credits_empty[]={
+	{ .uname = "HA0",
+	  .ucode = 0x100,
+	  .udesc = "HA/R2 AD Credits Empty",
+	},
+	{ .uname = "HA1",
+	  .ucode = 0x200,
+	  .udesc = "HA/R2 AD Credits Empty",
+	},
+	{ .uname = "R2_NCB",
+	  .ucode = 0x400,
+	  .udesc = "HA/R2 AD Credits Empty",
+	},
+	{ .uname = "R2_NCS",
+	  .ucode = 0x800,
+	  .udesc = "HA/R2 AD Credits Empty",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_qpi0_ad_credits_empty[]={
+	{ .uname = "VN0_HOM",
+	  .ucode = 0x200,
+	  .udesc = "VN0 HOM messages",
+	},
+	{ .uname = "VN0_NDR",
+	  .ucode = 0x800,
+	  .udesc = "VN0 NDR messages",
+	},
+	{ .uname = "VN0_SNP",
+	  .ucode = 0x400,
+	  .udesc = "VN0 SNP messages",
+	},
+	{ .uname = "VN1_HOM",
+	  .ucode = 0x1000,
+	  .udesc = "VN1 HOM messages",
+	},
+	{ .uname = "VN1_NDR",
+	  .ucode = 0x4000,
+	  .udesc = "VN1 NDR messages",
+	},
+	{ .uname = "VN1_SNP",
+	  .ucode = 0x2000,
+	  .udesc = "VN1 SNP messages",
+	},
+	{ .uname = "VNA",
+	  .ucode = 0x100,
+	  .udesc = "VNA messages",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_qpi0_bl_credits_empty[]={
+	{ .uname = "VN1_HOM",
+	  .ucode = 0x1000,
+	  .udesc = "QPIx BL Credits Empty",
+	},
+	{ .uname = "VN1_NDR",
+	  .ucode = 0x4000,
+	  .udesc = "QPIx BL Credits Empty",
+	},
+	{ .uname = "VN1_SNP",
+	  .ucode = 0x2000,
+	  .udesc = "QPIx BL Credits Empty",
+	},
+	{ .uname = "VNA",
+	  .ucode = 0x100,
+	  .udesc = "QPIx BL Credits Empty",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_ring_ad_used[]={
+	{ .uname  = "CCW",
+	  .ucode  = 0xc00,
+	  .udesc  = "Counterclockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CCW_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "Counterclockwise and Even",
+	},
+	{ .uname = "CCW_ODD",
+	  .ucode = 0x800,
+	  .udesc = "Counterclockwise and Odd",
+	},
+	{ .uname  = "CW",
+	  .ucode  = 0x300,
+	  .udesc  = "Clockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+	{ .uname = "CW_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "Clockwise and Even",
+	},
+	{ .uname = "CW_ODD",
+	  .ucode = 0x200,
+	  .udesc = "Clockwise and Odd",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_ring_iv_used[]={
+	{ .uname  = "ANY",
+	  .ucode  = 0xf00,
+	  .udesc  = "Any",
+	  .uflags = INTEL_X86_NCOMBO | INTEL_X86_DFL,
+	},
+	{ .uname  = "CW",
+	  .ucode  = 0x300,
+	  .udesc  = "Clockwise",
+	  .uflags = INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_ring_sink_starved[]={
+	{ .uname  = "AK",
+	  .ucode  = 0x200,
+	  .udesc  = "AK",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_rxr_cycles_ne[]={
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Cycles Not Empty -- HOM",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Cycles Not Empty -- NDR",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Cycles Not Empty -- SNP",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_rxr_cycles_ne_vn1[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- DRS",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- HOM",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- NCB",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- NCS",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- NDR",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VN1 Ingress Cycles Not Empty -- SNP",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_rxr_inserts[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "Ingress Allocations -- DRS",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Allocations -- HOM",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "Ingress Allocations -- NCB",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Allocations -- NCS",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Allocations -- NDR",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Allocations -- SNP",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_sbo0_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "SBo0 Credits Acquired -- For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "SBo0 Credits Acquired -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_sbo1_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "SBo1 Credits Acquired -- For AD Ring",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x200,
+	  .udesc = "SBo1 Credits Acquired -- For BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_stall_no_sbo_credit[]={
+	{ .uname = "SBO0_AD",
+	  .ucode = 0x100,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, AD Ring",
+	},
+	{ .uname = "SBO0_BL",
+	  .ucode = 0x400,
+	  .udesc = "Stall on No Sbo Credits -- For SBo0, BL Ring",
+	},
+	{ .uname = "SBO1_AD",
+	  .ucode = 0x200,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, AD Ring",
+	},
+	{ .uname = "SBO1_BL",
+	  .ucode = 0x800,
+	  .udesc = "Stall on No Sbo Credits -- For SBo1, BL Ring",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_txr_nack[]={
+	{ .uname = "DN_AD",
+	  .ucode = 0x100,
+	  .udesc = "Egress CCW NACK -- AD CCW",
+	},
+	{ .uname = "DN_AK",
+	  .ucode = 0x400,
+	  .udesc = "Egress CCW NACK -- AK CCW",
+	},
+	{ .uname = "DN_BL",
+	  .ucode = 0x200,
+	  .udesc = "Egress CCW NACK -- BL CCW",
+	},
+	{ .uname = "UP_AD",
+	  .ucode = 0x800,
+	  .udesc = "Egress CCW NACK -- AK CCW",
+	},
+	{ .uname = "UP_AK",
+	  .ucode = 0x2000,
+	  .udesc = "Egress CCW NACK -- BL CW",
+	},
+	{ .uname = "UP_BL",
+	  .ucode = 0x1000,
+	  .udesc = "Egress CCW NACK -- BL CCW",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vn0_credits_reject[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- DRS Message Class",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- HOM Message Class",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- NCB Message Class",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- NCS Message Class",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- NDR Message Class",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VN0 Credit Acquisition Failed on DRS -- SNP Message Class",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vn0_credits_used[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VN0 Credit Used -- DRS Message Class",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VN0 Credit Used -- HOM Message Class",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VN0 Credit Used -- NCB Message Class",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VN0 Credit Used -- NCS Message Class",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VN0 Credit Used -- NDR Message Class",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VN0 Credit Used -- SNP Message Class",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vn1_credits_reject[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- DRS Message Class",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- HOM Message Class",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- NCB Message Class",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- NCS Message Class",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- NDR Message Class",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VN1 Credit Acquisition Failed on DRS -- SNP Message Class",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vn1_credits_used[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VN1 Credit Used -- DRS Message Class",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VN1 Credit Used -- HOM Message Class",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VN1 Credit Used -- NCB Message Class",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VN1 Credit Used -- NCS Message Class",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VN1 Credit Used -- NDR Message Class",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VN1 Credit Used -- SNP Message Class",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vna_credits_acquired[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "VNA credit Acquisitions -- HOM Message Class",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "VNA credit Acquisitions -- HOM Message Class",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_r3_vna_credits_reject[]={
+	{ .uname = "DRS",
+	  .ucode = 0x800,
+	  .udesc = "VNA Credit Reject -- DRS Message Class",
+	},
+	{ .uname = "HOM",
+	  .ucode = 0x100,
+	  .udesc = "VNA Credit Reject -- HOM Message Class",
+	},
+	{ .uname = "NCB",
+	  .ucode = 0x1000,
+	  .udesc = "VNA Credit Reject -- NCB Message Class",
+	},
+	{ .uname = "NCS",
+	  .ucode = 0x2000,
+	  .udesc = "VNA Credit Reject -- NCS Message Class",
+	},
+	{ .uname = "NDR",
+	  .ucode = 0x400,
+	  .udesc = "VNA Credit Reject -- NDR Message Class",
+	},
+	{ .uname = "SNP",
+	  .ucode = 0x200,
+	  .udesc = "VNA Credit Reject -- SNP Message Class",
+	},
+};
+
+
+static intel_x86_entry_t intel_bdx_unc_r3_pe[]={
+  { .name   = "UNC_R3_CLOCKTICKS",
+    .code   = 0x1,
+    .desc   = "Counts the number of uclks in the QPI uclk domain.  This could be slightly different than the count in the Ubox because of enable/freeze delays.  However, because the QPI Agent is close to the Ubox, they generally should not diverge by more than a handful of cycles.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+  },
+  { .name   = "UNC_R3_C_HI_AD_CREDITS_EMPTY",
+    .code   = 0x1f,
+    .desc   = "No credits available to send to Cbox on the AD Ring (covers higher CBoxes)",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_c_hi_ad_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_c_hi_ad_credits_empty),
+  },
+  { .name   = "UNC_R3_C_LO_AD_CREDITS_EMPTY",
+    .code   = 0x22,
+    .desc   = "No credits available to send to Cbox on the AD Ring (covers lower CBoxes)",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_c_lo_ad_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_c_lo_ad_credits_empty),
+  },
+  { .name   = "UNC_R3_HA_R2_BL_CREDITS_EMPTY",
+    .code   = 0x2d,
+    .desc   = "No credits available to send to either HA or R2 on the BL Ring",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ha_r2_bl_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ha_r2_bl_credits_empty),
+  },
+  { .name   = "UNC_R3_QPI0_AD_CREDITS_EMPTY",
+    .code   = 0x20,
+    .desc   = "No credits available to send to QPI0 on the AD Ring",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_qpi0_ad_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_qpi0_ad_credits_empty),
+  },
+  { .name   = "UNC_R3_QPI0_BL_CREDITS_EMPTY",
+    .code   = 0x21,
+    .desc   = "No credits available to send to QPI0 on the BL Ring",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_qpi0_bl_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_qpi0_bl_credits_empty),
+  },
+  { .name   = "UNC_R3_QPI1_AD_CREDITS_EMPTY",
+    .code   = 0x2e,
+    .desc   = "No credits available to send to QPI1 on the AD Ring",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_qpi0_ad_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_qpi0_ad_credits_empty),
+  },
+  { .name   = "UNC_R3_QPI1_BL_CREDITS_EMPTY",
+    .code   = 0x2f,
+    .desc   = "No credits available to send to QPI1 on the BL Ring",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_qpi0_ad_credits_empty,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_qpi0_ad_credits_empty),
+  },
+  { .name   = "UNC_R3_RING_AD_USED",
+    .code   = 0x7,
+    .desc   = "Counts the number of cycles that the AD ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ring_ad_used),
+  },
+  { .name   = "UNC_R3_RING_AK_USED",
+    .code   = 0x8,
+    .desc   = "Counts the number of cycles that the AK ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ring_ad_used),
+  },
+  { .name   = "UNC_R3_RING_BL_USED",
+    .code   = 0x9,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sunk, but does not include when packets are being sent from the ring stop.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ring_ad_used),
+  },
+  { .name   = "UNC_R3_RING_IV_USED",
+    .code   = 0xa,
+    .desc   = "Counts the number of cycles that the IV ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ring_iv_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ring_iv_used),
+  },
+  { .name   = "UNC_R3_RING_SINK_STARVED",
+    .code   = 0xe,
+    .desc   = "Number of cycles the ringstop is in starvation (per ring)",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x7,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_ring_sink_starved,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_ring_sink_starved),
+  },
+  { .name   = "UNC_R3_RXR_CYCLES_NE",
+    .code   = 0x10,
+    .desc   = "Counts the number of cycles when the QPI Ingress is not empty.  This tracks one of the three rings that are used by the QPI agent.  This can be used in conjunction with the QPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_rxr_cycles_ne,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_rxr_cycles_ne),
+  },
+  { .name   = "UNC_R3_RXR_CYCLES_NE_VN1",
+    .code   = 0x14,
+    .desc   = "Counts the number of cycles when the QPI VN1  Ingress is not empty.  This tracks one of the three rings that are used by the QPI agent.  This can be used in conjunction with the QPI VN1  Ingress Occupancy Accumulator event in order to calculate average queue occupancy.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_rxr_cycles_ne_vn1,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_rxr_cycles_ne_vn1),
+  },
+  { .name   = "UNC_R3_RXR_INSERTS",
+    .code   = 0x11,
+    .desc   = "Counts the number of allocations into the QPI Ingress.  This tracks one of the three rings that are used by the QPI agent.  This can be used in conjunction with the QPI Ingress Occupancy Accumulator event in order to calculate average queue latency.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_rxr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_rxr_inserts),
+  },
+  { .name   = "UNC_R3_RXR_INSERTS_VN1",
+    .code   = 0x15,
+    .desc   = "Counts the number of allocations into the QPI VN1  Ingress.  This tracks one of the three rings that are used by the QPI agent.  This can be used in conjunction with the QPI VN1  Ingress Occupancy Accumulator event in order to calculate average queue latency.  Multiple ingress buffers can be tracked at a given time using multiple counters.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_rxr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_rxr_inserts),
+  },
+  { .name   = "UNC_R3_RXR_OCCUPANCY_VN1",
+    .code   = 0x13,
+    .desc   = "Accumulates the occupancy of a given QPI VN1  Ingress queue in each cycles.  This tracks one of the three ring Ingress buffers.  This can be used with the QPI VN1  Ingress Not Empty event to calculate average occupancy or the QPI VN1  Ingress Allocations event in order to calculate average queuing latency.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x1,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_rxr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_rxr_inserts),
+  },
+  { .name   = "UNC_R3_SBO0_CREDITS_ACQUIRED",
+    .code   = 0x28,
+    .desc   = "Number of Sbo 0 credits acquired in a given cycle, per ring.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_sbo0_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_sbo0_credits_acquired),
+  },
+  { .name   = "UNC_R3_SBO1_CREDITS_ACQUIRED",
+    .code   = 0x29,
+    .desc   = "Number of Sbo 1 credits acquired in a given cycle, per ring.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_sbo1_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_sbo1_credits_acquired),
+  },
+  { .name   = "UNC_R3_STALL_NO_SBO_CREDIT",
+    .code   = 0x2c,
+    .desc   = "Number of cycles Egress is stalled waiting for an Sbo credit to become available.  Per Sbo, per Ring.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_stall_no_sbo_credit,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_stall_no_sbo_credit),
+  },
+  { .name   = "UNC_R3_TXR_NACK",
+    .code   = 0x26,
+    .desc   = "",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_txr_nack,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_txr_nack),
+  },
+  { .name   = "UNC_R3_VN0_CREDITS_REJECT",
+    .code   = 0x37,
+    .desc   = "Number of times a request failed to acquire a DRS VN0 credit.  In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into.  There are two credit pools, VNA and VN0.  VNA is a shared pool used to achieve high performance.  The VN0 pool has reserved entries for each message class and is used to prevent deadlock.  Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail.  This therefore counts the number of times when a request failed to acquire either a VNA or VN0 credit and is delayed.  This should generally be a rare situation.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vn0_credits_reject,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vn0_credits_reject),
+  },
+  { .name   = "UNC_R3_VN0_CREDITS_USED",
+    .code   = 0x36,
+    .desc   = "Number of times a VN0 credit was used on the DRS message channel.  In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into.  There are two credit pools, VNA and VN0.  VNA is a shared pool used to achieve high performance.  The VN0 pool has reserved entries for each message class and is used to prevent deadlock.  Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail.  This counts the number of times a VN0 credit was used.  Note that a single VN0 credit holds access to potentially multiple flit buffers.  For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits.  A transfer on VN0 will only count a single credit even though it may use multiple buffers.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vn0_credits_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vn0_credits_used),
+  },
+  { .name   = "UNC_R3_VN1_CREDITS_REJECT",
+    .code   = 0x39,
+    .desc   = "Number of times a request failed to acquire a VN1 credit.  In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into.  There are two credit pools, VNA and VN1.  VNA is a shared pool used to achieve high performance.  The VN1 pool has reserved entries for each message class and is used to prevent deadlock.  Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail.  This therefore counts the number of times when a request failed to acquire either a VNA or VN1 credit and is delayed.  This should generally be a rare situation.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vn1_credits_reject,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vn1_credits_reject),
+  },
+  { .name   = "UNC_R3_VN1_CREDITS_USED",
+    .code   = 0x38,
+    .desc   = "Number of times a VN1 credit was used on the DRS message channel.  In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into.  There are two credit pools, VNA and VN1.  VNA is a shared pool used to achieve high performance.  The VN1 pool has reserved entries for each message class and is used to prevent deadlock.  Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail.  This counts the number of times a VN1 credit was used.  Note that a single VN1 credit holds access to potentially multiple flit buffers.  For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits.  A transfer on VN1 will only count a single credit even though it may use multiple buffers.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vn1_credits_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vn1_credits_used),
+  },
+  { .name   = "UNC_R3_VNA_CREDITS_ACQUIRED",
+    .code   = 0x33,
+    .desc   = "Number of QPI VNA Credit acquisitions.  This event can be used in conjunction with the VNA In-Use Accumulator to calculate the average lifetime of a credit holder.  VNA credits are used by all message classes in order to communicate across QPI.  If a packet is unable to acquire credits, it will then attempt to use credts from the VN0 pool.  Note that a single packet may require multiple flit buffers (i.e. when data is being transfered).  Therefore, this event will increment by the number of credits acquired in each cycle.  Filtering based on message class is not provided.  One can count the number of packets transfered in a given message class using an qfclk event.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vna_credits_acquired,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vna_credits_acquired),
+  },
+  { .name   = "UNC_R3_VNA_CREDITS_REJECT",
+    .code   = 0x34,
+    .desc   = "Number of attempted VNA credit acquisitions that were rejected because the VNA credit pool was full (or almost full).  It is possible to filter this event by message class.  Some packets use more than one flit buffer, and therefore must acquire multiple credits.  Therefore, one could get a reject even if the VNA credits were not fully used up.  The VNA pool is generally used to provide the bulk of the QPI bandwidth (as opposed to the VN0 pool which is used to guarantee forward progress).  VNA credits can run out if the flit buffer on the receiving side starts to queue up substantially.  This can happen if the rest of the uncore is unable to drain the requests fast enough.",
+    .modmsk = BDX_UNC_R3QPI_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_r3_vna_credits_reject,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_r3_vna_credits_reject),
+  },
+};
+
diff --git a/lib/events/intel_bdx_unc_sbo_events.h b/lib/events/intel_bdx_unc_sbo_events.h
new file mode 100644
index 0000000..2f35d95
--- /dev/null
+++ b/lib/events/intel_bdx_unc_sbo_events.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_sbo
+ */
+
+static intel_x86_umask_t bdx_unc_s_ring_ad_used[]={
+	{ .uname = "DOWN_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "Down and Event",
+	},
+	{ .uname = "DOWN_ODD",
+	  .ucode = 0x800,
+	  .udesc = "Down and Odd",
+	},
+	{ .uname = "UP_EVEN",
+	  .ucode = 0x100,
+	  .udesc = "Up and Even",
+	},
+	{ .uname = "UP_ODD",
+	  .ucode = 0x200,
+	  .udesc = "Up and Odd",
+	},
+	{ .uname = "UP",
+	  .ucode = 0x300,
+	  .udesc = "Up",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "DOWN",
+	  .ucode = 0xcc00,
+	  .udesc = "Down",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_ring_bounces[]={
+	{ .uname = "AD_CACHE",
+	  .ucode = 0x100,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- ",
+	},
+	{ .uname = "AK_CORE",
+	  .ucode = 0x200,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- Acknowledgements to core",
+	},
+	{ .uname = "BL_CORE",
+	  .ucode = 0x400,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- Data Responses to core",
+	},
+	{ .uname = "IV_CORE",
+	  .ucode = 0x800,
+	  .udesc = "Number of LLC responses that bounced on the Ring. -- Snoops of processors cachee.",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_ring_iv_used[]={
+	{ .uname = "DN",
+	  .ucode = 0xc00,
+	  .udesc = "BL Ring in Use -- Any",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "UP",
+	  .ucode = 0x300,
+	  .udesc = "BL Ring in Use -- Any",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_rxr_bypass[]={
+	{ .uname = "AD_BNC",
+	  .ucode = 0x200,
+	  .udesc = "Bypass -- AD - Bounces",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "AD_CRD",
+	  .ucode = 0x100,
+	  .udesc = "Bypass -- AD - Credits",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "AK",
+	  .ucode = 0x1000,
+	  .udesc = "Bypass -- AK",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "BL_BNC",
+	  .ucode = 0x800,
+	  .udesc = "Bypass -- BL - Bounces",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "BL_CRD",
+	  .ucode = 0x400,
+	  .udesc = "Bypass -- BL - Credits",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "IV",
+	  .ucode = 0x2000,
+	  .udesc = "Bypass -- IV",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_rxr_inserts[]={
+	{ .uname = "AD_BNC",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Allocations -- AD - Bounces",
+	},
+	{ .uname = "AD_CRD",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Allocations -- AD - Credits",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x1000,
+	  .udesc = "Ingress Allocations -- AK",
+	},
+	{ .uname = "BL_BNC",
+	  .ucode = 0x800,
+	  .udesc = "Ingress Allocations -- BL - Bounces",
+	},
+	{ .uname = "BL_CRD",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Allocations -- BL - Credits",
+	},
+	{ .uname = "IV",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Allocations -- IV",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_rxr_occupancy[]={
+	{ .uname = "AD_BNC",
+	  .ucode = 0x200,
+	  .udesc = "Ingress Occupancy -- AD - Bounces",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "AD_CRD",
+	  .ucode = 0x100,
+	  .udesc = "Ingress Occupancy -- AD - Credits",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "AK",
+	  .ucode = 0x1000,
+	  .udesc = "Ingress Occupancy -- AK",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "BL_BNC",
+	  .ucode = 0x800,
+	  .udesc = "Ingress Occupancy -- BL - Bounces",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "BL_CRD",
+	  .ucode = 0x400,
+	  .udesc = "Ingress Occupancy -- BL - Credits",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+	{ .uname = "IV",
+	  .ucode = 0x2000,
+	  .udesc = "Ingress Occupancy -- IV",
+	  .uflags= INTEL_X86_NCOMBO,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_txr_ads_used[]={
+	{ .uname = "AD",
+	  .ucode = 0x100,
+	  .udesc = "TBD",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x200,
+	  .udesc = "TBD",
+	},
+	{ .uname = "BL",
+	  .ucode = 0x400,
+	  .udesc = "TBD",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_txr_inserts[]={
+	{ .uname = "AD_BNC",
+	  .ucode = 0x200,
+	  .udesc = "Egress Allocations -- AD - Bounces",
+	},
+	{ .uname = "AD_CRD",
+	  .ucode = 0x100,
+	  .udesc = "Egress Allocations -- AD - Credits",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x1000,
+	  .udesc = "Egress Allocations -- AK",
+	},
+	{ .uname = "BL_BNC",
+	  .ucode = 0x800,
+	  .udesc = "Egress Allocations -- BL - Bounces",
+	},
+	{ .uname = "BL_CRD",
+	  .ucode = 0x400,
+	  .udesc = "Egress Allocations -- BL - Credits",
+	},
+	{ .uname = "IV",
+	  .ucode = 0x2000,
+	  .udesc = "Egress Allocations -- IV",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_txr_occupancy[]={
+	{ .uname = "AD_BNC",
+	  .ucode = 0x200,
+	  .udesc = "Egress Occupancy -- AD - Bounces",
+	},
+	{ .uname = "AD_CRD",
+	  .ucode = 0x100,
+	  .udesc = "Egress Occupancy -- AD - Credits",
+	},
+	{ .uname = "AK",
+	  .ucode = 0x1000,
+	  .udesc = "Egress Occupancy -- AK",
+	},
+	{ .uname = "BL_BNC",
+	  .ucode = 0x800,
+	  .udesc = "Egress Occupancy -- BL - Bounces",
+	},
+	{ .uname = "BL_CRD",
+	  .ucode = 0x400,
+	  .udesc = "Egress Occupancy -- BL - Credits",
+	},
+	{ .uname = "IV",
+	  .ucode = 0x2000,
+	  .udesc = "Egress Occupancy -- IV",
+	},
+};
+
+static intel_x86_umask_t bdx_unc_s_txr_ordering[]={
+	{ .uname = "IVSNOOPGO_UP",
+	  .ucode = 0x100,
+	  .udesc = "TBD",
+	},
+	{ .uname = "IVSNOOP_DN",
+	  .ucode = 0x200,
+	  .udesc = "TBD",
+	},
+	{ .uname = "AK_U2C_UP_EVEN",
+	  .ucode = 0x400,
+	  .udesc = "TBD",
+	},
+	{ .uname = "AK_U2C_UP_ODD",
+	  .ucode = 0x800,
+	  .udesc = "TBD",
+	},
+	{ .uname = "AK_U2C_DN_EVEN",
+	  .ucode = 0x1000,
+	  .udesc = "TBD",
+	},
+	{ .uname = "AK_U2C_DN_ODD",
+	  .ucode = 0x2000,
+	  .udesc = "TBD",
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_s_pe[]={
+  { .name   = "UNC_S_BOUNCE_CONTROL",
+    .code   = 0xa,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_S_CLOCKTICKS",
+    .code   = 0x0,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_S_FAST_ASSERTED",
+    .code   = 0x9,
+    .desc   = "Counts the number of cycles either the local or incoming distress signals are asserted.  Incoming distress includes up, dn and across.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+  },
+  { .name   = "UNC_S_RING_AD_USED",
+    .code   = 0x1b,
+    .desc   = "Counts the number of cycles that the AD ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop.  We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_ring_ad_used),
+  },
+  { .name   = "UNC_S_RING_AK_USED",
+    .code   = 0x1c,
+    .desc   = "Counts the number of cycles that the AK ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop. We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_ring_ad_used),
+  },
+  { .name   = "UNC_S_RING_BL_USED",
+    .code   = 0x1d,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop. We really have two rings in BDX -- a clockwise ring and a counter-clockwise ring.  On the left side of the ring, the UP direction is on the clockwise ring and DN is on the counter-clockwise ring.  On the right side of the ring, this is reversed.  The first half of the CBos are on the left side of the ring, and the 2nd half are on the right side of the ring.  In other words (for example), in a 4c part, Cbo 0 UP AD is NOT the same ring as CBo 2 UP AD because they are on opposite sides of the rhe ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_ring_ad_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_ring_ad_used),
+  },
+  { .name   = "UNC_S_RING_BOUNCES",
+    .code   = 0x5,
+    .desc   = "TBD",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_ring_bounces,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_ring_bounces),
+  },
+  { .name   = "UNC_S_RING_IV_USED",
+    .code   = 0x1e,
+    .desc   = "Counts the number of cycles that the BL ring is being used at this ring stop.  This includes when packets are passing by and when packets are being sent, but does not include when packets are being sunk into the ring stop.  There is only 1 IV ring in BDX.  Therefore, if one wants to monitor the Even ring, they should select both UP_EVEN and DN_EVEN.  To monitor the Odd ring, they should select both UP_ODD and DN_ DN_ODD.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_ring_iv_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_ring_iv_used),
+  },
+  { .name   = "UNC_S_RXR_BYPASS",
+    .code   = 0x12,
+    .desc   = "Bypass the Sbo Ingress.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_rxr_bypass,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_rxr_bypass),
+  },
+  { .name   = "UNC_S_RXR_INSERTS",
+    .code   = 0x13,
+    .desc   = "Number of allocations into the Sbo Ingress  The Ingress is used to queue up requests received from the ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_rxr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_rxr_inserts),
+  },
+  { .name   = "UNC_S_RXR_OCCUPANCY",
+    .code   = 0x11,
+    .desc   = "Occupancy event for the Ingress buffers in the Sbo.  The Ingress is used to queue up requests received from the ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_rxr_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_rxr_occupancy),
+  },
+  { .name   = "UNC_S_TXR_ADS_USED",
+    .code   = 0x4,
+    .desc   = "",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_txr_ads_used,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_txr_ads_used),
+  },
+  { .name   = "UNC_S_TXR_INSERTS",
+    .code   = 0x2,
+    .desc   = "Number of allocations into the Sbo Egress.  The Egress is used to queue up requests destined for the ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_txr_inserts,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_txr_inserts),
+  },
+  { .name   = "UNC_S_TXR_OCCUPANCY",
+    .code   = 0x1,
+    .desc   = "Occupancy event for the Egress buffers in the Sbo.  The egress is used to queue up requests destined for the ring.",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_txr_occupancy,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_txr_occupancy),
+  },
+  { .name   = "UNC_S_TXR_ORDERING",
+    .code   = 0x7,
+    .desc   = "TB",
+    .modmsk = BDX_UNC_SBO_ATTRS,
+    .cntmsk = 0xf,
+    .ngrp   = 1,
+    .umasks = bdx_unc_s_txr_ordering,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_s_txr_ordering),
+  },
+};
diff --git a/lib/events/intel_bdx_unc_ubo_events.h b/lib/events/intel_bdx_unc_ubo_events.h
new file mode 100644
index 0000000..2f4e1f3
--- /dev/null
+++ b/lib/events/intel_bdx_unc_ubo_events.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of libpfm, a performance monitoring support library for
+ * applications on Linux.
+ *
+ * PMU: bdx_unc_ubo
+ */
+
+static intel_x86_umask_t bdx_unc_u_event_msg[]={
+	{ .uname  = "DOORBELL_RCVD",
+	  .ucode  = 0x800,
+	  .udesc  = "VLW Received",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_umask_t bdx_unc_u_phold_cycles[]={
+	{ .uname  = "ASSERT_TO_ACK",
+	  .ucode  = 0x100,
+	  .udesc  = "Cycles PHOLD Assert to Ack. Assert to ACK",
+	  .uflags = INTEL_X86_DFL,
+	},
+};
+
+static intel_x86_entry_t intel_bdx_unc_u_pe[]={
+  { .name   = "UNC_U_EVENT_MSG",
+    .code   = 0x42,
+    .desc   = "Virtual Logical Wire (legacy) message were received from uncore",
+    .modmsk = BDX_UNC_UBO_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_u_event_msg,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_u_event_msg),
+  },
+  { .name   = "UNC_U_PHOLD_CYCLES",
+    .code   = 0x45,
+    .desc   = "PHOLD cycles.  Filter from source CoreID.",
+    .modmsk = BDX_UNC_UBO_ATTRS,
+    .cntmsk = 0x3,
+    .ngrp   = 1,
+    .umasks = bdx_unc_u_phold_cycles,
+    .numasks= LIBPFM_ARRAY_SIZE(bdx_unc_u_phold_cycles),
+  },
+  { .name   = "UNC_U_RACU_REQUESTS",
+    .code   = 0x46,
+    .desc   = "Number outstanding register requests within message channel tracker",
+    .modmsk = BDX_UNC_UBO_ATTRS,
+    .cntmsk = 0x3,
+  },
+};
+
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index bd57078..844667d 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -266,6 +266,54 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
 	&intel_knl_unc_cha36_support,
 	&intel_knl_unc_cha37_support,
 	&intel_knl_unc_m2pcie_support,
+	&intel_bdx_unc_cb0_support,
+	&intel_bdx_unc_cb1_support,
+	&intel_bdx_unc_cb2_support,
+	&intel_bdx_unc_cb3_support,
+	&intel_bdx_unc_cb4_support,
+	&intel_bdx_unc_cb5_support,
+	&intel_bdx_unc_cb6_support,
+	&intel_bdx_unc_cb7_support,
+	&intel_bdx_unc_cb8_support,
+	&intel_bdx_unc_cb9_support,
+	&intel_bdx_unc_cb10_support,
+	&intel_bdx_unc_cb11_support,
+	&intel_bdx_unc_cb12_support,
+	&intel_bdx_unc_cb13_support,
+	&intel_bdx_unc_cb14_support,
+	&intel_bdx_unc_cb15_support,
+	&intel_bdx_unc_cb16_support,
+	&intel_bdx_unc_cb17_support,
+	&intel_bdx_unc_cb18_support,
+	&intel_bdx_unc_cb19_support,
+	&intel_bdx_unc_cb20_support,
+	&intel_bdx_unc_cb21_support,
+	&intel_bdx_unc_cb22_support,
+	&intel_bdx_unc_cb23_support,
+	&intel_bdx_unc_ubo_support,
+	&intel_bdx_unc_sbo0_support,
+	&intel_bdx_unc_sbo1_support,
+	&intel_bdx_unc_sbo2_support,
+	&intel_bdx_unc_sbo3_support,
+	&intel_bdx_unc_ha0_support,
+	&intel_bdx_unc_ha1_support,
+	&intel_bdx_unc_imc0_support,
+	&intel_bdx_unc_imc1_support,
+	&intel_bdx_unc_imc2_support,
+	&intel_bdx_unc_imc3_support,
+	&intel_bdx_unc_imc4_support,
+	&intel_bdx_unc_imc5_support,
+	&intel_bdx_unc_imc6_support,
+	&intel_bdx_unc_imc7_support,
+	&intel_bdx_unc_irp_support,
+	&intel_bdx_unc_pcu_support,
+	&intel_bdx_unc_qpi0_support,
+	&intel_bdx_unc_qpi1_support,
+	&intel_bdx_unc_qpi2_support,
+	&intel_bdx_unc_r2pcie_support,
+	&intel_bdx_unc_r3qpi0_support,
+	&intel_bdx_unc_r3qpi1_support,
+	&intel_bdx_unc_r3qpi2_support,
 	&intel_x86_arch_support, /* must always be last for x86 */
 #endif
 
diff --git a/lib/pfmlib_intel_bdx_unc_cbo.c b/lib/pfmlib_intel_bdx_unc_cbo.c
new file mode 100644
index 0000000..d1ff970
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_cbo.c
@@ -0,0 +1,134 @@
+/*
+ * pfmlib_intel_bdx_unc_cbo.c : Intel BDX C-Box uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc.
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_cbo_events.h"
+
+static void
+display_cbo(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+	pfm_snbep_unc_reg_t f;
+
+	__pfm_vbprintf("[UNC_CBO=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d tid_en=%d] %s\n",
+			reg->val,
+			reg->cbo.unc_event,
+			reg->cbo.unc_umask,
+			reg->cbo.unc_en,
+			reg->cbo.unc_inv,
+			reg->cbo.unc_edge,
+			reg->cbo.unc_thres,
+			reg->cbo.unc_tid,
+			pe[e->event].name);
+
+	if (e->count == 1)
+		return;
+
+	f.val = e->codes[1];
+
+	__pfm_vbprintf("[UNC_CBOX_FILTER0=0x%"PRIx64" tid=%d core=0x%x"
+		       " state=0x%x]\n",
+			f.val,
+			f.ivbep_cbo_filt0.tid,
+			f.ivbep_cbo_filt0.cid,
+			f.ivbep_cbo_filt0.state);
+
+	if (e->count == 2)
+		return;
+
+	f.val = e->codes[2];
+
+	__pfm_vbprintf("[UNC_CBOX_FILTER1=0x%"PRIx64" nid=%d opc=0x%x"
+		       " nc=0x%x isoc=0x%x]\n",
+			f.val,
+			f.ivbep_cbo_filt1.nid,
+			f.ivbep_cbo_filt1.opc,
+			f.ivbep_cbo_filt1.nc,
+			f.ivbep_cbo_filt1.isoc);
+}
+
+#define DEFINE_C_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_cb##n##_support = {\
+	.desc			= "Intel BroadwellX C-Box "#n" uncore",\
+	.name			= "bdx_unc_cbo"#n,\
+	.perf_name		= "uncore_cbox_"#n,\
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_CB##n,\
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_c_pe),\
+	.type			= PFM_PMU_TYPE_UNCORE,\
+	.num_cntrs		= 4,\
+	.num_fixed_cntrs	= 0,\
+	.max_encoding		= 2,\
+	.pe			= intel_bdx_unc_c_pe,\
+	.atdesc			= snbep_unc_mods,\
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK|INTEL_PMU_FL_UNC_CBO,\
+	.pmu_detect		= pfm_intel_bdx_unc_detect,\
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,\
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),\
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first,\
+	.get_event_next		= pfm_intel_x86_get_event_next,\
+	.event_is_valid		= pfm_intel_x86_event_is_valid,\
+	.validate_table		= pfm_intel_x86_validate_table,\
+	.get_event_info		= pfm_intel_x86_get_event_info,\
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,\
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),\
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,\
+	.can_auto_encode	= pfm_intel_x86_can_auto_encode, \
+	.display_reg		= display_cbo,\
+}
+
+DEFINE_C_BOX(0);
+DEFINE_C_BOX(1);
+DEFINE_C_BOX(2);
+DEFINE_C_BOX(3);
+DEFINE_C_BOX(4);
+DEFINE_C_BOX(5);
+DEFINE_C_BOX(6);
+DEFINE_C_BOX(7);
+DEFINE_C_BOX(8);
+DEFINE_C_BOX(9);
+DEFINE_C_BOX(10);
+DEFINE_C_BOX(11);
+DEFINE_C_BOX(12);
+DEFINE_C_BOX(13);
+DEFINE_C_BOX(14);
+DEFINE_C_BOX(15);
+DEFINE_C_BOX(16);
+DEFINE_C_BOX(17);
+DEFINE_C_BOX(18);
+DEFINE_C_BOX(19);
+DEFINE_C_BOX(20);
+DEFINE_C_BOX(21);
+DEFINE_C_BOX(22);
+DEFINE_C_BOX(23);
diff --git a/lib/pfmlib_intel_bdx_unc_ha.c b/lib/pfmlib_intel_bdx_unc_ha.c
new file mode 100644
index 0000000..d928ba0
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_ha.c
@@ -0,0 +1,97 @@
+/*
+ * pfmlib_intel_bdx_unc_ha.c : Intel BroadwellX Home Agent (HA) uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_ha_events.h"
+
+static void
+display_ha(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+	pfm_snbep_unc_reg_t f;
+
+	__pfm_vbprintf("[UNC_HA=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->com.unc_event,
+			reg->com.unc_umask,
+			reg->com.unc_en,
+			reg->com.unc_inv,
+			reg->com.unc_edge,
+			reg->com.unc_thres,
+			pe[e->event].name);
+
+	if (e->count == 1)
+		return;
+
+	f.val = e->codes[1];
+	__pfm_vbprintf("[UNC_HA_ADDR=0x%"PRIx64" lo_addr=0x%x hi_addr=0x%x]\n",
+			f.val,
+			f.ha_addr.lo_addr,
+			f.ha_addr.hi_addr);
+
+	f.val = e->codes[2];
+	__pfm_vbprintf("[UNC_HA_OPC=0x%"PRIx64" opc=0x%x]\n", f.val, f.ha_opc.opc);
+}
+
+#define DEFINE_HA_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_ha##n##_support = {\
+	.desc			= "Intel BroadwellX HA "#n" uncore",\
+	.name			= "bdx_unc_ha"#n,\
+	.perf_name		= "uncore_ha_"#n,\
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_HA##n,\
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_h_pe),\
+	.type			= PFM_PMU_TYPE_UNCORE,\
+	.num_cntrs		= 4,\
+	.num_fixed_cntrs	= 0,\
+	.max_encoding		= 3, /* address matchers */\
+	.pe			= intel_bdx_unc_h_pe,\
+	.atdesc			= snbep_unc_mods,\
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,\
+	.pmu_detect		= pfm_intel_bdx_unc_detect,\
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,\
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),\
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first,\
+	.get_event_next		= pfm_intel_x86_get_event_next,\
+	.event_is_valid		= pfm_intel_x86_event_is_valid,\
+	.validate_table		= pfm_intel_x86_validate_table,\
+	.get_event_info		= pfm_intel_x86_get_event_info,\
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,\
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),\
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,\
+	.display_reg		= display_ha,\
+}
+
+DEFINE_HA_BOX(0);
+DEFINE_HA_BOX(1);
diff --git a/lib/pfmlib_intel_bdx_unc_imc.c b/lib/pfmlib_intel_bdx_unc_imc.c
new file mode 100644
index 0000000..462f547
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_imc.c
@@ -0,0 +1,71 @@
+/*
+ * pfmlib_intel_bdx_unc_imc.c : Intel BroadwellX Integrated Memory Controller (IMC) uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_imc_events.h"
+
+#define DEFINE_IMC_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_imc##n##_support = { \
+	.desc			= "Intel BroadwellX IMC"#n" uncore", \
+	.name			= "bdx_unc_imc"#n, \
+	.perf_name		= "uncore_imc_"#n, \
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_IMC##n, \
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_m_pe), \
+	.type			= PFM_PMU_TYPE_UNCORE, \
+	.num_cntrs		= 4, \
+	.num_fixed_cntrs	= 1, \
+	.max_encoding		= 1, \
+	.pe			= intel_bdx_unc_m_pe, \
+	.atdesc			= snbep_unc_mods, \
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK, \
+	.pmu_detect		= pfm_intel_bdx_unc_detect, \
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding, \
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding), \
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first, \
+	.get_event_next		= pfm_intel_x86_get_event_next, \
+	.event_is_valid		= pfm_intel_x86_event_is_valid, \
+	.validate_table		= pfm_intel_x86_validate_table, \
+	.get_event_info		= pfm_intel_x86_get_event_info, \
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info, \
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs), \
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs, \
+};
+
+DEFINE_IMC_BOX(0);
+DEFINE_IMC_BOX(1);
+DEFINE_IMC_BOX(2);
+DEFINE_IMC_BOX(3);
+DEFINE_IMC_BOX(4);
+DEFINE_IMC_BOX(5);
+DEFINE_IMC_BOX(6);
+DEFINE_IMC_BOX(7);
diff --git a/lib/pfmlib_intel_bdx_unc_irp.c b/lib/pfmlib_intel_bdx_unc_irp.c
new file mode 100644
index 0000000..14e010b
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_irp.c
@@ -0,0 +1,79 @@
+/*
+ * pfmlib_intel_bdx_irp.c : Intel BroadwellX IRP uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_irp_events.h"
+
+static void
+display_irp(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_IRP=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->irp.unc_event,
+			reg->irp.unc_umask,
+			reg->irp.unc_en,
+			reg->irp.unc_edge,
+			reg->irp.unc_thres,
+			pe[e->event].name);
+}
+
+pfmlib_pmu_t intel_bdx_unc_irp_support = {
+	.desc			= "Intel BroadwellX IRP uncore",
+	.name			= "bdx_unc_irp",
+	.perf_name		= "uncore_irp",
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_IRP,
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_i_pe),
+	.type			= PFM_PMU_TYPE_UNCORE,
+	.num_cntrs		= 4,
+	.num_fixed_cntrs	= 0,
+	.max_encoding		= 3,
+	.pe			= intel_bdx_unc_i_pe,
+	.atdesc			= snbep_unc_mods,
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,
+	.pmu_detect		= pfm_intel_bdx_unc_detect,
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect),
+	.get_event_first	= pfm_intel_x86_get_event_first,
+	.get_event_next		= pfm_intel_x86_get_event_next,
+	.event_is_valid		= pfm_intel_x86_event_is_valid,
+	.validate_table		= pfm_intel_x86_validate_table,
+	.get_event_info		= pfm_intel_x86_get_event_info,
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,
+	.display_reg		= display_irp,
+};
diff --git a/lib/pfmlib_intel_bdx_unc_pcu.c b/lib/pfmlib_intel_bdx_unc_pcu.c
new file mode 100644
index 0000000..435f280
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_pcu.c
@@ -0,0 +1,97 @@
+/*
+ * pfmlib_intel_bdx_unc_pcu.c : Intel BroadwellX Power Control Unit (PCU) uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_pcu_events.h"
+
+static void
+display_pcu(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+	pfm_snbep_unc_reg_t f;
+
+	__pfm_vbprintf("[UNC_PCU=0x%"PRIx64" event=0x%x sel_ext=%d occ_sel=0x%x en=%d "
+			"edge=%d thres=%d occ_inv=%d occ_edge=%d] %s\n",
+			reg->val,
+			reg->ivbep_pcu.unc_event,
+			reg->ivbep_pcu.unc_sel_ext,
+			reg->ivbep_pcu.unc_occ,
+			reg->ivbep_pcu.unc_en,
+			reg->ivbep_pcu.unc_edge,
+			reg->ivbep_pcu.unc_thres,
+			reg->ivbep_pcu.unc_occ_inv,
+			reg->ivbep_pcu.unc_occ_edge,
+			pe[e->event].name);
+
+	if (e->count == 1)
+		return;
+
+	f.val = e->codes[1];
+
+	__pfm_vbprintf("[UNC_PCU_FILTER=0x%"PRIx64" band0=%u band1=%u band2=%u band3=%u]\n",
+			f.val,
+			f.pcu_filt.filt0,
+			f.pcu_filt.filt1,
+			f.pcu_filt.filt2,
+			f.pcu_filt.filt3);
+}
+
+
+pfmlib_pmu_t intel_bdx_unc_pcu_support = {
+	.desc			= "Intel BroadwellX PCU uncore",
+	.name			= "bdx_unc_pcu",
+	.perf_name		= "uncore_pcu",
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_PCU,
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_p_pe),
+	.type			= PFM_PMU_TYPE_UNCORE,
+	.num_cntrs		= 4,
+	.num_fixed_cntrs	= 0,
+	.max_encoding		= 2,
+	.pe			= intel_bdx_unc_p_pe,
+	.atdesc			= snbep_unc_mods,
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,
+	.pmu_detect		= pfm_intel_bdx_unc_detect,
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect),
+	.get_event_first	= pfm_intel_x86_get_event_first,
+	.get_event_next		= pfm_intel_x86_get_event_next,
+	.event_is_valid		= pfm_intel_x86_event_is_valid,
+	.validate_table		= pfm_intel_x86_validate_table,
+	.get_event_info		= pfm_intel_x86_get_event_info,
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,
+	.can_auto_encode	= pfm_intel_snbep_unc_can_auto_encode,
+	.display_reg		= display_pcu,
+};
diff --git a/lib/pfmlib_intel_bdx_unc_qpi.c b/lib/pfmlib_intel_bdx_unc_qpi.c
new file mode 100644
index 0000000..e3fba3d
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_qpi.c
@@ -0,0 +1,85 @@
+/*
+ * pfmlib_intel_bdx_qpi.c : Intel BroadwellX QPI uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_qpi_events.h"
+
+static void
+display_qpi(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_QPI=0x%"PRIx64" event=0x%x sel_ext=%d umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->qpi.unc_event,
+			reg->qpi.unc_event_ext,
+			reg->qpi.unc_umask,
+			reg->qpi.unc_en,
+			reg->qpi.unc_inv,
+			reg->qpi.unc_edge,
+			reg->qpi.unc_thres,
+			pe[e->event].name);
+}
+
+#define DEFINE_QPI_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_qpi##n##_support = {\
+	.desc			= "Intel BroadwellX QPI"#n" uncore",\
+	.name			= "bdx_unc_qpi"#n,\
+	.perf_name		= "uncore_qpi_"#n,\
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_QPI##n,\
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_q_pe),\
+	.type			= PFM_PMU_TYPE_UNCORE,\
+	.num_cntrs		= 4,\
+	.num_fixed_cntrs	= 0,\
+	.max_encoding		= 3,\
+	.pe			= intel_bdx_unc_q_pe,\
+	.atdesc			= snbep_unc_mods,\
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,\
+	.pmu_detect		= pfm_intel_bdx_unc_detect,\
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,\
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),\
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first,\
+	.get_event_next		= pfm_intel_x86_get_event_next,\
+	.event_is_valid		= pfm_intel_x86_event_is_valid,\
+	.validate_table		= pfm_intel_x86_validate_table,\
+	.get_event_info		= pfm_intel_x86_get_event_info,\
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,\
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),\
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,\
+	.display_reg		= display_qpi,\
+}
+DEFINE_QPI_BOX(0);
+DEFINE_QPI_BOX(1);
+DEFINE_QPI_BOX(2);
diff --git a/lib/pfmlib_intel_bdx_unc_r2pcie.c b/lib/pfmlib_intel_bdx_unc_r2pcie.c
new file mode 100644
index 0000000..18bed6c
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_r2pcie.c
@@ -0,0 +1,80 @@
+/*
+ * pfmlib_intel_bdx_r2pcie.c : Intel BroadwellX R2PCIe uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_r2pcie_events.h"
+
+static void
+display_r2(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_R2PCIE=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->com.unc_event,
+			reg->com.unc_umask,
+			reg->com.unc_en,
+			reg->com.unc_inv,
+			reg->com.unc_edge,
+			reg->com.unc_thres,
+			pe[e->event].name);
+}
+
+pfmlib_pmu_t intel_bdx_unc_r2pcie_support = {
+	.desc			= "Intel BroadwellX R2PCIe uncore",
+	.name			= "bdx_unc_r2pcie",
+	.perf_name		= "uncore_r2pcie",
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_R2PCIE,
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_r2_pe),
+	.type			= PFM_PMU_TYPE_UNCORE,
+	.num_cntrs		= 4,
+	.num_fixed_cntrs	= 0,
+	.max_encoding		= 1,
+	.pe			= intel_bdx_unc_r2_pe,
+	.atdesc			= snbep_unc_mods,
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,
+	.pmu_detect		= pfm_intel_bdx_unc_detect,
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect),
+	.get_event_first	= pfm_intel_x86_get_event_first,
+	.get_event_next		= pfm_intel_x86_get_event_next,
+	.event_is_valid		= pfm_intel_x86_event_is_valid,
+	.validate_table		= pfm_intel_x86_validate_table,
+	.get_event_info		= pfm_intel_x86_get_event_info,
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,
+	.display_reg		= display_r2,
+};
diff --git a/lib/pfmlib_intel_bdx_unc_r3qpi.c b/lib/pfmlib_intel_bdx_unc_r3qpi.c
new file mode 100644
index 0000000..89ba498
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_r3qpi.c
@@ -0,0 +1,84 @@
+/*
+ * pfmlib_intel_bdx_r3qpi.c : Intel BroadwellX R3QPI uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_r3qpi_events.h"
+
+static void
+display_r3(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_R3QPI=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->com.unc_event,
+			reg->com.unc_umask,
+			reg->com.unc_en,
+			reg->com.unc_inv,
+			reg->com.unc_edge,
+			reg->com.unc_thres,
+			pe[e->event].name);
+}
+
+#define DEFINE_R3QPI_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_r3qpi##n##_support = {\
+	.desc			= "Intel BroadwellX R3QPI"#n" uncore", \
+	.name			= "bdx_unc_r3qpi"#n,\
+	.perf_name		= "uncore_r3qpi_"#n, \
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_R3QPI##n, \
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_r3_pe),\
+	.type			= PFM_PMU_TYPE_UNCORE,\
+	.num_cntrs		= 3,\
+	.num_fixed_cntrs	= 0,\
+	.max_encoding		= 1,\
+	.pe			= intel_bdx_unc_r3_pe,\
+	.atdesc			= snbep_unc_mods,\
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,\
+	.pmu_detect		= pfm_intel_bdx_unc_detect,\
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,\
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),\
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first,\
+	.get_event_next		= pfm_intel_x86_get_event_next,\
+	.event_is_valid		= pfm_intel_x86_event_is_valid,\
+	.validate_table		= pfm_intel_x86_validate_table,\
+	.get_event_info		= pfm_intel_x86_get_event_info,\
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,\
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),\
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,\
+	.display_reg		= display_r3,\
+}
+DEFINE_R3QPI_BOX(0);
+DEFINE_R3QPI_BOX(1);
+DEFINE_R3QPI_BOX(2);
diff --git a/lib/pfmlib_intel_bdx_unc_sbo.c b/lib/pfmlib_intel_bdx_unc_sbo.c
new file mode 100644
index 0000000..a2be8bc
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_sbo.c
@@ -0,0 +1,86 @@
+/*
+ * pfmlib_intel_bdx_unc_sbo.c : Intel BroadwellX S-Box uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_sbo_events.h"
+
+static void
+display_sbo(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_SBO=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->com.unc_event,
+			reg->com.unc_umask,
+			reg->com.unc_en,
+			reg->com.unc_inv,
+			reg->com.unc_edge,
+			reg->com.unc_thres,
+			pe[e->event].name);
+}
+
+#define DEFINE_S_BOX(n) \
+pfmlib_pmu_t intel_bdx_unc_sbo##n##_support = {\
+	.desc			= "Intel BroadwellX S-BOX"#n" uncore",\
+	.name			= "bdx_unc_sbo"#n,\
+	.perf_name		= "uncore_sbox_"#n,\
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_SB##n,\
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_s_pe),\
+	.type			= PFM_PMU_TYPE_UNCORE,\
+	.num_cntrs		= 4,\
+	.num_fixed_cntrs	= 0,\
+	.max_encoding		= 3,\
+	.pe			= intel_bdx_unc_s_pe,\
+	.atdesc			= snbep_unc_mods,\
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,\
+	.pmu_detect		= pfm_intel_bdx_unc_detect,\
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,\
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),\
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect), \
+	.get_event_first	= pfm_intel_x86_get_event_first,\
+	.get_event_next		= pfm_intel_x86_get_event_next,\
+	.event_is_valid		= pfm_intel_x86_event_is_valid,\
+	.validate_table		= pfm_intel_x86_validate_table,\
+	.get_event_info		= pfm_intel_x86_get_event_info,\
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,\
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),\
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,\
+	.display_reg		= display_sbo,\
+}
+
+DEFINE_S_BOX(0);
+DEFINE_S_BOX(1);
+DEFINE_S_BOX(2);
+DEFINE_S_BOX(3);
diff --git a/lib/pfmlib_intel_bdx_unc_ubo.c b/lib/pfmlib_intel_bdx_unc_ubo.c
new file mode 100644
index 0000000..f0d058a
--- /dev/null
+++ b/lib/pfmlib_intel_bdx_unc_ubo.c
@@ -0,0 +1,81 @@
+/*
+ * pfmlib_intel_bdx_unc_ubo.c : Intel BroadwellX U-Box uncore PMU
+ *
+ * Copyright (c) 2017 Google Inc. All rights reserved
+ * Contributed by Stephane Eranian <eranian@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* private headers */
+#include "pfmlib_priv.h"
+#include "pfmlib_intel_x86_priv.h"
+#include "pfmlib_intel_snbep_unc_priv.h"
+#include "events/intel_bdx_unc_ubo_events.h"
+
+static void
+display_ubo(void *this, pfmlib_event_desc_t *e, void *val)
+{
+	const intel_x86_entry_t *pe = this_pe(this);
+	pfm_snbep_unc_reg_t *reg = val;
+
+	__pfm_vbprintf("[UNC_UBO=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
+		       "inv=%d edge=%d thres=%d] %s\n",
+			reg->val,
+			reg->com.unc_event,
+			reg->com.unc_umask,
+			reg->com.unc_en,
+			reg->com.unc_inv,
+			reg->com.unc_edge,
+			reg->com.unc_thres,
+			pe[e->event].name);
+}
+
+
+pfmlib_pmu_t intel_bdx_unc_ubo_support = {
+	.desc			= "Intel BroadwellX U-Box uncore",
+	.name			= "bdx_unc_ubo",
+	.perf_name		= "uncore_ubox",
+	.pmu			= PFM_PMU_INTEL_BDX_UNC_UBOX,
+	.pme_count		= LIBPFM_ARRAY_SIZE(intel_bdx_unc_u_pe),
+	.type			= PFM_PMU_TYPE_UNCORE,
+	.num_cntrs		= 2,
+	.num_fixed_cntrs	= 1,
+	.max_encoding		= 1,
+	.pe			= intel_bdx_unc_u_pe,
+	.atdesc			= snbep_unc_mods,
+	.flags			= PFMLIB_PMU_FL_RAW_UMASK,
+	.pmu_detect		= pfm_intel_bdx_unc_detect,
+	.get_event_encoding[PFM_OS_NONE] = pfm_intel_snbep_unc_get_encoding,
+	 PFMLIB_ENCODE_PERF(pfm_intel_snbep_unc_get_perf_encoding),
+	 PFMLIB_OS_DETECT(pfm_intel_x86_perf_detect),
+	.get_event_first	= pfm_intel_x86_get_event_first,
+	.get_event_next		= pfm_intel_x86_get_event_next,
+	.event_is_valid		= pfm_intel_x86_event_is_valid,
+	.validate_table		= pfm_intel_x86_validate_table,
+	.get_event_info		= pfm_intel_x86_get_event_info,
+	.get_event_attr_info	= pfm_intel_x86_get_event_attr_info,
+	PFMLIB_VALID_PERF_PATTRS(pfm_intel_snbep_unc_perf_validate_pattrs),
+	.get_event_nattrs	= pfm_intel_x86_get_event_nattrs,
+	.display_reg		= display_ubo,
+};
diff --git a/lib/pfmlib_intel_snbep_unc.c b/lib/pfmlib_intel_snbep_unc.c
index 1e80147..c44d92a 100644
--- a/lib/pfmlib_intel_snbep_unc.c
+++ b/lib/pfmlib_intel_snbep_unc.c
@@ -129,7 +129,26 @@ pfm_intel_knl_unc_detect(void *this)
        return PFM_SUCCESS;
 }
 
+int
+pfm_intel_bdx_unc_detect(void *this)
+{
+       int ret;
+
+       ret = pfm_intel_x86_detect();
+       if (ret != PFM_SUCCESS)
+
+       if (pfm_intel_x86_cfg.family != 6)
+               return PFM_ERR_NOTSUPP;
 
+       switch(pfm_intel_x86_cfg.model) {
+               case 79: /* Broadwell X */
+               case 86: /* Broadwell X */
+                         break;
+               default:
+                       return PFM_ERR_NOTSUPP;
+       }
+       return PFM_SUCCESS;
+}
 
 static void
 display_com(void *this, pfmlib_event_desc_t *e, void *val)
@@ -255,7 +274,7 @@ snbep_unc_add_defaults(void *this, pfmlib_event_desc_t *e,
 			}
 		}
 		if (!added && !skip) {
-			DPRINT("no default found for event %s unit mask group %d (max_grpid=%d)\n", ent->name, i, max_grpid);
+			DPRINT("no default found for event %s unit mask group %d (max_grpid=%d, i=%d)\n", ent->name, i, max_grpid, i);
 			return PFM_ERR_UMASK;
 		}
 	}
diff --git a/lib/pfmlib_intel_snbep_unc_priv.h b/lib/pfmlib_intel_snbep_unc_priv.h
index 4984242..898a460 100644
--- a/lib/pfmlib_intel_snbep_unc_priv.h
+++ b/lib/pfmlib_intel_snbep_unc_priv.h
@@ -65,10 +65,13 @@
 #define HSWEP_UNC_IRP_ATTRS \
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8|_SNBEP_UNC_ATTR_I)
 
+#define BDX_UNC_IRP_ATTRS HSWEP_UNC_IRP_ATTRS
+
 #define SNBEP_UNC_R3QPI_ATTRS \
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
 
 #define HSWEP_UNC_R3QPI_ATTRS SNBEP_UNC_R3QPI_ATTRS
+#define BDX_UNC_R3QPI_ATTRS   SNBEP_UNC_R3QPI_ATTRS
 
 #define IVBEP_UNC_R3QPI_ATTRS \
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
@@ -77,6 +80,7 @@
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
 
 #define HSWEP_UNC_R2PCIE_ATTRS SNBEP_UNC_R2PCIE_ATTRS
+#define BDX_UNC_R2PCIE_ATTRS   SNBEP_UNC_R2PCIE_ATTRS
 
 #define IVBEP_UNC_R2PCIE_ATTRS \
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
@@ -88,6 +92,7 @@
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
 
 #define HSWEP_UNC_QPI_ATTRS SNBEP_UNC_QPI_ATTRS
+#define BDX_UNC_QPI_ATTRS   SNBEP_UNC_QPI_ATTRS
 
 #define SNBEP_UNC_UBO_ATTRS \
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
@@ -96,6 +101,7 @@
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
 
 #define HSWEP_UNC_UBO_ATTRS SNBEP_UNC_UBO_ATTRS
+#define BDX_UNC_UBO_ATTRS   SNBEP_UNC_UBO_ATTRS
 
 #define SNBEP_UNC_PCU_ATTRS \
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T5)
@@ -105,6 +111,9 @@
 
 #define HSWEP_UNC_PCU_ATTRS SNBEP_UNC_PCU_ATTRS
 
+#define BDX_UNC_PCU_ATTRS \
+	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
+
 #define SNBEP_UNC_PCU_BAND_ATTRS \
 	(SNBEP_UNC_PCU_ATTRS | _SNBEP_UNC_ATTR_FF)
 
@@ -112,6 +121,7 @@
 	(IVBEP_UNC_PCU_ATTRS | _SNBEP_UNC_ATTR_FF)
 
 #define HSWEP_UNC_PCU_BAND_ATTRS SNBEP_UNC_PCU_BAND_ATTRS
+#define BDX_UNC_PCU_BAND_ATTRS   SNBEP_UNC_PCU_BAND_ATTRS
 
 #define SNBEP_UNC_IMC_ATTRS \
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
@@ -121,6 +131,8 @@
 
 #define HSWEP_UNC_IMC_ATTRS SNBEP_UNC_IMC_ATTRS
 
+#define BDX_UNC_IMC_ATTRS SNBEP_UNC_IMC_ATTRS
+
 #define SNBEP_UNC_CBO_ATTRS   \
 	(_SNBEP_UNC_ATTR_I   |\
 	 _SNBEP_UNC_ATTR_E   |\
@@ -140,6 +152,8 @@
 	 _SNBEP_UNC_ATTR_CF1 |\
 	 _SNBEP_UNC_ATTR_TF)
 
+#define BDX_UNC_CBO_ATTRS HSWEP_UNC_CBO_ATTRS
+
 #define SNBEP_UNC_CBO_NID_ATTRS	\
 	(SNBEP_UNC_CBO_ATTRS|_SNBEP_UNC_ATTR_NF)
 
@@ -149,6 +163,8 @@
 #define HSWEP_UNC_CBO_NID_ATTRS	\
 	(HSWEP_UNC_CBO_ATTRS | _SNBEP_UNC_ATTR_NF1)
 
+#define BDX_UNC_CBO_NID_ATTRS HSWEP_UNC_CBO_NID_ATTRS
+
 #define SNBEP_UNC_HA_ATTRS \
 	(_SNBEP_UNC_ATTR_I|_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8)
 
@@ -158,12 +174,18 @@
 #define HSWEP_UNC_HA_ATTRS \
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8|_SNBEP_UNC_ATTR_I)
 
+#define BDX_UNC_HA_ATTRS \
+	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8|_SNBEP_UNC_ATTR_I)
+
 #define SNBEP_UNC_HA_OPC_ATTRS \
 	(SNBEP_UNC_HA_ATTRS|_SNBEP_UNC_ATTR_A)
 
 #define HSWEP_UNC_SBO_ATTRS \
 	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8|_SNBEP_UNC_ATTR_I)
 
+#define BDX_UNC_SBO_ATTRS \
+	(_SNBEP_UNC_ATTR_E|_SNBEP_UNC_ATTR_T8|_SNBEP_UNC_ATTR_I)
+
 #define KNL_UNC_CHA_TOR_ATTRS    _SNBEP_UNC_ATTR_NF1
 
 typedef union {
@@ -327,6 +349,7 @@ extern int  pfm_intel_snbep_unc_detect(void *this);
 extern int  pfm_intel_ivbep_unc_detect(void *this);
 extern int  pfm_intel_hswep_unc_detect(void *this);
 extern int  pfm_intel_knl_unc_detect(void *this);
+extern int  pfm_intel_bdx_unc_detect(void *this);
 extern int  pfm_intel_snbep_unc_get_perf_encoding(void *this, pfmlib_event_desc_t *e);
 extern int  pfm_intel_snbep_unc_can_auto_encode(void *this, int pidx, int uidx);
 extern int pfm_intel_snbep_unc_get_event_attr_info(void *this, int pidx, int attr_idx, pfmlib_event_attr_info_t *info);
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index 1f80571..1f2d030 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -439,6 +439,54 @@ extern pfmlib_pmu_t intel_knl_unc_cha35_support;
 extern pfmlib_pmu_t intel_knl_unc_cha36_support;
 extern pfmlib_pmu_t intel_knl_unc_cha37_support;
 extern pfmlib_pmu_t intel_knl_unc_m2pcie_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb0_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb1_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb2_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb3_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb4_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb5_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb6_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb7_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb8_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb9_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb10_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb11_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb12_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb13_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb14_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb15_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb16_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb17_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb18_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb19_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb20_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb21_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb22_support;
+extern pfmlib_pmu_t intel_bdx_unc_cb23_support;
+extern pfmlib_pmu_t intel_bdx_unc_ha0_support;
+extern pfmlib_pmu_t intel_bdx_unc_ha1_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc0_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc1_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc2_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc3_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc4_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc5_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc6_support;
+extern pfmlib_pmu_t intel_bdx_unc_imc7_support;
+extern pfmlib_pmu_t intel_bdx_unc_pcu_support;
+extern pfmlib_pmu_t intel_bdx_unc_qpi0_support;
+extern pfmlib_pmu_t intel_bdx_unc_qpi1_support;
+extern pfmlib_pmu_t intel_bdx_unc_qpi2_support;
+extern pfmlib_pmu_t intel_bdx_unc_sbo0_support;
+extern pfmlib_pmu_t intel_bdx_unc_sbo1_support;
+extern pfmlib_pmu_t intel_bdx_unc_sbo2_support;
+extern pfmlib_pmu_t intel_bdx_unc_sbo3_support;
+extern pfmlib_pmu_t intel_bdx_unc_ubo_support;
+extern pfmlib_pmu_t intel_bdx_unc_r2pcie_support;
+extern pfmlib_pmu_t intel_bdx_unc_r3qpi0_support;
+extern pfmlib_pmu_t intel_bdx_unc_r3qpi1_support;
+extern pfmlib_pmu_t intel_bdx_unc_r3qpi2_support;
+extern pfmlib_pmu_t intel_bdx_unc_irp_support;
 extern pfmlib_pmu_t intel_glm_support;
 extern pfmlib_pmu_t power4_support;
 extern pfmlib_pmu_t ppc970_support;
diff --git a/tests/validate_x86.c b/tests/validate_x86.c
index aa0aaa1..3edc8a8 100644
--- a/tests/validate_x86.c
+++ b/tests/validate_x86.c
@@ -4755,6 +4755,836 @@ static const test_event_t x86_test_events[]={
 	  .name = "skl::offcore_response_1:0x7fffffffff",
 	  .ret  = PFM_ERR_ATTR,
 	},
+
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo1::UNC_C_CLOCKTICKS:u",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo0::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo1::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo1::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo2::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo2::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo3::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo3::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo4::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo4::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo5::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo5::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo6::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo6::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo7::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo7::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo8::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo8::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo9::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo9::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo10::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo10::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo11::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo11::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo12::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo12::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo13::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo13::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo14::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo14::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo15::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo15::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo16::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo16::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo17::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo17::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo18::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo18::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo19::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo19::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo20::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo20::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo21::UNC_C_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_cbo21::UNC_C_CLOCKTICKS:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:DATA_READ",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0x334,
+	  .codes[1] = 0xfe0000,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:DATA_READ:STATE_MESIFD:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:DATA_READ:nf=1",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0x1134,
+	  .codes[1] = 0xfe0000,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:ANY:STATE_MESIFD:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:NID:STATE_M",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:NID:nf=3",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x5134,
+	  .codes[1] = 0xfe0000,
+	  .codes[2] = 0x3,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:ANY:NID:STATE_MESIFD:e=0:t=0:tf=0:nf=3:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:NID:STATE_M:tid=1",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_ring_iv_used:DN:UP",
+	  .ret  = PFM_ERR_FEATCOMB,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:WRITE:NID:nf=3:tf=1:e:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x10c4534,
+	  .codes[1] = 0xfe0001,
+	  .codes[2] = 0x3,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_LOOKUP:NID:WRITE:STATE_MESIFD:e=1:t=1:tf=1:nf=3:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS",
+	  .ret  = PFM_ERR_UMASK,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:NID",
+	  .ret  = PFM_ERR_UMASK,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:NID:nf=1",
+	  .ret  = PFM_ERR_UMASK,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:M_STATE",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x137,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:M_STATE:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:M_STATE:S_STATE",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x537,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:S_STATE:M_STATE:e=0:t=0:tf=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:M_STATE:S_STATE:NID:nf=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x4537,
+	  .codes[1] = 0x0,
+	  .codes[2] = 0x1,
+	  .fstr = "bdx_unc_cbo0::UNC_C_LLC_VICTIMS:S_STATE:M_STATE:NID:e=0:t=0:tf=0:nf=1:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE",
+	  .ret  = PFM_ERR_UMASK,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:WB",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1035,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:WB:e=0:t=0:tf=0:isoc=0:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE:OPC_ITOM",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x135,
+	  .codes[1] = 0x0,
+	  .codes[2] = 0x1c800000ull,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE:OPC_ITOM:e=0:t=0:tf=0:isoc=0:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE:OPC_ITOM:isoc=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x135,
+	  .codes[1] = 0x0,
+	  .codes[2] = 0x9c800000ull,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE:OPC_ITOM:e=0:t=0:tf=0:isoc=1:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPCODE:OPC_PCIWILF:nf=1",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:NID_OPCODE:OPC_PCIRDCUR:nf=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x4135,
+	  .codes[1] = 0x0,
+	  .codes[2] = 0x19e00001ull,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:NID_OPCODE:OPC_PCIRDCUR:e=0:t=0:tf=0:nf=1:isoc=0:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:OPC_RFO:NID_OPCODE:nf=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 3,
+	  .codes[0] = 0x4135,
+	  .codes[1] = 0x0,
+	  .codes[2] = 0x18000001ull,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_INSERTS:NID_OPCODE:OPC_RFO:e=0:t=0:tf=0:nf=1:isoc=0:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_cbo0::UNC_C_TOR_OCCUPANCY:MISS_REMOTE",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8a36,
+	  .fstr = "bdx_unc_cbo0::UNC_C_TOR_OCCUPANCY:MISS_REMOTE:e=0:t=0:tf=0:isoc=0:nc=0:cf=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_irp::unc_i_clockticks",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_irp::UNC_I_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_irp::unc_i_coherent_ops:RFO",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x813,
+	  .fstr = "bdx_unc_irp::UNC_I_COHERENT_OPS:RFO:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_irp::unc_i_transactions:reads",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x116,
+	  .fstr = "bdx_unc_irp::UNC_I_TRANSACTIONS:READS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_irp::unc_i_transactions:reads:c=1:i",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_irp::unc_i_transactions:reads:t=6",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x6000116,
+	  .fstr = "bdx_unc_irp::UNC_I_TRANSACTIONS:READS:e=0:i=0:t=6",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo0::unc_s_clockticks",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo0::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo1::unc_s_clockticks",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo1::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo2::unc_s_clockticks",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo2::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo3::unc_s_clockticks",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo3::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_pcu::UNC_P_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_CLOCKTICKS:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1000000,
+	  .fstr = "bdx_unc_pcu::UNC_P_CLOCKTICKS:e=0:i=0:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_CORE0_TRANSITION_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x60,
+	  .fstr = "bdx_unc_pcu::UNC_P_CORE0_TRANSITION_CYCLES:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_CORE17_TRANSITION_CYCLES",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x71,
+	  .fstr = "bdx_unc_pcu::UNC_P_CORE17_TRANSITION_CYCLES:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND1_CYCLES",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND2_CYCLES",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND3_CYCLES",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:ff=32",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0xb,
+	  .codes[1] = 0x20,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:e=0:i=0:t=0:ff=32",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND1_CYCLES:ff=16",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0xc,
+	  .codes[1] = 0x1000,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND1_CYCLES:e=0:i=0:t=0:ff=16",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND2_CYCLES:ff=8",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0xd,
+	  .codes[1] = 0x80000,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND2_CYCLES:e=0:i=0:t=0:ff=8",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND3_CYCLES:ff=40",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0xe,
+	  .codes[1] = 0x28000000,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND3_CYCLES:e=0:i=0:t=0:ff=40",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:ff=32:e",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0x4000b,
+	  .codes[1] = 0x20,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:e=1:i=0:t=0:ff=32",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:ff=32:t=24",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0x1800000b,
+	  .codes[1] = 0x20,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:e=0:i=0:t=24:ff=32",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:ff=32:e:t=4",
+	  .ret  = PFM_SUCCESS,
+	  .count = 2,
+	  .codes[0] = 0x404000b,
+	  .codes[1] = 0x20,
+	  .fstr = "bdx_unc_pcu::UNC_P_FREQ_BAND0_CYCLES:e=1:i=0:t=4:ff=32",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x4080,
+	  .fstr = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0:e=0:i=0:t=0"
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C3",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x8080,
+	  .fstr = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C3:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C6",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xc080,
+	  .fstr = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C6:e=0:i=0:t=0"
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0:t=6:i",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x6804080,
+	  .fstr = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0:e=0:i=1:t=6"
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0:t=6",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x6004080,
+	  .fstr = "bdx_unc_pcu::UNC_P_POWER_STATE_OCCUPANCY:CORES_C0:e=0:i=0:t=6"
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE10",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x3a,
+	  .fstr = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE10:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE14",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x3e,
+	  .fstr = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE14:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE17",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x41,
+	  .fstr = "bdx_unc_pcu::UNC_P_DEMOTIONS_CORE17:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ha0::UNC_H_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_ha0::UNC_H_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ha1::UNC_H_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_ha1::UNC_H_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ha1::UNC_H_REQUESTS:READS:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1000301,
+	  .fstr = "bdx_unc_ha1::UNC_H_REQUESTS:READS:e=0:i=0:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ha0::UNC_H_IMC_WRITES:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1000f1a,
+	  .fstr = "bdx_unc_ha0::UNC_H_IMC_WRITES:ALL:e=0:i=0:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ha0::UNC_H_IMC_READS:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1000117,
+	  .fstr = "bdx_unc_ha0::UNC_H_IMC_READS:NORMAL:e=0:i=0:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc0::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc1::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc1::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc2::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc2::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc3::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc3::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc4::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc4::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc5::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc5::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc6::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc6::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc7::UNC_M_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xff,
+	  .fstr = "bdx_unc_imc7::UNC_M_CLOCKTICKS",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_CLOCKTICKS:t=1",
+	  .ret  = PFM_ERR_ATTR,
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_DCLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_imc0::UNC_M_DCLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc4::UNC_M_DCLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x00,
+	  .fstr = "bdx_unc_imc4::UNC_M_DCLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_CAS_COUNT:RD",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0304,
+	  .fstr = "bdx_unc_imc0::UNC_M_CAS_COUNT:RD:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_PRE_COUNT:WR",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0802,
+	  .fstr = "bdx_unc_imc0::UNC_M_PRE_COUNT:WR:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_POWER_CKE_CYCLES:RANK0",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x183,
+	  .fstr = "bdx_unc_imc0::UNC_M_POWER_CKE_CYCLES:RANK0:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_CAS_COUNT:WR",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xc04,
+	  .fstr = "bdx_unc_imc0::UNC_M_CAS_COUNT:WR:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:BANK0",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xb0,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:BANK0:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:ALLBANKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x10b0,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:ALLBANKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:BANKG0",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x11b0,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK0:BANKG0:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK4:BANK7",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x7b4,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK4:BANK7:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK4:BANK7:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x10007b4,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK4:BANK7:e=0:i=0:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_imc0::UNC_M_RD_CAS_RANK7:BANK7:t=1:i",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x18007b7,
+	  .fstr = "bdx_unc_imc0::UNC_M_RD_CAS_RANK7:BANK7:e=0:i=1:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo0::UNC_S_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo0::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo0::UNC_S_FAST_ASSERTED:t=1:i",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1800009,
+	  .fstr = "bdx_unc_sbo0::UNC_S_FAST_ASSERTED:e=0:i=1:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo3::UNC_S_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x0,
+	  .fstr = "bdx_unc_sbo3::UNC_S_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_sbo3::UNC_S_FAST_ASSERTED:t=1:i",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1800009,
+	  .fstr = "bdx_unc_sbo3::UNC_S_FAST_ASSERTED:e=0:i=1:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_ubo::UNC_U_EVENT_MSG",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x842,
+	  .fstr = "bdx_unc_ubo::UNC_U_EVENT_MSG:DOORBELL_RCVD:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x14,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi1::UNC_Q_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x14,
+	  .fstr = "bdx_unc_qpi1::UNC_Q_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi2::UNC_Q_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x14,
+	  .fstr = "bdx_unc_qpi2::UNC_Q_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_DIRECT2CORE:SUCCESS_RBT_HIT",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x113,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_DIRECT2CORE:SUCCESS_RBT_HIT:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_RXL_FLITS_G1:DRS:i:t=1",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1a01802,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_RXL_FLITS_G1:DRS:e=0:i=1:t=1",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_TXL_FLITS_G2:NDR_AD",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x200101,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_TXL_FLITS_G2:NDR_AD:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_RXL_OCCUPANCY",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0xb,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_RXL_OCCUPANCY:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_qpi0::UNC_Q_TXL_INSERTS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x4,
+	  .fstr = "bdx_unc_qpi0::UNC_Q_TXL_INSERTS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r2pcie::UNC_R2_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1,
+	  .fstr = "bdx_unc_r2pcie::UNC_R2_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r2pcie::UNC_R2_RING_AD_USED:CW",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x307,
+	  .fstr = "bdx_unc_r2pcie::UNC_R2_RING_AD_USED:CW:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r3qpi0::UNC_R3_CLOCKTICKS",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x1,
+	  .fstr = "bdx_unc_r3qpi0::UNC_R3_CLOCKTICKS:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r3qpi0::UNC_R3_RXR_CYCLES_NE:SNP:e=0:t=0",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x210,
+	  .fstr = "bdx_unc_r3qpi0::UNC_R3_RXR_CYCLES_NE:SNP:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r3qpi1::UNC_R3_RING_SINK_STARVED",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x20e,
+	  .fstr = "bdx_unc_r3qpi1::UNC_R3_RING_SINK_STARVED:AK:e=0:i=0:t=0",
+	},
+	{ SRC_LINE,
+	  .name = "bdx_unc_r3qpi1::UNC_R3_HA_R2_BL_CREDITS_EMPTY:HA1:i:t=2",
+	  .ret  = PFM_SUCCESS,
+	  .count = 1,
+	  .codes[0] = 0x280022d,
+	  .fstr = "bdx_unc_r3qpi1::UNC_R3_HA_R2_BL_CREDITS_EMPTY:HA1:e=0:i=1:t=2",
+	},
 };
 
 #define NUM_TEST_EVENTS (int)(sizeof(x86_test_events)/sizeof(test_event_t))