Merge branch 'x86/cpu' into perf/core, to pick up dependent changes
authorIngo Molnar <mingo@kernel.org>
Mon, 17 Jun 2019 10:29:16 +0000 (12:29 +0200)
committerIngo Molnar <mingo@kernel.org>
Mon, 17 Jun 2019 10:29:16 +0000 (12:29 +0200)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
73 files changed:
Documentation/cputopology.txt
Documentation/x86/topology.rst
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore.h
arch/x86/events/intel/uncore_snb.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/events/perf_event.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/topology.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/topology.c
arch/x86/kernel/smpboot.c
arch/x86/xen/smp_pv.c
drivers/base/topology.c
drivers/hwmon/coretemp.c
drivers/powercap/intel_rapl.c
drivers/thermal/intel/x86_pkg_temp_thermal.c
fs/sysfs/group.c
include/linux/perf_event.h
include/linux/sysfs.h
include/linux/topology.h
kernel/events/core.c
kernel/trace/trace_uprobe.c
tools/include/linux/kernel.h
tools/lib/vsprintf.c
tools/perf/Documentation/intel-pt.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Makefile.perf
tools/perf/builtin-script.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/examples/bpf/augmented_raw_syscalls.c
tools/perf/perf-with-kcore.sh
tools/perf/scripts/python/export-to-postgresql.py
tools/perf/scripts/python/export-to-sqlite.py
tools/perf/scripts/python/exported-sql-viewer.py
tools/perf/tests/Build
tools/perf/tests/builtin-test.c
tools/perf/tests/map_groups.c [new file with mode: 0644]
tools/perf/tests/tests.h
tools/perf/trace/beauty/Build
tools/perf/trace/beauty/beauty.h
tools/perf/trace/beauty/clone.c
tools/perf/trace/beauty/fsconfig.sh [new file with mode: 0755]
tools/perf/trace/beauty/fsmount.c [new file with mode: 0644]
tools/perf/trace/beauty/fsmount.sh [new file with mode: 0755]
tools/perf/trace/beauty/fspick.c [new file with mode: 0644]
tools/perf/trace/beauty/fspick.sh [new file with mode: 0755]
tools/perf/trace/beauty/move_mount.c [new file with mode: 0644]
tools/perf/trace/beauty/move_mount_flags.sh [new file with mode: 0755]
tools/perf/trace/beauty/sync_file_range.c [new file with mode: 0644]
tools/perf/trace/beauty/sync_file_range.sh [new file with mode: 0755]
tools/perf/ui/browsers/annotate.c
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/auxtrace.c
tools/perf/util/dso.c
tools/perf/util/event.c
tools/perf/util/hist.c
tools/perf/util/intel-pt.c
tools/perf/util/machine.c
tools/perf/util/map.c
tools/perf/util/map_groups.h
tools/perf/util/setup.py
tools/perf/util/symbol.c
tools/perf/util/symbol_conf.h
tools/perf/util/thread.c
tools/perf/util/thread.h

index cb61277..b90dafc 100644 (file)
@@ -12,6 +12,12 @@ physical_package_id:
        socket number, but the actual value is architecture and platform
        dependent.
 
+die_id:
+
+       the CPU die ID of cpuX. Typically it is the hardware platform's
+       identifier (rather than the kernel's).  The actual value is
+       architecture and platform dependent.
+
 core_id:
 
        the CPU core ID of cpuX. Typically it is the hardware platform's
@@ -30,25 +36,33 @@ drawer_id:
        identifier (rather than the kernel's).  The actual value is
        architecture and platform dependent.
 
-thread_siblings:
+core_cpus:
 
-       internal kernel map of cpuX's hardware threads within the same
-       core as cpuX.
+       internal kernel map of CPUs within the same core.
+       (deprecated name: "thread_siblings")
 
-thread_siblings_list:
+core_cpus_list:
 
-       human-readable list of cpuX's hardware threads within the same
-       core as cpuX.
+       human-readable list of CPUs within the same core.
+       (deprecated name: "thread_siblings_list");
 
-core_siblings:
+package_cpus:
 
-       internal kernel map of cpuX's hardware threads within the same
-       physical_package_id.
+       internal kernel map of the CPUs sharing the same physical_package_id.
+       (deprecated name: "core_siblings")
 
-core_siblings_list:
+package_cpus_list:
 
-       human-readable list of cpuX's hardware threads within the same
-       physical_package_id.
+       human-readable list of CPUs sharing the same physical_package_id.
+       (deprecated name: "core_siblings_list")
+
+die_cpus:
+
+       internal kernel map of CPUs within the same die.
+
+die_cpus_list:
+
+       human-readable list of CPUs within the same die.
 
 book_siblings:
 
@@ -81,11 +95,13 @@ For an architecture to support this feature, it must define some of
 these macros in include/asm-XXX/topology.h::
 
        #define topology_physical_package_id(cpu)
+       #define topology_die_id(cpu)
        #define topology_core_id(cpu)
        #define topology_book_id(cpu)
        #define topology_drawer_id(cpu)
        #define topology_sibling_cpumask(cpu)
        #define topology_core_cpumask(cpu)
+       #define topology_die_cpumask(cpu)
        #define topology_book_cpumask(cpu)
        #define topology_drawer_cpumask(cpu)
 
@@ -99,9 +115,11 @@ provides default definitions for any of the above macros that are
 not defined by include/asm-XXX/topology.h:
 
 1) topology_physical_package_id: -1
-2) topology_core_id: 0
-3) topology_sibling_cpumask: just the given CPU
-4) topology_core_cpumask: just the given CPU
+2) topology_die_id: -1
+3) topology_core_id: 0
+4) topology_sibling_cpumask: just the given CPU
+5) topology_core_cpumask: just the given CPU
+6) topology_die_cpumask: just the given CPU
 
 For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
 default definitions for topology_book_id() and topology_book_cpumask().
index 6e28dbe..8e9704f 100644 (file)
@@ -49,6 +49,10 @@ Package-related topology information in the kernel:
 
     The number of cores in a package. This information is retrieved via CPUID.
 
+  - cpuinfo_x86.x86_max_dies:
+
+    The number of dies in a package. This information is retrieved via CPUID.
+
   - cpuinfo_x86.phys_proc_id:
 
     The physical ID of the package. This information is retrieved via CPUID
index f315425..f0e4804 100644 (file)
@@ -1618,68 +1618,6 @@ static struct attribute_group x86_pmu_format_group __ro_after_init = {
        .attrs = NULL,
 };
 
-/*
- * Remove all undefined events (x86_pmu.event_map(id) == 0)
- * out of events_attr attributes.
- */
-static void __init filter_events(struct attribute **attrs)
-{
-       struct device_attribute *d;
-       struct perf_pmu_events_attr *pmu_attr;
-       int offset = 0;
-       int i, j;
-
-       for (i = 0; attrs[i]; i++) {
-               d = (struct device_attribute *)attrs[i];
-               pmu_attr = container_of(d, struct perf_pmu_events_attr, attr);
-               /* str trumps id */
-               if (pmu_attr->event_str)
-                       continue;
-               if (x86_pmu.event_map(i + offset))
-                       continue;
-
-               for (j = i; attrs[j]; j++)
-                       attrs[j] = attrs[j + 1];
-
-               /* Check the shifted attr. */
-               i--;
-
-               /*
-                * event_map() is index based, the attrs array is organized
-                * by increasing event index. If we shift the events, then
-                * we need to compensate for the event_map(), otherwise
-                * we are looking up the wrong event in the map
-                */
-               offset++;
-       }
-}
-
-/* Merge two pointer arrays */
-__init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
-{
-       struct attribute **new;
-       int j, i;
-
-       for (j = 0; a && a[j]; j++)
-               ;
-       for (i = 0; b && b[i]; i++)
-               j++;
-       j++;
-
-       new = kmalloc_array(j, sizeof(struct attribute *), GFP_KERNEL);
-       if (!new)
-               return NULL;
-
-       j = 0;
-       for (i = 0; a && a[i]; i++)
-               new[j++] = a[i];
-       for (i = 0; b && b[i]; i++)
-               new[j++] = b[i];
-       new[j] = NULL;
-
-       return new;
-}
-
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page)
 {
        struct perf_pmu_events_attr *pmu_attr = \
@@ -1744,9 +1682,24 @@ static struct attribute *events_attr[] = {
        NULL,
 };
 
+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static umode_t
+is_visible(struct kobject *kobj, struct attribute *attr, int idx)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
+       /* str trumps id */
+       return pmu_attr->event_str || x86_pmu.event_map(idx) ? attr->mode : 0;
+}
+
 static struct attribute_group x86_pmu_events_group __ro_after_init = {
        .name = "events",
        .attrs = events_attr,
+       .is_visible = is_visible,
 };
 
 ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
@@ -1842,37 +1795,10 @@ static int __init init_hw_perf_events(void)
 
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
-       if (x86_pmu.caps_attrs) {
-               struct attribute **tmp;
-
-               tmp = merge_attr(x86_pmu_caps_group.attrs, x86_pmu.caps_attrs);
-               if (!WARN_ON(!tmp))
-                       x86_pmu_caps_group.attrs = tmp;
-       }
-
-       if (x86_pmu.event_attrs)
-               x86_pmu_events_group.attrs = x86_pmu.event_attrs;
-
        if (!x86_pmu.events_sysfs_show)
                x86_pmu_events_group.attrs = &empty_attrs;
-       else
-               filter_events(x86_pmu_events_group.attrs);
 
-       if (x86_pmu.cpu_events) {
-               struct attribute **tmp;
-
-               tmp = merge_attr(x86_pmu_events_group.attrs, x86_pmu.cpu_events);
-               if (!WARN_ON(!tmp))
-                       x86_pmu_events_group.attrs = tmp;
-       }
-
-       if (x86_pmu.attrs) {
-               struct attribute **tmp;
-
-               tmp = merge_attr(x86_pmu_attr_group.attrs, x86_pmu.attrs);
-               if (!WARN_ON(!tmp))
-                       x86_pmu_attr_group.attrs = tmp;
-       }
+       pmu.attr_update = x86_pmu.attr_update;
 
        pr_info("... version:                %d\n",     x86_pmu.version);
        pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
index a5436ce..71001f0 100644 (file)
@@ -3897,8 +3897,6 @@ static __initconst const struct x86_pmu core_pmu = {
        .check_period           = intel_pmu_check_period,
 };
 
-static struct attribute *intel_pmu_attrs[];
-
 static __initconst const struct x86_pmu intel_pmu = {
        .name                   = "Intel",
        .handle_irq             = intel_pmu_handle_irq,
@@ -3930,8 +3928,6 @@ static __initconst const struct x86_pmu intel_pmu = {
        .format_attrs           = intel_arch3_formats_attr,
        .events_sysfs_show      = intel_event_sysfs_show,
 
-       .attrs                  = intel_pmu_attrs,
-
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
@@ -4274,13 +4270,6 @@ static struct attribute *icl_tsx_events_attrs[] = {
        NULL,
 };
 
-static __init struct attribute **get_icl_events_attrs(void)
-{
-       return boot_cpu_has(X86_FEATURE_RTM) ?
-               merge_attr(icl_events_attrs, icl_tsx_events_attrs) :
-               icl_events_attrs;
-}
-
 static ssize_t freeze_on_smi_show(struct device *cdev,
                                  struct device_attribute *attr,
                                  char *buf)
@@ -4406,33 +4395,90 @@ static struct attribute *intel_pmu_attrs[] = {
        NULL,
 };
 
-static __init struct attribute **
-get_events_attrs(struct attribute **base,
-                struct attribute **mem,
-                struct attribute **tsx)
+static umode_t
+tsx_is_visible(struct kobject *kobj, struct attribute *attr, int i)
 {
-       struct attribute **attrs = base;
-       struct attribute **old;
+       return boot_cpu_has(X86_FEATURE_RTM) ? attr->mode : 0;
+}
 
-       if (mem && x86_pmu.pebs)
-               attrs = merge_attr(attrs, mem);
+static umode_t
+pebs_is_visible(struct kobject *kobj, struct attribute *attr, int i)
+{
+       return x86_pmu.pebs ? attr->mode : 0;
+}
 
-       if (tsx && boot_cpu_has(X86_FEATURE_RTM)) {
-               old = attrs;
-               attrs = merge_attr(attrs, tsx);
-               if (old != base)
-                       kfree(old);
-       }
+static umode_t
+lbr_is_visible(struct kobject *kobj, struct attribute *attr, int i)
+{
+       return x86_pmu.lbr_nr ? attr->mode : 0;
+}
 
-       return attrs;
+static umode_t
+exra_is_visible(struct kobject *kobj, struct attribute *attr, int i)
+{
+       return x86_pmu.version >= 2 ? attr->mode : 0;
 }
 
+static struct attribute_group group_events_td  = {
+       .name = "events",
+};
+
+static struct attribute_group group_events_mem = {
+       .name       = "events",
+       .is_visible = pebs_is_visible,
+};
+
+static struct attribute_group group_events_tsx = {
+       .name       = "events",
+       .is_visible = tsx_is_visible,
+};
+
+static struct attribute_group group_caps_gen = {
+       .name  = "caps",
+       .attrs = intel_pmu_caps_attrs,
+};
+
+static struct attribute_group group_caps_lbr = {
+       .name       = "caps",
+       .attrs      = lbr_attrs,
+       .is_visible = lbr_is_visible,
+};
+
+static struct attribute_group group_format_extra = {
+       .name       = "format",
+       .is_visible = exra_is_visible,
+};
+
+static struct attribute_group group_format_extra_skl = {
+       .name       = "format",
+       .is_visible = exra_is_visible,
+};
+
+static struct attribute_group group_default = {
+       .attrs = intel_pmu_attrs,
+};
+
+static const struct attribute_group *attr_update[] = {
+       &group_events_td,
+       &group_events_mem,
+       &group_events_tsx,
+       &group_caps_gen,
+       &group_caps_lbr,
+       &group_format_extra,
+       &group_format_extra_skl,
+       &group_default,
+       NULL,
+};
+
+static struct attribute *empty_attrs;
+
 __init int intel_pmu_init(void)
 {
-       struct attribute **extra_attr = NULL;
-       struct attribute **mem_attr = NULL;
-       struct attribute **tsx_attr = NULL;
-       struct attribute **to_free = NULL;
+       struct attribute **extra_skl_attr = &empty_attrs;
+       struct attribute **extra_attr = &empty_attrs;
+       struct attribute **td_attr    = &empty_attrs;
+       struct attribute **mem_attr   = &empty_attrs;
+       struct attribute **tsx_attr   = &empty_attrs;
        union cpuid10_edx edx;
        union cpuid10_eax eax;
        union cpuid10_ebx ebx;
@@ -4596,7 +4642,7 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
                x86_pmu.extra_regs = intel_slm_extra_regs;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.cpu_events = slm_events_attrs;
+               td_attr = slm_events_attrs;
                extra_attr = slm_format_attr;
                pr_cont("Silvermont events, ");
                name = "silvermont";
@@ -4624,7 +4670,7 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.lbr_pt_coexist = true;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.cpu_events = glm_events_attrs;
+               td_attr = glm_events_attrs;
                extra_attr = slm_format_attr;
                pr_cont("Goldmont events, ");
                name = "goldmont";
@@ -4651,7 +4697,7 @@ __init int intel_pmu_init(void)
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_PEBS_ALL;
                x86_pmu.get_event_constraints = glp_get_event_constraints;
-               x86_pmu.cpu_events = glm_events_attrs;
+               td_attr = glm_events_attrs;
                /* Goldmont Plus has 4-wide pipeline */
                event_attr_td_total_slots_scale_glm.event_str = "4";
                extra_attr = slm_format_attr;
@@ -4740,7 +4786,7 @@ __init int intel_pmu_init(void)
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
-               x86_pmu.cpu_events = snb_events_attrs;
+               td_attr  = snb_events_attrs;
                mem_attr = snb_mem_events_attrs;
 
                /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
@@ -4781,7 +4827,7 @@ __init int intel_pmu_init(void)
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
-               x86_pmu.cpu_events = snb_events_attrs;
+               td_attr  = snb_events_attrs;
                mem_attr = snb_mem_events_attrs;
 
                /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
@@ -4818,10 +4864,10 @@ __init int intel_pmu_init(void)
 
                x86_pmu.hw_config = hsw_hw_config;
                x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
                x86_pmu.lbr_double_abort = true;
                extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
                        hsw_format_attr : nhm_format_attr;
+               td_attr  = hsw_events_attrs;
                mem_attr = hsw_mem_events_attrs;
                tsx_attr = hsw_tsx_events_attrs;
                pr_cont("Haswell events, ");
@@ -4860,10 +4906,10 @@ __init int intel_pmu_init(void)
 
                x86_pmu.hw_config = hsw_hw_config;
                x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
                x86_pmu.limit_period = bdw_limit_period;
                extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
                        hsw_format_attr : nhm_format_attr;
+               td_attr  = hsw_events_attrs;
                mem_attr = hsw_mem_events_attrs;
                tsx_attr = hsw_tsx_events_attrs;
                pr_cont("Broadwell events, ");
@@ -4920,9 +4966,8 @@ __init int intel_pmu_init(void)
                x86_pmu.get_event_constraints = hsw_get_event_constraints;
                extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
                        hsw_format_attr : nhm_format_attr;
-               extra_attr = merge_attr(extra_attr, skl_format_attr);
-               to_free = extra_attr;
-               x86_pmu.cpu_events = hsw_events_attrs;
+               extra_skl_attr = skl_format_attr;
+               td_attr  = hsw_events_attrs;
                mem_attr = hsw_mem_events_attrs;
                tsx_attr = hsw_tsx_events_attrs;
                intel_pmu_pebs_data_source_skl(
@@ -4959,8 +5004,9 @@ __init int intel_pmu_init(void)
                x86_pmu.get_event_constraints = icl_get_event_constraints;
                extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
                        hsw_format_attr : nhm_format_attr;
-               extra_attr = merge_attr(extra_attr, skl_format_attr);
-               x86_pmu.cpu_events = get_icl_events_attrs();
+               extra_skl_attr = skl_format_attr;
+               mem_attr = icl_events_attrs;
+               tsx_attr = icl_tsx_events_attrs;
                x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xca, .umask=0x02);
                x86_pmu.lbr_pt_coexist = true;
                intel_pmu_pebs_data_source_skl(false);
@@ -4988,14 +5034,14 @@ __init int intel_pmu_init(void)
 
        snprintf(pmu_name_str, sizeof(pmu_name_str), "%s", name);
 
-       if (version >= 2 && extra_attr) {
-               x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
-                                                 extra_attr);
-               WARN_ON(!x86_pmu.format_attrs);
-       }
 
-       x86_pmu.cpu_events = get_events_attrs(x86_pmu.cpu_events,
-                                             mem_attr, tsx_attr);
+       group_events_td.attrs  = td_attr;
+       group_events_mem.attrs = mem_attr;
+       group_events_tsx.attrs = tsx_attr;
+       group_format_extra.attrs = extra_attr;
+       group_format_extra_skl.attrs = extra_skl_attr;
+
+       x86_pmu.attr_update = attr_update;
 
        if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
                WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
@@ -5043,12 +5089,8 @@ __init int intel_pmu_init(void)
                        x86_pmu.lbr_nr = 0;
        }
 
-       x86_pmu.caps_attrs = intel_pmu_caps_attrs;
-
-       if (x86_pmu.lbr_nr) {
-               x86_pmu.caps_attrs = merge_attr(x86_pmu.caps_attrs, lbr_attrs);
+       if (x86_pmu.lbr_nr)
                pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
-       }
 
        /*
         * Access extra MSR may cause #GP under certain circumstances.
@@ -5078,7 +5120,6 @@ __init int intel_pmu_init(void)
        if (x86_pmu.counter_freezing)
                x86_pmu.handle_irq = intel_pmu_handle_irq_v4;
 
-       kfree(to_free);
        return 0;
 }
 
index 6072f92..267d7f8 100644 (file)
@@ -302,7 +302,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
                        return -EINVAL;
                event->hw.event_base = pkg_msr[cfg].msr;
                cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
-                                     topology_core_cpumask(event->cpu));
+                                     topology_die_cpumask(event->cpu));
        } else {
                return -ENOENT;
        }
@@ -385,7 +385,7 @@ static int cstate_cpu_exit(unsigned int cpu)
        if (has_cstate_pkg &&
            cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) {
 
-               target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+               target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
                /* Migrate events if there is a valid target */
                if (target < nr_cpu_ids) {
                        cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
@@ -414,7 +414,7 @@ static int cstate_cpu_init(unsigned int cpu)
         * in the package cpu mask as the designated reader.
         */
        target = cpumask_any_and(&cstate_pkg_cpu_mask,
-                                topology_core_cpumask(cpu));
+                                topology_die_cpumask(cpu));
        if (has_cstate_pkg && target >= nr_cpu_ids)
                cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
 
@@ -663,7 +663,13 @@ static int __init cstate_init(void)
        }
 
        if (has_cstate_pkg) {
-               err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
+               if (topology_max_die_per_package() > 1) {
+                       err = perf_pmu_register(&cstate_pkg_pmu,
+                                               "cstate_die", -1);
+               } else {
+                       err = perf_pmu_register(&cstate_pkg_pmu,
+                                               cstate_pkg_pmu.name, -1);
+               }
                if (err) {
                        has_cstate_pkg = false;
                        pr_info("Failed to register cstate pkg pmu\n");
index 26c03f5..8c7ecde 100644 (file)
@@ -149,7 +149,7 @@ struct rapl_pmu {
 
 struct rapl_pmus {
        struct pmu              pmu;
-       unsigned int            maxpkg;
+       unsigned int            maxdie;
        struct rapl_pmu         *pmus[];
 };
 
@@ -162,13 +162,13 @@ static u64 rapl_timer_ms;
 
 static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
 {
-       unsigned int pkgid = topology_logical_package_id(cpu);
+       unsigned int dieid = topology_logical_die_id(cpu);
 
        /*
         * The unsigned check also catches the '-1' return value for non
         * existent mappings in the topology map.
         */
-       return pkgid < rapl_pmus->maxpkg ? rapl_pmus->pmus[pkgid] : NULL;
+       return dieid < rapl_pmus->maxdie ? rapl_pmus->pmus[dieid] : NULL;
 }
 
 static inline u64 rapl_read_counter(struct perf_event *event)
@@ -572,7 +572,7 @@ static int rapl_cpu_offline(unsigned int cpu)
 
        pmu->cpu = -1;
        /* Find a new cpu to collect rapl events */
-       target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+       target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
 
        /* Migrate rapl events to the new target */
        if (target < nr_cpu_ids) {
@@ -599,14 +599,14 @@ static int rapl_cpu_online(unsigned int cpu)
                pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
                rapl_hrtimer_init(pmu);
 
-               rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
+               rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu;
        }
 
        /*
         * Check if there is an online cpu in the package which collects rapl
         * events already.
         */
-       target = cpumask_any_and(&rapl_cpu_mask, topology_core_cpumask(cpu));
+       target = cpumask_any_and(&rapl_cpu_mask, topology_die_cpumask(cpu));
        if (target < nr_cpu_ids)
                return 0;
 
@@ -669,22 +669,22 @@ static void cleanup_rapl_pmus(void)
 {
        int i;
 
-       for (i = 0; i < rapl_pmus->maxpkg; i++)
+       for (i = 0; i < rapl_pmus->maxdie; i++)
                kfree(rapl_pmus->pmus[i]);
        kfree(rapl_pmus);
 }
 
 static int __init init_rapl_pmus(void)
 {
-       int maxpkg = topology_max_packages();
+       int maxdie = topology_max_packages() * topology_max_die_per_package();
        size_t size;
 
-       size = sizeof(*rapl_pmus) + maxpkg * sizeof(struct rapl_pmu *);
+       size = sizeof(*rapl_pmus) + maxdie * sizeof(struct rapl_pmu *);
        rapl_pmus = kzalloc(size, GFP_KERNEL);
        if (!rapl_pmus)
                return -ENOMEM;
 
-       rapl_pmus->maxpkg               = maxpkg;
+       rapl_pmus->maxdie               = maxdie;
        rapl_pmus->pmu.attr_groups      = rapl_attr_groups;
        rapl_pmus->pmu.task_ctx_nr      = perf_invalid_context;
        rapl_pmus->pmu.event_init       = rapl_pmu_event_init;
index 089bfcd..6094c8d 100644 (file)
@@ -15,7 +15,7 @@ struct pci_driver *uncore_pci_driver;
 DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
 struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
 struct pci_extra_dev *uncore_extra_pci_dev;
-static int max_packages;
+static int max_dies;
 
 /* mask of cpus that collect uncore events */
 static cpumask_t uncore_cpu_mask;
@@ -101,13 +101,13 @@ ssize_t uncore_event_show(struct kobject *kobj,
 
 struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
 {
-       unsigned int pkgid = topology_logical_package_id(cpu);
+       unsigned int dieid = topology_logical_die_id(cpu);
 
        /*
         * The unsigned check also catches the '-1' return value for non
         * existent mappings in the topology map.
         */
-       return pkgid < max_packages ? pmu->boxes[pkgid] : NULL;
+       return dieid < max_dies ? pmu->boxes[dieid] : NULL;
 }
 
 u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
@@ -312,7 +312,7 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
        uncore_pmu_init_hrtimer(box);
        box->cpu = -1;
        box->pci_phys_id = -1;
-       box->pkgid = -1;
+       box->dieid = -1;
 
        /* set default hrtimer timeout */
        box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
@@ -827,10 +827,10 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
 
 static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
 {
-       int pkg;
+       int die;
 
-       for (pkg = 0; pkg < max_packages; pkg++)
-               kfree(pmu->boxes[pkg]);
+       for (die = 0; die < max_dies; die++)
+               kfree(pmu->boxes[die]);
        kfree(pmu->boxes);
 }
 
@@ -867,7 +867,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
        if (!pmus)
                return -ENOMEM;
 
-       size = max_packages * sizeof(struct intel_uncore_box *);
+       size = max_dies * sizeof(struct intel_uncore_box *);
 
        for (i = 0; i < type->num_boxes; i++) {
                pmus[i].func_id = setid ? i : -1;
@@ -937,20 +937,21 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
        struct intel_uncore_type *type;
        struct intel_uncore_pmu *pmu = NULL;
        struct intel_uncore_box *box;
-       int phys_id, pkg, ret;
+       int phys_id, die, ret;
 
        phys_id = uncore_pcibus_to_physid(pdev->bus);
        if (phys_id < 0)
                return -ENODEV;
 
-       pkg = topology_phys_to_logical_pkg(phys_id);
-       if (pkg < 0)
+       die = (topology_max_die_per_package() > 1) ? phys_id :
+                                       topology_phys_to_logical_pkg(phys_id);
+       if (die < 0)
                return -EINVAL;
 
        if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
                int idx = UNCORE_PCI_DEV_IDX(id->driver_data);
 
-               uncore_extra_pci_dev[pkg].dev[idx] = pdev;
+               uncore_extra_pci_dev[die].dev[idx] = pdev;
                pci_set_drvdata(pdev, NULL);
                return 0;
        }
@@ -989,7 +990,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
                pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)];
        }
 
-       if (WARN_ON_ONCE(pmu->boxes[pkg] != NULL))
+       if (WARN_ON_ONCE(pmu->boxes[die] != NULL))
                return -EINVAL;
 
        box = uncore_alloc_box(type, NUMA_NO_NODE);
@@ -1003,13 +1004,13 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
 
        atomic_inc(&box->refcnt);
        box->pci_phys_id = phys_id;
-       box->pkgid = pkg;
+       box->dieid = die;
        box->pci_dev = pdev;
        box->pmu = pmu;
        uncore_box_init(box);
        pci_set_drvdata(pdev, box);
 
-       pmu->boxes[pkg] = box;
+       pmu->boxes[die] = box;
        if (atomic_inc_return(&pmu->activeboxes) > 1)
                return 0;
 
@@ -1017,7 +1018,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
        ret = uncore_pmu_register(pmu);
        if (ret) {
                pci_set_drvdata(pdev, NULL);
-               pmu->boxes[pkg] = NULL;
+               pmu->boxes[die] = NULL;
                uncore_box_exit(box);
                kfree(box);
        }
@@ -1028,16 +1029,17 @@ static void uncore_pci_remove(struct pci_dev *pdev)
 {
        struct intel_uncore_box *box;
        struct intel_uncore_pmu *pmu;
-       int i, phys_id, pkg;
+       int i, phys_id, die;
 
        phys_id = uncore_pcibus_to_physid(pdev->bus);
 
        box = pci_get_drvdata(pdev);
        if (!box) {
-               pkg = topology_phys_to_logical_pkg(phys_id);
+               die = (topology_max_die_per_package() > 1) ? phys_id :
+                                       topology_phys_to_logical_pkg(phys_id);
                for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
-                       if (uncore_extra_pci_dev[pkg].dev[i] == pdev) {
-                               uncore_extra_pci_dev[pkg].dev[i] = NULL;
+                       if (uncore_extra_pci_dev[die].dev[i] == pdev) {
+                               uncore_extra_pci_dev[die].dev[i] = NULL;
                                break;
                        }
                }
@@ -1050,7 +1052,7 @@ static void uncore_pci_remove(struct pci_dev *pdev)
                return;
 
        pci_set_drvdata(pdev, NULL);
-       pmu->boxes[box->pkgid] = NULL;
+       pmu->boxes[box->dieid] = NULL;
        if (atomic_dec_return(&pmu->activeboxes) == 0)
                uncore_pmu_unregister(pmu);
        uncore_box_exit(box);
@@ -1062,7 +1064,7 @@ static int __init uncore_pci_init(void)
        size_t size;
        int ret;
 
-       size = max_packages * sizeof(struct pci_extra_dev);
+       size = max_dies * sizeof(struct pci_extra_dev);
        uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
        if (!uncore_extra_pci_dev) {
                ret = -ENOMEM;
@@ -1109,11 +1111,11 @@ static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
 {
        struct intel_uncore_pmu *pmu = type->pmus;
        struct intel_uncore_box *box;
-       int i, pkg;
+       int i, die;
 
-       pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
+       die = topology_logical_die_id(old_cpu < 0 ? new_cpu : old_cpu);
        for (i = 0; i < type->num_boxes; i++, pmu++) {
-               box = pmu->boxes[pkg];
+               box = pmu->boxes[die];
                if (!box)
                        continue;
 
@@ -1146,13 +1148,13 @@ static int uncore_event_cpu_offline(unsigned int cpu)
        struct intel_uncore_type *type, **types = uncore_msr_uncores;
        struct intel_uncore_pmu *pmu;
        struct intel_uncore_box *box;
-       int i, pkg, target;
+       int i, die, target;
 
        /* Check if exiting cpu is used for collecting uncore events */
        if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
                goto unref;
        /* Find a new cpu to collect uncore events */
-       target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+       target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
 
        /* Migrate uncore events to the new target */
        if (target < nr_cpu_ids)
@@ -1165,12 +1167,12 @@ static int uncore_event_cpu_offline(unsigned int cpu)
 
 unref:
        /* Clear the references */
-       pkg = topology_logical_package_id(cpu);
+       die = topology_logical_die_id(cpu);
        for (; *types; types++) {
                type = *types;
                pmu = type->pmus;
                for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       box = pmu->boxes[pkg];
+                       box = pmu->boxes[die];
                        if (box && atomic_dec_return(&box->refcnt) == 0)
                                uncore_box_exit(box);
                }
@@ -1179,7 +1181,7 @@ unref:
 }
 
 static int allocate_boxes(struct intel_uncore_type **types,
-                        unsigned int pkg, unsigned int cpu)
+                        unsigned int die, unsigned int cpu)
 {
        struct intel_uncore_box *box, *tmp;
        struct intel_uncore_type *type;
@@ -1192,20 +1194,20 @@ static int allocate_boxes(struct intel_uncore_type **types,
                type = *types;
                pmu = type->pmus;
                for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       if (pmu->boxes[pkg])
+                       if (pmu->boxes[die])
                                continue;
                        box = uncore_alloc_box(type, cpu_to_node(cpu));
                        if (!box)
                                goto cleanup;
                        box->pmu = pmu;
-                       box->pkgid = pkg;
+                       box->dieid = die;
                        list_add(&box->active_list, &allocated);
                }
        }
        /* Install them in the pmus */
        list_for_each_entry_safe(box, tmp, &allocated, active_list) {
                list_del_init(&box->active_list);
-               box->pmu->boxes[pkg] = box;
+               box->pmu->boxes[die] = box;
        }
        return 0;
 
@@ -1222,10 +1224,10 @@ static int uncore_event_cpu_online(unsigned int cpu)
        struct intel_uncore_type *type, **types = uncore_msr_uncores;
        struct intel_uncore_pmu *pmu;
        struct intel_uncore_box *box;
-       int i, ret, pkg, target;
+       int i, ret, die, target;
 
-       pkg = topology_logical_package_id(cpu);
-       ret = allocate_boxes(types, pkg, cpu);
+       die = topology_logical_die_id(cpu);
+       ret = allocate_boxes(types, die, cpu);
        if (ret)
                return ret;
 
@@ -1233,7 +1235,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
                type = *types;
                pmu = type->pmus;
                for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       box = pmu->boxes[pkg];
+                       box = pmu->boxes[die];
                        if (box && atomic_inc_return(&box->refcnt) == 1)
                                uncore_box_init(box);
                }
@@ -1243,7 +1245,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
         * Check if there is an online cpu in the package
         * which collects uncore events already.
         */
-       target = cpumask_any_and(&uncore_cpu_mask, topology_core_cpumask(cpu));
+       target = cpumask_any_and(&uncore_cpu_mask, topology_die_cpumask(cpu));
        if (target < nr_cpu_ids)
                return 0;
 
@@ -1419,7 +1421,7 @@ static int __init intel_uncore_init(void)
        if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return -ENODEV;
 
-       max_packages = topology_max_packages();
+       max_dies = topology_max_packages() * topology_max_die_per_package();
 
        uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
        if (uncore_init->pci_init) {
index 79eb2e2..33aba25 100644 (file)
@@ -108,7 +108,7 @@ struct intel_uncore_extra_reg {
 
 struct intel_uncore_box {
        int pci_phys_id;
-       int pkgid;      /* Logical package ID */
+       int dieid;      /* Logical die ID */
        int n_active;   /* number of active events */
        int n_events;
        int cpu;        /* cpu to collect events */
@@ -467,7 +467,7 @@ static inline void uncore_box_exit(struct intel_uncore_box *box)
 
 static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
 {
-       return (box->pkgid < 0);
+       return (box->dieid < 0);
 }
 
 static inline struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
index f843181..b0ca4f8 100644 (file)
@@ -3,27 +3,29 @@
 #include "uncore.h"
 
 /* Uncore IMC PCI IDs */
-#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
-#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
-#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
-#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
-#define PCI_DEVICE_ID_INTEL_HSW_U_IMC  0x0a04
-#define PCI_DEVICE_ID_INTEL_BDW_IMC    0x1604
-#define PCI_DEVICE_ID_INTEL_SKL_U_IMC  0x1904
-#define PCI_DEVICE_ID_INTEL_SKL_Y_IMC  0x190c
-#define PCI_DEVICE_ID_INTEL_SKL_HD_IMC 0x1900
-#define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC 0x1910
-#define PCI_DEVICE_ID_INTEL_SKL_SD_IMC 0x190f
-#define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC 0x191f
-#define PCI_DEVICE_ID_INTEL_KBL_Y_IMC  0x590c
-#define PCI_DEVICE_ID_INTEL_KBL_U_IMC  0x5904
-#define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC 0x5914
-#define PCI_DEVICE_ID_INTEL_KBL_SD_IMC 0x590f
-#define PCI_DEVICE_ID_INTEL_KBL_SQ_IMC 0x591f
-#define PCI_DEVICE_ID_INTEL_CFL_2U_IMC 0x3ecc
-#define PCI_DEVICE_ID_INTEL_CFL_4U_IMC 0x3ed0
-#define PCI_DEVICE_ID_INTEL_CFL_4H_IMC 0x3e10
-#define PCI_DEVICE_ID_INTEL_CFL_6H_IMC 0x3ec4
+#define PCI_DEVICE_ID_INTEL_SNB_IMC            0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC            0x0154
+#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC         0x0150
+#define PCI_DEVICE_ID_INTEL_HSW_IMC            0x0c00
+#define PCI_DEVICE_ID_INTEL_HSW_U_IMC          0x0a04
+#define PCI_DEVICE_ID_INTEL_BDW_IMC            0x1604
+#define PCI_DEVICE_ID_INTEL_SKL_U_IMC          0x1904
+#define PCI_DEVICE_ID_INTEL_SKL_Y_IMC          0x190c
+#define PCI_DEVICE_ID_INTEL_SKL_HD_IMC         0x1900
+#define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC         0x1910
+#define PCI_DEVICE_ID_INTEL_SKL_SD_IMC         0x190f
+#define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC         0x191f
+#define PCI_DEVICE_ID_INTEL_KBL_Y_IMC          0x590c
+#define PCI_DEVICE_ID_INTEL_KBL_U_IMC          0x5904
+#define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC         0x5914
+#define PCI_DEVICE_ID_INTEL_KBL_SD_IMC         0x590f
+#define PCI_DEVICE_ID_INTEL_KBL_SQ_IMC         0x591f
+#define PCI_DEVICE_ID_INTEL_KBL_HQ_IMC         0x5910
+#define PCI_DEVICE_ID_INTEL_KBL_WQ_IMC         0x5918
+#define PCI_DEVICE_ID_INTEL_CFL_2U_IMC         0x3ecc
+#define PCI_DEVICE_ID_INTEL_CFL_4U_IMC         0x3ed0
+#define PCI_DEVICE_ID_INTEL_CFL_4H_IMC         0x3e10
+#define PCI_DEVICE_ID_INTEL_CFL_6H_IMC         0x3ec4
 #define PCI_DEVICE_ID_INTEL_CFL_2S_D_IMC       0x3e0f
 #define PCI_DEVICE_ID_INTEL_CFL_4S_D_IMC       0x3e1f
 #define PCI_DEVICE_ID_INTEL_CFL_6S_D_IMC       0x3ec2
 #define PCI_DEVICE_ID_INTEL_CFL_4S_S_IMC       0x3e33
 #define PCI_DEVICE_ID_INTEL_CFL_6S_S_IMC       0x3eca
 #define PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC       0x3e32
+#define PCI_DEVICE_ID_INTEL_AML_YD_IMC         0x590c
+#define PCI_DEVICE_ID_INTEL_AML_YQ_IMC         0x590d
+#define PCI_DEVICE_ID_INTEL_WHL_UQ_IMC         0x3ed0
+#define PCI_DEVICE_ID_INTEL_WHL_4_UQ_IMC       0x3e34
+#define PCI_DEVICE_ID_INTEL_WHL_UD_IMC         0x3e35
 #define PCI_DEVICE_ID_INTEL_ICL_U_IMC          0x8a02
 #define PCI_DEVICE_ID_INTEL_ICL_U2_IMC         0x8a12
 
+
 /* SNB event control */
 #define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
 #define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
@@ -682,6 +690,14 @@ static const struct pci_device_id skl_uncore_pci_ids[] = {
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
        { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_HQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_WQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_2U_IMC),
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
@@ -737,6 +753,26 @@ static const struct pci_device_id skl_uncore_pci_ids[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC),
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AML_YD_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AML_YQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WHL_UQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WHL_4_UQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WHL_UD_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
        { /* end: all zeroes */ },
 };
 
@@ -807,6 +843,8 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
        IMC_DEV(KBL_UQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U Quad Core */
        IMC_DEV(KBL_SD_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core S Dual Core */
        IMC_DEV(KBL_SQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core S Quad Core */
+       IMC_DEV(KBL_HQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core H Quad Core */
+       IMC_DEV(KBL_WQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core S 4 cores Work Station */
        IMC_DEV(CFL_2U_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core U 2 Cores */
        IMC_DEV(CFL_4U_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core U 4 Cores */
        IMC_DEV(CFL_4H_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core H 4 Cores */
@@ -821,6 +859,11 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
        IMC_DEV(CFL_4S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 4 Cores Server */
        IMC_DEV(CFL_6S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 6 Cores Server */
        IMC_DEV(CFL_8S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 8 Cores Server */
+       IMC_DEV(AML_YD_IMC, &skl_uncore_pci_driver),    /* 8th Gen Core Y Mobile Dual Core */
+       IMC_DEV(AML_YQ_IMC, &skl_uncore_pci_driver),    /* 8th Gen Core Y Mobile Quad Core */
+       IMC_DEV(WHL_UQ_IMC, &skl_uncore_pci_driver),    /* 8th Gen Core U Mobile Quad Core */
+       IMC_DEV(WHL_4_UQ_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core U Mobile Quad Core */
+       IMC_DEV(WHL_UD_IMC, &skl_uncore_pci_driver),    /* 8th Gen Core U Mobile Dual Core */
        IMC_DEV(ICL_U_IMC, &icl_uncore_pci_driver),     /* 10th Gen Core Mobile */
        IMC_DEV(ICL_U2_IMC, &icl_uncore_pci_driver),    /* 10th Gen Core Mobile */
        {  /* end marker */ }
index b10e043..bbe89bc 100644 (file)
@@ -1058,8 +1058,8 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve
 
        if (reg1->idx != EXTRA_REG_NONE) {
                int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
-               int pkg = box->pkgid;
-               struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx];
+               int die = box->dieid;
+               struct pci_dev *filter_pdev = uncore_extra_pci_dev[die].dev[idx];
 
                if (filter_pdev) {
                        pci_write_config_dword(filter_pdev, reg1->reg,
index a6ac2f4..9bcec3f 100644 (file)
@@ -631,14 +631,11 @@ struct x86_pmu {
        int             attr_rdpmc_broken;
        int             attr_rdpmc;
        struct attribute **format_attrs;
-       struct attribute **event_attrs;
-       struct attribute **caps_attrs;
 
        ssize_t         (*events_sysfs_show)(char *page, u64 config);
-       struct attribute **cpu_events;
+       const struct attribute_group **attr_update;
 
        unsigned long   attr_freeze_on_smi;
-       struct attribute **attrs;
 
        /*
         * CPU Hotplug hooks
@@ -905,8 +902,6 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
 ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
 ssize_t intel_event_sysfs_show(char *page, u64 config);
 
-struct attribute **merge_attr(struct attribute **a, struct attribute **b);
-
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
                          char *page);
 ssize_t events_ht_sysfs_show(struct device *dev, struct device_attribute *attr,
index c34a35c..6aba36b 100644 (file)
@@ -105,7 +105,7 @@ struct cpuinfo_x86 {
        int                     x86_power;
        unsigned long           loops_per_jiffy;
        /* cpuid returned max cores value: */
-       u16                      x86_max_cores;
+       u16                     x86_max_cores;
        u16                     apicid;
        u16                     initial_apicid;
        u16                     x86_clflush_size;
@@ -117,6 +117,8 @@ struct cpuinfo_x86 {
        u16                     logical_proc_id;
        /* Core id: */
        u16                     cpu_core_id;
+       u16                     cpu_die_id;
+       u16                     logical_die_id;
        /* Index into per_cpu list: */
        u16                     cpu_index;
        u32                     microcode;
index da545df..b673a22 100644 (file)
@@ -23,6 +23,7 @@ extern unsigned int num_processors;
 
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
+DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
 /* cpus sharing the last level cache: */
 DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
index 453cf38..4b14d23 100644 (file)
@@ -106,15 +106,25 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);
 
 #define topology_logical_package_id(cpu)       (cpu_data(cpu).logical_proc_id)
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).phys_proc_id)
+#define topology_logical_die_id(cpu)           (cpu_data(cpu).logical_die_id)
+#define topology_die_id(cpu)                   (cpu_data(cpu).cpu_die_id)
 #define topology_core_id(cpu)                  (cpu_data(cpu).cpu_core_id)
 
 #ifdef CONFIG_SMP
+#define topology_die_cpumask(cpu)              (per_cpu(cpu_die_map, cpu))
 #define topology_core_cpumask(cpu)             (per_cpu(cpu_core_map, cpu))
 #define topology_sibling_cpumask(cpu)          (per_cpu(cpu_sibling_map, cpu))
 
 extern unsigned int __max_logical_packages;
 #define topology_max_packages()                        (__max_logical_packages)
 
+extern unsigned int __max_die_per_package;
+
+static inline int topology_max_die_per_package(void)
+{
+       return __max_die_per_package;
+}
+
 extern int __max_smt_threads;
 
 static inline int topology_max_smt_threads(void)
@@ -123,14 +133,21 @@ static inline int topology_max_smt_threads(void)
 }
 
 int topology_update_package_map(unsigned int apicid, unsigned int cpu);
+int topology_update_die_map(unsigned int dieid, unsigned int cpu);
 int topology_phys_to_logical_pkg(unsigned int pkg);
+int topology_phys_to_logical_die(unsigned int die, unsigned int cpu);
 bool topology_is_primary_thread(unsigned int cpu);
 bool topology_smt_supported(void);
 #else
 #define topology_max_packages()                        (1)
 static inline int
 topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
+static inline int
+topology_update_die_map(unsigned int dieid, unsigned int cpu) { return 0; }
 static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
+static inline int topology_phys_to_logical_die(unsigned int die,
+               unsigned int cpu) { return 0; }
+static inline int topology_max_die_per_package(void) { return 1; }
 static inline int topology_max_smt_threads(void) { return 1; }
 static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
 static inline bool topology_smt_supported(void) { return false; }
index 2c57fff..9375b3a 100644 (file)
@@ -1299,6 +1299,7 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
                       cpu, apicid, c->initial_apicid);
        }
        BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
+       BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
 #else
        c->logical_proc_id = 0;
 #endif
index 8f6c784..ee48c3f 100644 (file)
 /* leaf 0xb SMT level */
 #define SMT_LEVEL      0
 
-/* leaf 0xb sub-leaf types */
+/* extended topology sub-leaf types */
 #define INVALID_TYPE   0
 #define SMT_TYPE       1
 #define CORE_TYPE      2
+#define DIE_TYPE       5
 
 #define LEAFB_SUBTYPE(ecx)             (((ecx) >> 8) & 0xff)
 #define BITS_SHIFT_NEXT_LEVEL(eax)     ((eax) & 0x1f)
 #define LEVEL_MAX_SIBLINGS(ebx)                ((ebx) & 0xffff)
 
-int detect_extended_topology_early(struct cpuinfo_x86 *c)
-{
 #ifdef CONFIG_SMP
+unsigned int __max_die_per_package __read_mostly = 1;
+EXPORT_SYMBOL(__max_die_per_package);
+
+/*
+ * Check if given CPUID extended toplogy "leaf" is implemented
+ */
+static int check_extended_topology_leaf(int leaf)
+{
        unsigned int eax, ebx, ecx, edx;
 
-       if (c->cpuid_level < 0xb)
+       cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+
+       if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
                return -1;
 
-       cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+       return 0;
+}
+/*
+ * Return best CPUID Extended Toplogy Leaf supported
+ */
+static int detect_extended_topology_leaf(struct cpuinfo_x86 *c)
+{
+       if (c->cpuid_level >= 0x1f) {
+               if (check_extended_topology_leaf(0x1f) == 0)
+                       return 0x1f;
+       }
 
-       /*
-        * check if the cpuid leaf 0xb is actually implemented.
-        */
-       if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
+       if (c->cpuid_level >= 0xb) {
+               if (check_extended_topology_leaf(0xb) == 0)
+                       return 0xb;
+       }
+
+       return -1;
+}
+#endif
+
+int detect_extended_topology_early(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_SMP
+       unsigned int eax, ebx, ecx, edx;
+       int leaf;
+
+       leaf = detect_extended_topology_leaf(c);
+       if (leaf < 0)
                return -1;
 
        set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
 
+       cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
        /*
         * initial apic id, which also represents 32-bit extended x2apic id.
         */
@@ -52,7 +85,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
 }
 
 /*
- * Check for extended topology enumeration cpuid leaf 0xb and if it
+ * Check for extended topology enumeration cpuid leaf, and if it
  * exists, use it for populating initial_apicid and cpu topology
  * detection.
  */
@@ -60,22 +93,28 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        unsigned int eax, ebx, ecx, edx, sub_index;
-       unsigned int ht_mask_width, core_plus_mask_width;
+       unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
        unsigned int core_select_mask, core_level_siblings;
+       unsigned int die_select_mask, die_level_siblings;
+       int leaf;
 
-       if (detect_extended_topology_early(c) < 0)
+       leaf = detect_extended_topology_leaf(c);
+       if (leaf < 0)
                return -1;
 
        /*
         * Populate HT related information from sub-leaf level 0.
         */
-       cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+       cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+       c->initial_apicid = edx;
        core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
        core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
+       die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
 
        sub_index = 1;
        do {
-               cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
+               cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
 
                /*
                 * Check for the Core type in the implemented sub leaves.
@@ -83,23 +122,34 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
                if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
                        core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
                        core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
-                       break;
+                       die_level_siblings = core_level_siblings;
+                       die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
+               }
+               if (LEAFB_SUBTYPE(ecx) == DIE_TYPE) {
+                       die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
+                       die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
                }
 
                sub_index++;
        } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
 
        core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
-
-       c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width)
-                                                & core_select_mask;
-       c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width);
+       die_select_mask = (~(-1 << die_plus_mask_width)) >>
+                               core_plus_mask_width;
+
+       c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
+                               ht_mask_width) & core_select_mask;
+       c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
+                               core_plus_mask_width) & die_select_mask;
+       c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
+                               die_plus_mask_width);
        /*
         * Reinit the apicid, now that we have extended initial_apicid.
         */
        c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
 
        c->x86_max_cores = (core_level_siblings / smp_num_siblings);
+       __max_die_per_package = (die_level_siblings / core_level_siblings);
 #endif
        return 0;
 }
index 362dd89..e4f4f3c 100644 (file)
@@ -89,6 +89,10 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
 DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
 EXPORT_PER_CPU_SYMBOL(cpu_core_map);
 
+/* representing HT, core, and die siblings of each logical CPU */
+DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
+EXPORT_PER_CPU_SYMBOL(cpu_die_map);
+
 DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 
 /* Per CPU bogomips and other parameters */
@@ -99,6 +103,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
 unsigned int __max_logical_packages __read_mostly;
 EXPORT_SYMBOL(__max_logical_packages);
 static unsigned int logical_packages __read_mostly;
+static unsigned int logical_die __read_mostly;
 
 /* Maximum number of SMT threads on any online core */
 int __read_mostly __max_smt_threads = 1;
@@ -300,6 +305,26 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg)
        return -1;
 }
 EXPORT_SYMBOL(topology_phys_to_logical_pkg);
+/**
+ * topology_phys_to_logical_die - Map a physical die id to logical
+ *
+ * Returns logical die id or -1 if not found
+ */
+int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu)
+{
+       int cpu;
+       int proc_id = cpu_data(cur_cpu).phys_proc_id;
+
+       for_each_possible_cpu(cpu) {
+               struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+               if (c->initialized && c->cpu_die_id == die_id &&
+                   c->phys_proc_id == proc_id)
+                       return c->logical_die_id;
+       }
+       return -1;
+}
+EXPORT_SYMBOL(topology_phys_to_logical_die);
 
 /**
  * topology_update_package_map - Update the physical to logical package map
@@ -324,6 +349,29 @@ found:
        cpu_data(cpu).logical_proc_id = new;
        return 0;
 }
+/**
+ * topology_update_die_map - Update the physical to logical die map
+ * @die:       The die id as retrieved via CPUID
+ * @cpu:       The cpu for which this is updated
+ */
+int topology_update_die_map(unsigned int die, unsigned int cpu)
+{
+       int new;
+
+       /* Already available somewhere? */
+       new = topology_phys_to_logical_die(die, cpu);
+       if (new >= 0)
+               goto found;
+
+       new = logical_die++;
+       if (new != die) {
+               pr_info("CPU %u Converting physical %u to logical die %u\n",
+                       cpu, die, new);
+       }
+found:
+       cpu_data(cpu).logical_die_id = new;
+       return 0;
+}
 
 void __init smp_store_boot_cpu_info(void)
 {
@@ -333,6 +381,7 @@ void __init smp_store_boot_cpu_info(void)
        *c = boot_cpu_data;
        c->cpu_index = id;
        topology_update_package_map(c->phys_proc_id, id);
+       topology_update_die_map(c->cpu_die_id, id);
        c->initialized = true;
 }
 
@@ -387,6 +436,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
                int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
 
                if (c->phys_proc_id == o->phys_proc_id &&
+                   c->cpu_die_id == o->cpu_die_id &&
                    per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) {
                        if (c->cpu_core_id == o->cpu_core_id)
                                return topology_sane(c, o, "smt");
@@ -398,6 +448,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
                }
 
        } else if (c->phys_proc_id == o->phys_proc_id &&
+                  c->cpu_die_id == o->cpu_die_id &&
                   c->cpu_core_id == o->cpu_core_id) {
                return topology_sane(c, o, "smt");
        }
@@ -460,6 +511,15 @@ static bool match_pkg(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
        return false;
 }
 
+static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
+{
+       if ((c->phys_proc_id == o->phys_proc_id) &&
+               (c->cpu_die_id == o->cpu_die_id))
+               return true;
+       return false;
+}
+
+
 #if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC)
 static inline int x86_sched_itmt_flags(void)
 {
@@ -522,6 +582,7 @@ void set_cpu_sibling_map(int cpu)
                cpumask_set_cpu(cpu, topology_sibling_cpumask(cpu));
                cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
                cpumask_set_cpu(cpu, topology_core_cpumask(cpu));
+               cpumask_set_cpu(cpu, topology_die_cpumask(cpu));
                c->booted_cores = 1;
                return;
        }
@@ -570,6 +631,9 @@ void set_cpu_sibling_map(int cpu)
                }
                if (match_pkg(c, o) && !topology_same_node(c, o))
                        x86_has_numa_in_package = true;
+
+               if ((i == cpu) || (has_mp && match_die(c, o)))
+                       link_mask(topology_die_cpumask, cpu, i);
        }
 
        threads = cpumask_weight(topology_sibling_cpumask(cpu));
@@ -1174,6 +1238,7 @@ static __init void disable_smp(void)
                physid_set_mask_of_physid(0, &phys_cpu_present_map);
        cpumask_set_cpu(0, topology_sibling_cpumask(0));
        cpumask_set_cpu(0, topology_core_cpumask(0));
+       cpumask_set_cpu(0, topology_die_cpumask(0));
 }
 
 /*
@@ -1269,6 +1334,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        for_each_possible_cpu(i) {
                zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
                zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
+               zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL);
                zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
        }
 
@@ -1489,6 +1555,8 @@ static void remove_siblinginfo(int cpu)
                        cpu_data(sibling).booted_cores--;
        }
 
+       for_each_cpu(sibling, topology_die_cpumask(cpu))
+               cpumask_clear_cpu(cpu, topology_die_cpumask(sibling));
        for_each_cpu(sibling, topology_sibling_cpumask(cpu))
                cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
        for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
@@ -1496,6 +1564,7 @@ static void remove_siblinginfo(int cpu)
        cpumask_clear(cpu_llc_shared_mask(cpu));
        cpumask_clear(topology_sibling_cpumask(cpu));
        cpumask_clear(topology_core_cpumask(cpu));
+       cpumask_clear(topology_die_cpumask(cpu));
        c->cpu_core_id = 0;
        c->booted_cores = 0;
        cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
index 590fcf8..77d81c1 100644 (file)
@@ -251,6 +251,7 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus)
        for_each_possible_cpu(i) {
                zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
                zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
+               zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL);
                zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
        }
        set_cpu_sibling_map(0);
index 5fd9f16..4e033d4 100644 (file)
@@ -43,6 +43,9 @@ static ssize_t name##_list_show(struct device *dev,                   \
 define_id_show_func(physical_package_id);
 static DEVICE_ATTR_RO(physical_package_id);
 
+define_id_show_func(die_id);
+static DEVICE_ATTR_RO(die_id);
+
 define_id_show_func(core_id);
 static DEVICE_ATTR_RO(core_id);
 
@@ -50,10 +53,22 @@ define_siblings_show_func(thread_siblings, sibling_cpumask);
 static DEVICE_ATTR_RO(thread_siblings);
 static DEVICE_ATTR_RO(thread_siblings_list);
 
+define_siblings_show_func(core_cpus, sibling_cpumask);
+static DEVICE_ATTR_RO(core_cpus);
+static DEVICE_ATTR_RO(core_cpus_list);
+
 define_siblings_show_func(core_siblings, core_cpumask);
 static DEVICE_ATTR_RO(core_siblings);
 static DEVICE_ATTR_RO(core_siblings_list);
 
+define_siblings_show_func(die_cpus, die_cpumask);
+static DEVICE_ATTR_RO(die_cpus);
+static DEVICE_ATTR_RO(die_cpus_list);
+
+define_siblings_show_func(package_cpus, core_cpumask);
+static DEVICE_ATTR_RO(package_cpus);
+static DEVICE_ATTR_RO(package_cpus_list);
+
 #ifdef CONFIG_SCHED_BOOK
 define_id_show_func(book_id);
 static DEVICE_ATTR_RO(book_id);
@@ -72,11 +87,18 @@ static DEVICE_ATTR_RO(drawer_siblings_list);
 
 static struct attribute *default_attrs[] = {
        &dev_attr_physical_package_id.attr,
+       &dev_attr_die_id.attr,
        &dev_attr_core_id.attr,
        &dev_attr_thread_siblings.attr,
        &dev_attr_thread_siblings_list.attr,
+       &dev_attr_core_cpus.attr,
+       &dev_attr_core_cpus_list.attr,
        &dev_attr_core_siblings.attr,
        &dev_attr_core_siblings_list.attr,
+       &dev_attr_die_cpus.attr,
+       &dev_attr_die_cpus_list.attr,
+       &dev_attr_package_cpus.attr,
+       &dev_attr_package_cpus_list.attr,
 #ifdef CONFIG_SCHED_BOOK
        &dev_attr_book_id.attr,
        &dev_attr_book_siblings.attr,
index 4d0d6c8..fe6618e 100644 (file)
@@ -96,10 +96,10 @@ struct platform_data {
        struct device_attribute name_attr;
 };
 
-/* Keep track of how many package pointers we allocated in init() */
-static int max_packages __read_mostly;
-/* Array of package pointers. Serialized by cpu hotplug lock */
-static struct platform_device **pkg_devices;
+/* Keep track of how many zone pointers we allocated in init() */
+static int max_zones __read_mostly;
+/* Array of zone pointers. Serialized by cpu hotplug lock */
+static struct platform_device **zone_devices;
 
 static ssize_t show_label(struct device *dev,
                                struct device_attribute *devattr, char *buf)
@@ -422,10 +422,10 @@ static int chk_ucode_version(unsigned int cpu)
 
 static struct platform_device *coretemp_get_pdev(unsigned int cpu)
 {
-       int pkgid = topology_logical_package_id(cpu);
+       int id = topology_logical_die_id(cpu);
 
-       if (pkgid >= 0 && pkgid < max_packages)
-               return pkg_devices[pkgid];
+       if (id >= 0 && id < max_zones)
+               return zone_devices[id];
        return NULL;
 }
 
@@ -531,7 +531,7 @@ static int coretemp_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct platform_data *pdata;
 
-       /* Initialize the per-package data structures */
+       /* Initialize the per-zone data structures */
        pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL);
        if (!pdata)
                return -ENOMEM;
@@ -566,13 +566,13 @@ static struct platform_driver coretemp_driver = {
 
 static struct platform_device *coretemp_device_add(unsigned int cpu)
 {
-       int err, pkgid = topology_logical_package_id(cpu);
+       int err, zoneid = topology_logical_die_id(cpu);
        struct platform_device *pdev;
 
-       if (pkgid < 0)
+       if (zoneid < 0)
                return ERR_PTR(-ENOMEM);
 
-       pdev = platform_device_alloc(DRVNAME, pkgid);
+       pdev = platform_device_alloc(DRVNAME, zoneid);
        if (!pdev)
                return ERR_PTR(-ENOMEM);
 
@@ -582,7 +582,7 @@ static struct platform_device *coretemp_device_add(unsigned int cpu)
                return ERR_PTR(err);
        }
 
-       pkg_devices[pkgid] = pdev;
+       zone_devices[zoneid] = pdev;
        return pdev;
 }
 
@@ -690,7 +690,7 @@ static int coretemp_cpu_offline(unsigned int cpu)
         * the rest.
         */
        if (cpumask_empty(&pd->cpumask)) {
-               pkg_devices[topology_logical_package_id(cpu)] = NULL;
+               zone_devices[topology_logical_die_id(cpu)] = NULL;
                platform_device_unregister(pdev);
                return 0;
        }
@@ -728,10 +728,10 @@ static int __init coretemp_init(void)
        if (!x86_match_cpu(coretemp_ids))
                return -ENODEV;
 
-       max_packages = topology_max_packages();
-       pkg_devices = kcalloc(max_packages, sizeof(struct platform_device *),
+       max_zones = topology_max_packages() * topology_max_die_per_package();
+       zone_devices = kcalloc(max_zones, sizeof(struct platform_device *),
                              GFP_KERNEL);
-       if (!pkg_devices)
+       if (!zone_devices)
                return -ENOMEM;
 
        err = platform_driver_register(&coretemp_driver);
@@ -747,7 +747,7 @@ static int __init coretemp_init(void)
 
 outdrv:
        platform_driver_unregister(&coretemp_driver);
-       kfree(pkg_devices);
+       kfree(zone_devices);
        return err;
 }
 module_init(coretemp_init)
@@ -756,7 +756,7 @@ static void __exit coretemp_exit(void)
 {
        cpuhp_remove_state(coretemp_hp_online);
        platform_driver_unregister(&coretemp_driver);
-       kfree(pkg_devices);
+       kfree(zone_devices);
 }
 module_exit(coretemp_exit)
 
index f888117..8692f6b 100644 (file)
@@ -166,12 +166,15 @@ struct rapl_domain {
 #define power_zone_to_rapl_domain(_zone) \
        container_of(_zone, struct rapl_domain, power_zone)
 
+/* maximum rapl package domain name: package-%d-die-%d */
+#define PACKAGE_DOMAIN_NAME_LENGTH 30
 
-/* Each physical package contains multiple domains, these are the common
+
+/* Each rapl package contains multiple domains, these are the common
  * data across RAPL domains within a package.
  */
 struct rapl_package {
-       unsigned int id; /* physical package/socket id */
+       unsigned int id; /* logical die id, equals physical 1-die systems */
        unsigned int nr_domains;
        unsigned long domain_map; /* bit map of active domains */
        unsigned int power_unit;
@@ -186,6 +189,7 @@ struct rapl_package {
        int lead_cpu; /* one active cpu per package for access */
        /* Track active cpus */
        struct cpumask cpumask;
+       char name[PACKAGE_DOMAIN_NAME_LENGTH];
 };
 
 struct rapl_defaults {
@@ -252,8 +256,9 @@ static struct powercap_control_type *control_type; /* PowerCap Controller */
 static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */
 
 /* caller to ensure CPU hotplug lock is held */
-static struct rapl_package *find_package_by_id(int id)
+static struct rapl_package *rapl_find_package_domain(int cpu)
 {
+       int id = topology_logical_die_id(cpu);
        struct rapl_package *rp;
 
        list_for_each_entry(rp, &rapl_packages, plist) {
@@ -913,8 +918,8 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Core CPU package %d energy=%dpJ, time=%dus, power=%duW\n",
-               rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
+       pr_debug("Core CPU %s energy=%dpJ, time=%dus, power=%duW\n",
+               rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
 }
@@ -938,8 +943,8 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Atom package %d energy=%dpJ, time=%dus, power=%duW\n",
-               rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
+       pr_debug("Atom %s energy=%dpJ, time=%dus, power=%duW\n",
+               rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
 }
@@ -1168,7 +1173,7 @@ static void rapl_update_domain_data(struct rapl_package *rp)
        u64 val;
 
        for (dmn = 0; dmn < rp->nr_domains; dmn++) {
-               pr_debug("update package %d domain %s data\n", rp->id,
+               pr_debug("update %s domain %s data\n", rp->name,
                         rp->domains[dmn].name);
                /* exclude non-raw primitives */
                for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) {
@@ -1193,7 +1198,6 @@ static void rapl_unregister_powercap(void)
 static int rapl_package_register_powercap(struct rapl_package *rp)
 {
        struct rapl_domain *rd;
-       char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/
        struct powercap_zone *power_zone = NULL;
        int nr_pl, ret;
 
@@ -1204,20 +1208,16 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
        for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
                if (rd->id == RAPL_DOMAIN_PACKAGE) {
                        nr_pl = find_nr_power_limit(rd);
-                       pr_debug("register socket %d package domain %s\n",
-                               rp->id, rd->name);
-                       memset(dev_name, 0, sizeof(dev_name));
-                       snprintf(dev_name, sizeof(dev_name), "%s-%d",
-                               rd->name, rp->id);
+                       pr_debug("register package domain %s\n", rp->name);
                        power_zone = powercap_register_zone(&rd->power_zone,
                                                        control_type,
-                                                       dev_name, NULL,
+                                                       rp->name, NULL,
                                                        &zone_ops[rd->id],
                                                        nr_pl,
                                                        &constraint_ops);
                        if (IS_ERR(power_zone)) {
-                               pr_debug("failed to register package, %d\n",
-                                       rp->id);
+                               pr_debug("failed to register power zone %s\n",
+                                       rp->name);
                                return PTR_ERR(power_zone);
                        }
                        /* track parent zone in per package/socket data */
@@ -1243,8 +1243,8 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
                                                &constraint_ops);
 
                if (IS_ERR(power_zone)) {
-                       pr_debug("failed to register power_zone, %d:%s:%s\n",
-                               rp->id, rd->name, dev_name);
+                       pr_debug("failed to register power_zone, %s:%s\n",
+                               rp->name, rd->name);
                        ret = PTR_ERR(power_zone);
                        goto err_cleanup;
                }
@@ -1257,7 +1257,7 @@ err_cleanup:
         * failed after the first domain setup.
         */
        while (--rd >= rp->domains) {
-               pr_debug("unregister package %d domain %s\n", rp->id, rd->name);
+               pr_debug("unregister %s domain %s\n", rp->name, rd->name);
                powercap_unregister_zone(control_type, &rd->power_zone);
        }
 
@@ -1288,7 +1288,7 @@ static int __init rapl_register_psys(void)
        rd->rpl[0].name = pl1_name;
        rd->rpl[1].prim_id = PL2_ENABLE;
        rd->rpl[1].name = pl2_name;
-       rd->rp = find_package_by_id(0);
+       rd->rp = rapl_find_package_domain(0);
 
        power_zone = powercap_register_zone(&rd->power_zone, control_type,
                                            "psys", NULL,
@@ -1367,8 +1367,8 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
        /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
        if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
                if (val64) {
-                       pr_info("RAPL package %d domain %s locked by BIOS\n",
-                               rd->rp->id, rd->name);
+                       pr_info("RAPL %s domain %s locked by BIOS\n",
+                               rd->rp->name, rd->name);
                        rd->state |= DOMAIN_STATE_BIOS_LOCKED;
                }
        }
@@ -1397,10 +1397,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
        }
        rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
        if (!rp->nr_domains) {
-               pr_debug("no valid rapl domains found in package %d\n", rp->id);
+               pr_debug("no valid rapl domains found in %s\n", rp->name);
                return -ENODEV;
        }
-       pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id);
+       pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name);
 
        rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
                        GFP_KERNEL);
@@ -1433,8 +1433,8 @@ static void rapl_remove_package(struct rapl_package *rp)
                        rd_package = rd;
                        continue;
                }
-               pr_debug("remove package, undo power limit on %d: %s\n",
-                        rp->id, rd->name);
+               pr_debug("remove package, undo power limit on %s: %s\n",
+                        rp->name, rd->name);
                powercap_unregister_zone(control_type, &rd->power_zone);
        }
        /* do parent zone last */
@@ -1444,9 +1444,11 @@ static void rapl_remove_package(struct rapl_package *rp)
 }
 
 /* called from CPU hotplug notifier, hotplug lock held */
-static struct rapl_package *rapl_add_package(int cpu, int pkgid)
+static struct rapl_package *rapl_add_package(int cpu)
 {
+       int id = topology_logical_die_id(cpu);
        struct rapl_package *rp;
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
        int ret;
 
        rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
@@ -1454,9 +1456,16 @@ static struct rapl_package *rapl_add_package(int cpu, int pkgid)
                return ERR_PTR(-ENOMEM);
 
        /* add the new package to the list */
-       rp->id = pkgid;
+       rp->id = id;
        rp->lead_cpu = cpu;
 
+       if (topology_max_die_per_package() > 1)
+               snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH,
+                       "package-%d-die-%d", c->phys_proc_id, c->cpu_die_id);
+       else
+               snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d",
+                       c->phys_proc_id);
+
        /* check if the package contains valid domains */
        if (rapl_detect_domains(rp, cpu) ||
                rapl_defaults->check_unit(rp, cpu)) {
@@ -1485,12 +1494,11 @@ err_free_package:
  */
 static int rapl_cpu_online(unsigned int cpu)
 {
-       int pkgid = topology_physical_package_id(cpu);
        struct rapl_package *rp;
 
-       rp = find_package_by_id(pkgid);
+       rp = rapl_find_package_domain(cpu);
        if (!rp) {
-               rp = rapl_add_package(cpu, pkgid);
+               rp = rapl_add_package(cpu);
                if (IS_ERR(rp))
                        return PTR_ERR(rp);
        }
@@ -1500,11 +1508,10 @@ static int rapl_cpu_online(unsigned int cpu)
 
 static int rapl_cpu_down_prep(unsigned int cpu)
 {
-       int pkgid = topology_physical_package_id(cpu);
        struct rapl_package *rp;
        int lead_cpu;
 
-       rp = find_package_by_id(pkgid);
+       rp = rapl_find_package_domain(cpu);
        if (!rp)
                return 0;
 
index 319b771..e85d54d 100644 (file)
@@ -43,7 +43,7 @@ MODULE_PARM_DESC(notify_delay_ms,
 */
 #define MAX_NUMBER_OF_TRIPS    2
 
-struct pkg_device {
+struct zone_device {
        int                             cpu;
        bool                            work_scheduled;
        u32                             tj_max;
@@ -58,10 +58,10 @@ static struct thermal_zone_params pkg_temp_tz_params = {
        .no_hwmon       = true,
 };
 
-/* Keep track of how many package pointers we allocated in init() */
-static int max_packages __read_mostly;
-/* Array of package pointers */
-static struct pkg_device **packages;
+/* Keep track of how many zone pointers we allocated in init() */
+static int max_id __read_mostly;
+/* Array of zone pointers */
+static struct zone_device **zones;
 /* Serializes interrupt notification, work and hotplug */
 static DEFINE_SPINLOCK(pkg_temp_lock);
 /* Protects zone operation in the work function against hotplug removal */
@@ -108,12 +108,12 @@ err_out:
  *
  * - Other callsites: Must hold pkg_temp_lock
  */
-static struct pkg_device *pkg_temp_thermal_get_dev(unsigned int cpu)
+static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
 {
-       int pkgid = topology_logical_package_id(cpu);
+       int id = topology_logical_die_id(cpu);
 
-       if (pkgid >= 0 && pkgid < max_packages)
-               return packages[pkgid];
+       if (id >= 0 && id < max_id)
+               return zones[id];
        return NULL;
 }
 
@@ -138,12 +138,13 @@ static int get_tj_max(int cpu, u32 *tj_max)
 
 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 {
-       struct pkg_device *pkgdev = tzd->devdata;
+       struct zone_device *zonedev = tzd->devdata;
        u32 eax, edx;
 
-       rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_STATUS, &eax, &edx);
+       rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_STATUS,
+                       &eax, &edx);
        if (eax & 0x80000000) {
-               *temp = pkgdev->tj_max - ((eax >> 16) & 0x7f) * 1000;
+               *temp = zonedev->tj_max - ((eax >> 16) & 0x7f) * 1000;
                pr_debug("sys_get_curr_temp %d\n", *temp);
                return 0;
        }
@@ -153,7 +154,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 static int sys_get_trip_temp(struct thermal_zone_device *tzd,
                             int trip, int *temp)
 {
-       struct pkg_device *pkgdev = tzd->devdata;
+       struct zone_device *zonedev = tzd->devdata;
        unsigned long thres_reg_value;
        u32 mask, shift, eax, edx;
        int ret;
@@ -169,14 +170,14 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
                shift = THERM_SHIFT_THRESHOLD0;
        }
 
-       ret = rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+       ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
                           &eax, &edx);
        if (ret < 0)
                return ret;
 
        thres_reg_value = (eax & mask) >> shift;
        if (thres_reg_value)
-               *temp = pkgdev->tj_max - thres_reg_value * 1000;
+               *temp = zonedev->tj_max - thres_reg_value * 1000;
        else
                *temp = 0;
        pr_debug("sys_get_trip_temp %d\n", *temp);
@@ -187,14 +188,14 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
 static int
 sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
 {
-       struct pkg_device *pkgdev = tzd->devdata;
+       struct zone_device *zonedev = tzd->devdata;
        u32 l, h, mask, shift, intr;
        int ret;
 
-       if (trip >= MAX_NUMBER_OF_TRIPS || temp >= pkgdev->tj_max)
+       if (trip >= MAX_NUMBER_OF_TRIPS || temp >= zonedev->tj_max)
                return -EINVAL;
 
-       ret = rdmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+       ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
                           &l, &h);
        if (ret < 0)
                return ret;
@@ -216,11 +217,12 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
        if (!temp) {
                l &= ~intr;
        } else {
-               l |= (pkgdev->tj_max - temp)/1000 << shift;
+               l |= (zonedev->tj_max - temp)/1000 << shift;
                l |= intr;
        }
 
-       return wrmsr_on_cpu(pkgdev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+       return wrmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+                       l, h);
 }
 
 static int sys_get_trip_type(struct thermal_zone_device *thermal, int trip,
@@ -275,26 +277,26 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
 {
        struct thermal_zone_device *tzone = NULL;
        int cpu = smp_processor_id();
-       struct pkg_device *pkgdev;
+       struct zone_device *zonedev;
        u64 msr_val, wr_val;
 
        mutex_lock(&thermal_zone_mutex);
        spin_lock_irq(&pkg_temp_lock);
        ++pkg_work_cnt;
 
-       pkgdev = pkg_temp_thermal_get_dev(cpu);
-       if (!pkgdev) {
+       zonedev = pkg_temp_thermal_get_dev(cpu);
+       if (!zonedev) {
                spin_unlock_irq(&pkg_temp_lock);
                mutex_unlock(&thermal_zone_mutex);
                return;
        }
-       pkgdev->work_scheduled = false;
+       zonedev->work_scheduled = false;
 
        rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
        wr_val = msr_val & ~(THERM_LOG_THRESHOLD0 | THERM_LOG_THRESHOLD1);
        if (wr_val != msr_val) {
                wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, wr_val);
-               tzone = pkgdev->tzone;
+               tzone = zonedev->tzone;
        }
 
        enable_pkg_thres_interrupt();
@@ -320,7 +322,7 @@ static void pkg_thermal_schedule_work(int cpu, struct delayed_work *work)
 static int pkg_thermal_notify(u64 msr_val)
 {
        int cpu = smp_processor_id();
-       struct pkg_device *pkgdev;
+       struct zone_device *zonedev;
        unsigned long flags;
 
        spin_lock_irqsave(&pkg_temp_lock, flags);
@@ -329,10 +331,10 @@ static int pkg_thermal_notify(u64 msr_val)
        disable_pkg_thres_interrupt();
 
        /* Work is per package, so scheduling it once is enough. */
-       pkgdev = pkg_temp_thermal_get_dev(cpu);
-       if (pkgdev && !pkgdev->work_scheduled) {
-               pkgdev->work_scheduled = true;
-               pkg_thermal_schedule_work(pkgdev->cpu, &pkgdev->work);
+       zonedev = pkg_temp_thermal_get_dev(cpu);
+       if (zonedev && !zonedev->work_scheduled) {
+               zonedev->work_scheduled = true;
+               pkg_thermal_schedule_work(zonedev->cpu, &zonedev->work);
        }
 
        spin_unlock_irqrestore(&pkg_temp_lock, flags);
@@ -341,12 +343,12 @@ static int pkg_thermal_notify(u64 msr_val)
 
 static int pkg_temp_thermal_device_add(unsigned int cpu)
 {
-       int pkgid = topology_logical_package_id(cpu);
+       int id = topology_logical_die_id(cpu);
        u32 tj_max, eax, ebx, ecx, edx;
-       struct pkg_device *pkgdev;
+       struct zone_device *zonedev;
        int thres_count, err;
 
-       if (pkgid >= max_packages)
+       if (id >= max_id)
                return -ENOMEM;
 
        cpuid(6, &eax, &ebx, &ecx, &edx);
@@ -360,51 +362,51 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
        if (err)
                return err;
 
-       pkgdev = kzalloc(sizeof(*pkgdev), GFP_KERNEL);
-       if (!pkgdev)
+       zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL);
+       if (!zonedev)
                return -ENOMEM;
 
-       INIT_DELAYED_WORK(&pkgdev->work, pkg_temp_thermal_threshold_work_fn);
-       pkgdev->cpu = cpu;
-       pkgdev->tj_max = tj_max;
-       pkgdev->tzone = thermal_zone_device_register("x86_pkg_temp",
+       INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn);
+       zonedev->cpu = cpu;
+       zonedev->tj_max = tj_max;
+       zonedev->tzone = thermal_zone_device_register("x86_pkg_temp",
                        thres_count,
                        (thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
-                       pkgdev, &tzone_ops, &pkg_temp_tz_params, 0, 0);
-       if (IS_ERR(pkgdev->tzone)) {
-               err = PTR_ERR(pkgdev->tzone);
-               kfree(pkgdev);
+                       zonedev, &tzone_ops, &pkg_temp_tz_params, 0, 0);
+       if (IS_ERR(zonedev->tzone)) {
+               err = PTR_ERR(zonedev->tzone);
+               kfree(zonedev);
                return err;
        }
        /* Store MSR value for package thermal interrupt, to restore at exit */
-       rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, pkgdev->msr_pkg_therm_low,
-             pkgdev->msr_pkg_therm_high);
+       rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low,
+             zonedev->msr_pkg_therm_high);
 
-       cpumask_set_cpu(cpu, &pkgdev->cpumask);
+       cpumask_set_cpu(cpu, &zonedev->cpumask);
        spin_lock_irq(&pkg_temp_lock);
-       packages[pkgid] = pkgdev;
+       zones[id] = zonedev;
        spin_unlock_irq(&pkg_temp_lock);
        return 0;
 }
 
 static int pkg_thermal_cpu_offline(unsigned int cpu)
 {
-       struct pkg_device *pkgdev = pkg_temp_thermal_get_dev(cpu);
+       struct zone_device *zonedev = pkg_temp_thermal_get_dev(cpu);
        bool lastcpu, was_target;
        int target;
 
-       if (!pkgdev)
+       if (!zonedev)
                return 0;
 
-       target = cpumask_any_but(&pkgdev->cpumask, cpu);
-       cpumask_clear_cpu(cpu, &pkgdev->cpumask);
+       target = cpumask_any_but(&zonedev->cpumask, cpu);
+       cpumask_clear_cpu(cpu, &zonedev->cpumask);
        lastcpu = target >= nr_cpu_ids;
        /*
         * Remove the sysfs files, if this is the last cpu in the package
         * before doing further cleanups.
         */
        if (lastcpu) {
-               struct thermal_zone_device *tzone = pkgdev->tzone;
+               struct thermal_zone_device *tzone = zonedev->tzone;
 
                /*
                 * We must protect against a work function calling
@@ -413,7 +415,7 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
                 * won't try to call.
                 */
                mutex_lock(&thermal_zone_mutex);
-               pkgdev->tzone = NULL;
+               zonedev->tzone = NULL;
                mutex_unlock(&thermal_zone_mutex);
 
                thermal_zone_device_unregister(tzone);
@@ -427,8 +429,8 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
         * one. When we drop the lock, then the interrupt notify function
         * will see the new target.
         */
-       was_target = pkgdev->cpu == cpu;
-       pkgdev->cpu = target;
+       was_target = zonedev->cpu == cpu;
+       zonedev->cpu = target;
 
        /*
         * If this is the last CPU in the package remove the package
@@ -437,23 +439,23 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
         * worker will see the package anymore.
         */
        if (lastcpu) {
-               packages[topology_logical_package_id(cpu)] = NULL;
+               zones[topology_logical_die_id(cpu)] = NULL;
                /* After this point nothing touches the MSR anymore. */
                wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
-                     pkgdev->msr_pkg_therm_low, pkgdev->msr_pkg_therm_high);
+                     zonedev->msr_pkg_therm_low, zonedev->msr_pkg_therm_high);
        }
 
        /*
         * Check whether there is work scheduled and whether the work is
         * targeted at the outgoing CPU.
         */
-       if (pkgdev->work_scheduled && was_target) {
+       if (zonedev->work_scheduled && was_target) {
                /*
                 * To cancel the work we need to drop the lock, otherwise
                 * we might deadlock if the work needs to be flushed.
                 */
                spin_unlock_irq(&pkg_temp_lock);
-               cancel_delayed_work_sync(&pkgdev->work);
+               cancel_delayed_work_sync(&zonedev->work);
                spin_lock_irq(&pkg_temp_lock);
                /*
                 * If this is not the last cpu in the package and the work
@@ -461,21 +463,21 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
                 * need to reschedule the work, otherwise the interrupt
                 * stays disabled forever.
                 */
-               if (!lastcpu && pkgdev->work_scheduled)
-                       pkg_thermal_schedule_work(target, &pkgdev->work);
+               if (!lastcpu && zonedev->work_scheduled)
+                       pkg_thermal_schedule_work(target, &zonedev->work);
        }
 
        spin_unlock_irq(&pkg_temp_lock);
 
        /* Final cleanup if this is the last cpu */
        if (lastcpu)
-               kfree(pkgdev);
+               kfree(zonedev);
        return 0;
 }
 
 static int pkg_thermal_cpu_online(unsigned int cpu)
 {
-       struct pkg_device *pkgdev = pkg_temp_thermal_get_dev(cpu);
+       struct zone_device *zonedev = pkg_temp_thermal_get_dev(cpu);
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
        /* Paranoia check */
@@ -483,8 +485,8 @@ static int pkg_thermal_cpu_online(unsigned int cpu)
                return -ENODEV;
 
        /* If the package exists, nothing to do */
-       if (pkgdev) {
-               cpumask_set_cpu(cpu, &pkgdev->cpumask);
+       if (zonedev) {
+               cpumask_set_cpu(cpu, &zonedev->cpumask);
                return 0;
        }
        return pkg_temp_thermal_device_add(cpu);
@@ -503,10 +505,10 @@ static int __init pkg_temp_thermal_init(void)
        if (!x86_match_cpu(pkg_temp_thermal_ids))
                return -ENODEV;
 
-       max_packages = topology_max_packages();
-       packages = kcalloc(max_packages, sizeof(struct pkg_device *),
+       max_id = topology_max_packages() * topology_max_die_per_package();
+       zones = kcalloc(max_id, sizeof(struct zone_device *),
                           GFP_KERNEL);
-       if (!packages)
+       if (!zones)
                return -ENOMEM;
 
        ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "thermal/x86_pkg:online",
@@ -525,7 +527,7 @@ static int __init pkg_temp_thermal_init(void)
        return 0;
 
 err:
-       kfree(packages);
+       kfree(zones);
        return ret;
 }
 module_init(pkg_temp_thermal_init)
@@ -537,7 +539,7 @@ static void __exit pkg_temp_thermal_exit(void)
 
        cpuhp_remove_state(pkg_thermal_hp_state);
        debugfs_remove_recursive(debugfs);
-       kfree(packages);
+       kfree(zones);
 }
 module_exit(pkg_temp_thermal_exit)
 
index 5703860..d41c21f 100644 (file)
@@ -175,6 +175,26 @@ int sysfs_create_group(struct kobject *kobj,
 }
 EXPORT_SYMBOL_GPL(sysfs_create_group);
 
+static int internal_create_groups(struct kobject *kobj, int update,
+                                 const struct attribute_group **groups)
+{
+       int error = 0;
+       int i;
+
+       if (!groups)
+               return 0;
+
+       for (i = 0; groups[i]; i++) {
+               error = internal_create_group(kobj, update, groups[i]);
+               if (error) {
+                       while (--i >= 0)
+                               sysfs_remove_group(kobj, groups[i]);
+                       break;
+               }
+       }
+       return error;
+}
+
 /**
  * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
  * @kobj:      The kobject to create the group on
@@ -191,25 +211,29 @@ EXPORT_SYMBOL_GPL(sysfs_create_group);
 int sysfs_create_groups(struct kobject *kobj,
                        const struct attribute_group **groups)
 {
-       int error = 0;
-       int i;
-
-       if (!groups)
-               return 0;
-
-       for (i = 0; groups[i]; i++) {
-               error = sysfs_create_group(kobj, groups[i]);
-               if (error) {
-                       while (--i >= 0)
-                               sysfs_remove_group(kobj, groups[i]);
-                       break;
-               }
-       }
-       return error;
+       return internal_create_groups(kobj, 0, groups);
 }
 EXPORT_SYMBOL_GPL(sysfs_create_groups);
 
 /**
+ * sysfs_update_groups - given a directory kobject, create a bunch of attribute groups
+ * @kobj:      The kobject to update the group on
+ * @groups:    The attribute groups to update, NULL terminated
+ *
+ * This function update a bunch of attribute groups.  If an error occurs when
+ * updating a group, all previously updated groups will be removed together
+ * with already existing (not updated) attributes.
+ *
+ * Returns 0 on success or error code from sysfs_update_group on failure.
+ */
+int sysfs_update_groups(struct kobject *kobj,
+                       const struct attribute_group **groups)
+{
+       return internal_create_groups(kobj, 1, groups);
+}
+EXPORT_SYMBOL_GPL(sysfs_update_groups);
+
+/**
  * sysfs_update_group - given a directory kobject, update an attribute group
  * @kobj:      The kobject to update the group on
  * @grp:       The attribute group to update
index 0ab99c7..3dc01cf 100644 (file)
@@ -255,6 +255,7 @@ struct pmu {
        struct module                   *module;
        struct device                   *dev;
        const struct attribute_group    **attr_groups;
+       const struct attribute_group    **attr_update;
        const char                      *name;
        int                             type;
 
index 786816c..9652367 100644 (file)
@@ -268,6 +268,8 @@ int __must_check sysfs_create_group(struct kobject *kobj,
                                    const struct attribute_group *grp);
 int __must_check sysfs_create_groups(struct kobject *kobj,
                                     const struct attribute_group **groups);
+int __must_check sysfs_update_groups(struct kobject *kobj,
+                                    const struct attribute_group **groups);
 int sysfs_update_group(struct kobject *kobj,
                       const struct attribute_group *grp);
 void sysfs_remove_group(struct kobject *kobj,
@@ -433,6 +435,12 @@ static inline int sysfs_create_groups(struct kobject *kobj,
        return 0;
 }
 
+static inline int sysfs_update_groups(struct kobject *kobj,
+                                     const struct attribute_group **groups)
+{
+       return 0;
+}
+
 static inline int sysfs_update_group(struct kobject *kobj,
                                const struct attribute_group *grp)
 {
index cb0775e..47a3e3c 100644 (file)
@@ -184,6 +184,9 @@ static inline int cpu_to_mem(int cpu)
 #ifndef topology_physical_package_id
 #define topology_physical_package_id(cpu)      ((void)(cpu), -1)
 #endif
+#ifndef topology_die_id
+#define topology_die_id(cpu)                   ((void)(cpu), -1)
+#endif
 #ifndef topology_core_id
 #define topology_core_id(cpu)                  ((void)(cpu), 0)
 #endif
@@ -193,6 +196,9 @@ static inline int cpu_to_mem(int cpu)
 #ifndef topology_core_cpumask
 #define topology_core_cpumask(cpu)             cpumask_of(cpu)
 #endif
+#ifndef topology_die_cpumask
+#define topology_die_cpumask(cpu)              cpumask_of(cpu)
+#endif
 
 #ifdef CONFIG_SCHED_SMT
 static inline const struct cpumask *cpu_smt_mask(int cpu)
index abbd4b3..118ad1a 100644 (file)
@@ -8532,9 +8532,9 @@ static int perf_tp_event_match(struct perf_event *event,
        if (event->hw.state & PERF_HES_STOPPED)
                return 0;
        /*
-        * All tracepoints are from kernel-space.
+        * If exclude_kernel, only trace user-space tracepoints (uprobes)
         */
-       if (event->attr.exclude_kernel)
+       if (event->attr.exclude_kernel && !user_mode(regs))
                return 0;
 
        if (!perf_tp_filter_match(event, data))
@@ -9874,6 +9874,12 @@ static int pmu_dev_alloc(struct pmu *pmu)
        if (ret)
                goto del_dev;
 
+       if (pmu->attr_update)
+               ret = sysfs_update_groups(&pmu->dev->kobj, pmu->attr_update);
+
+       if (ret)
+               goto del_dev;
+
 out:
        return ret;
 
index eb7e06b..0d60d68 100644 (file)
@@ -1331,7 +1331,7 @@ static inline void init_trace_event_call(struct trace_uprobe *tu,
        call->event.funcs = &uprobe_funcs;
        call->class->define_fields = uprobe_event_define_fields;
 
-       call->flags = TRACE_EVENT_FL_UPROBE;
+       call->flags = TRACE_EVENT_FL_UPROBE | TRACE_EVENT_FL_CAP_ANY;
        call->class->reg = trace_uprobe_register;
        call->data = tu;
 }
index 857d9e2..cba2269 100644 (file)
 
 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
 int scnprintf(char * buf, size_t size, const char * fmt, ...);
+int scnprintf_pad(char * buf, size_t size, const char * fmt, ...);
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 
index e08ee14..8780b4c 100644 (file)
@@ -23,3 +23,22 @@ int scnprintf(char * buf, size_t size, const char * fmt, ...)
 
        return (i >= ssize) ? (ssize - 1) : i;
 }
+
+int scnprintf_pad(char * buf, size_t size, const char * fmt, ...)
+{
+       ssize_t ssize = size;
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i = vscnprintf(buf, size, fmt, args);
+       va_end(args);
+
+       if (i < (int) size) {
+               for (; i < (int) size; i++)
+                       buf[i] = ' ';
+               buf[i] = 0x0;
+       }
+
+       return (i >= ssize) ? (ssize - 1) : i;
+}
index 115eaac..60d99e5 100644 (file)
@@ -88,16 +88,16 @@ smaller.
 
 To represent software control flow, "branches" samples are produced.  By default
 a branch sample is synthesized for every single branch.  To get an idea what
-data is available you can use the 'perf script' tool with no parameters, which
-will list all the samples.
+data is available you can use the 'perf script' tool with all itrace sampling
+options, which will list all the samples.
 
        perf record -e intel_pt//u ls
-       perf script
+       perf script --itrace=ibxwpe
 
 An interesting field that is not printed by default is 'flags' which can be
 displayed as follows:
 
-       perf script -Fcomm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr,symoff,flags
+       perf script --itrace=ibxwpe -F+flags
 
 The flags are "bcrosyiABEx" which stand for branch, call, return, conditional,
 system, asynchronous, interrupt, transaction abort, trace begin, trace end, and
@@ -713,7 +713,7 @@ Having no option is the same as
 
 which, in turn, is the same as
 
-       --itrace=ibxwpe
+       --itrace=cepwx
 
 The letters are:
 
index 9b0d04d..af82827 100644 (file)
@@ -313,6 +313,9 @@ OPTIONS
 --show-round-events
        Display finished round events i.e. events of type PERF_RECORD_FINISHED_ROUND.
 
+--show-bpf-events
+       Display bpf events i.e. events of type PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT.
+
 --demangle::
        Demangle symbol names to human readable form. It's enabled by default,
        disable with --no-demangle.
index 44d89fb..cfea87c 100644 (file)
@@ -262,6 +262,11 @@ Default is to monitor all CPUS.
        The number of threads to run when synthesizing events for existing processes.
        By default, the number of threads equals to the number of online CPUs.
 
+--namespaces::
+       Record events of type PERF_RECORD_NAMESPACES and display it with the
+       'cgroup_id' sort key.
+
+
 INTERACTIVE PROMPTING KEYS
 --------------------------
 
index 4d46ca6..0fffd2b 100644 (file)
@@ -420,6 +420,24 @@ fadvise_advice_tbl := $(srctree)/tools/perf/trace/beauty/fadvise.sh
 $(fadvise_advice_array): $(linux_uapi_dir)/in.h $(fadvise_advice_tbl)
        $(Q)$(SHELL) '$(fadvise_advice_tbl)' $(linux_uapi_dir) > $@
 
+fsmount_arrays := $(beauty_outdir)/fsmount_arrays.c
+fsmount_tbls := $(srctree)/tools/perf/trace/beauty/fsmount.sh
+
+$(fsmount_arrays): $(linux_uapi_dir)/fs.h $(fsmount_tbls)
+       $(Q)$(SHELL) '$(fsmount_tbls)' $(linux_uapi_dir) > $@
+
+fspick_arrays := $(beauty_outdir)/fspick_arrays.c
+fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh
+
+$(fspick_arrays): $(linux_uapi_dir)/fs.h $(fspick_tbls)
+       $(Q)$(SHELL) '$(fspick_tbls)' $(linux_uapi_dir) > $@
+
+fsconfig_arrays := $(beauty_outdir)/fsconfig_arrays.c
+fsconfig_tbls := $(srctree)/tools/perf/trace/beauty/fsconfig.sh
+
+$(fsconfig_arrays): $(linux_uapi_dir)/fs.h $(fsconfig_tbls)
+       $(Q)$(SHELL) '$(fsconfig_tbls)' $(linux_uapi_dir) > $@
+
 pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c
 asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
 pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
@@ -494,6 +512,12 @@ mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
 $(mount_flags_array): $(linux_uapi_dir)/fs.h $(mount_flags_tbl)
        $(Q)$(SHELL) '$(mount_flags_tbl)' $(linux_uapi_dir) > $@
 
+move_mount_flags_array := $(beauty_outdir)/move_mount_flags_array.c
+move_mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/move_mount_flags.sh
+
+$(move_mount_flags_array): $(linux_uapi_dir)/fs.h $(move_mount_flags_tbl)
+       $(Q)$(SHELL) '$(move_mount_flags_tbl)' $(linux_uapi_dir) > $@
+
 prctl_option_array := $(beauty_outdir)/prctl_option_array.c
 prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
 prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
@@ -526,6 +550,12 @@ arch_errno_tbl := $(srctree)/tools/perf/trace/beauty/arch_errno_names.sh
 $(arch_errno_name_array): $(arch_errno_tbl)
        $(Q)$(SHELL) '$(arch_errno_tbl)' $(CC) $(arch_errno_hdr_dir) > $@
 
+sync_file_range_arrays := $(beauty_outdir)/sync_file_range_arrays.c
+sync_file_range_tbls := $(srctree)/tools/perf/trace/beauty/sync_file_range.sh
+
+$(sync_file_range_arrays): $(linux_uapi_dir)/fs.h $(sync_file_range_tbls)
+       $(Q)$(SHELL) '$(sync_file_range_tbls)' $(linux_uapi_dir) > $@
+
 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
 
 # Create python binding output directory if not already present
@@ -629,6 +659,9 @@ build-dir   = $(if $(__build-dir),$(__build-dir),.)
 
 prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioctl_array) \
        $(fadvise_advice_array) \
+       $(fsconfig_arrays) \
+       $(fsmount_arrays) \
+       $(fspick_arrays) \
        $(pkey_alloc_access_rights_array) \
        $(sndrv_pcm_ioctl_array) \
        $(sndrv_ctl_ioctl_array) \
@@ -639,12 +672,14 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
        $(madvise_behavior_array) \
        $(mmap_flags_array) \
        $(mount_flags_array) \
+       $(move_mount_flags_array) \
        $(perf_ioctl_array) \
        $(prctl_option_array) \
        $(usbdevfs_ioctl_array) \
        $(x86_arch_prctl_code_array) \
        $(rename_flags_array) \
-       $(arch_errno_name_array)
+       $(arch_errno_name_array) \
+       $(sync_file_range_arrays)
 
 $(OUTPUT)%.o: %.c prepare FORCE
        $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -923,9 +958,13 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
                $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
                $(OUTPUT)pmu-events/pmu-events.c \
                $(OUTPUT)$(fadvise_advice_array) \
+               $(OUTPUT)$(fsconfig_arrays) \
+               $(OUTPUT)$(fsmount_arrays) \
+               $(OUTPUT)$(fspick_arrays) \
                $(OUTPUT)$(madvise_behavior_array) \
                $(OUTPUT)$(mmap_flags_array) \
                $(OUTPUT)$(mount_flags_array) \
+               $(OUTPUT)$(move_mount_flags_array) \
                $(OUTPUT)$(drm_ioctl_array) \
                $(OUTPUT)$(pkey_alloc_access_rights_array) \
                $(OUTPUT)$(sndrv_ctl_ioctl_array) \
@@ -939,7 +978,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
                $(OUTPUT)$(usbdevfs_ioctl_array) \
                $(OUTPUT)$(x86_arch_prctl_code_array) \
                $(OUTPUT)$(rename_flags_array) \
-               $(OUTPUT)$(arch_errno_name_array)
+               $(OUTPUT)$(arch_errno_name_array) \
+               $(OUTPUT)$(sync_file_range_arrays)
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 
 #
index 61cfd8f..3a48a26 100644 (file)
@@ -1606,6 +1606,7 @@ struct perf_script {
        bool                    show_namespace_events;
        bool                    show_lost_events;
        bool                    show_round_events;
+       bool                    show_bpf_events;
        bool                    allocated;
        bool                    per_event_dump;
        struct cpu_map          *cpus;
@@ -2318,6 +2319,41 @@ process_finished_round_event(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
+static int
+process_bpf_events(struct perf_tool *tool __maybe_unused,
+                  union perf_event *event,
+                  struct perf_sample *sample,
+                  struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+
+       if (machine__process_ksymbol(machine, event, sample) < 0)
+               return -1;
+
+       if (!evsel->attr.sample_id_all) {
+               perf_event__fprintf(event, stdout);
+               return 0;
+       }
+
+       thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+       if (thread == NULL) {
+               pr_debug("problem processing MMAP event, skipping it.\n");
+               return -1;
+       }
+
+       if (!filter_cpu(sample)) {
+               perf_sample__fprintf_start(sample, thread, evsel,
+                                          event->header.type, stdout);
+               perf_event__fprintf(event, stdout);
+       }
+
+       thread__put(thread);
+       return 0;
+}
+
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
@@ -2420,6 +2456,10 @@ static int __cmd_script(struct perf_script *script)
                script->tool.ordered_events = false;
                script->tool.finished_round = process_finished_round_event;
        }
+       if (script->show_bpf_events) {
+               script->tool.ksymbol   = process_bpf_events;
+               script->tool.bpf_event = process_bpf_events;
+       }
 
        if (perf_script__setup_per_event_dump(script)) {
                pr_err("Couldn't create the per event dump files\n");
@@ -3297,6 +3337,7 @@ static int parse_call_trace(const struct option *opt __maybe_unused,
        parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
        itrace_parse_synth_opts(opt, "cewp", 0);
        symbol_conf.nanosecs = true;
+       symbol_conf.pad_output_len_dso = 50;
        return 0;
 }
 
@@ -3438,6 +3479,8 @@ int cmd_script(int argc, const char **argv)
                    "Show lost events (if recorded)"),
        OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
                    "Show round events (if recorded)"),
+       OPT_BOOLEAN('\0', "show-bpf-events", &script.show_bpf_events,
+                   "Show bpf related events (if recorded)"),
        OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
                    "Dump trace output to files named by the monitored events"),
        OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
index 466621c..12b6b15 100644 (file)
@@ -1207,11 +1207,14 @@ static int __cmd_top(struct perf_top *top)
 
        init_process_thread(top);
 
+       if (opts->record_namespaces)
+               top->tool.namespace_events = true;
+
        ret = perf_event__synthesize_bpf_events(top->session, perf_event__process,
                                                &top->session->machines.host,
                                                &top->record_opts);
        if (ret < 0)
-               pr_warning("Couldn't synthesize bpf events.\n");
+               pr_debug("Couldn't synthesize BPF events: Pre-existing BPF programs won't have symbols resolved.\n");
 
        machine__synthesize_threads(&top->session->machines.host, &opts->target,
                                    top->evlist->threads, false,
@@ -1499,6 +1502,8 @@ int cmd_top(int argc, const char **argv)
        OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
        OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
                        "number of thread to run event synthesize"),
+       OPT_BOOLEAN(0, "namespaces", &opts->record_namespaces,
+                   "Record namespaces events"),
        OPT_END()
        };
        struct perf_evlist *sb_evlist = NULL;
index 52fadc8..ff17c4a 100644 (file)
@@ -402,6 +402,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
 
 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
 
+size_t syscall_arg__scnprintf_strarray_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       return strarray__scnprintf_flags(arg->parm, bf, size, arg->show_string_prefix, arg->val);
+}
+
 size_t strarrays__scnprintf(struct strarrays *sas, char *bf, size_t size, const char *intfmt, bool show_prefix, int val)
 {
        size_t printed;
@@ -481,6 +486,15 @@ static const char *bpf_cmd[] = {
 };
 static DEFINE_STRARRAY(bpf_cmd, "BPF_");
 
+static const char *fsmount_flags[] = {
+       [1] = "CLOEXEC",
+};
+static DEFINE_STRARRAY(fsmount_flags, "FSMOUNT_");
+
+#include "trace/beauty/generated/fsconfig_arrays.c"
+
+static DEFINE_STRARRAY(fsconfig_cmds, "FSCONFIG_");
+
 static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
 static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, "EPOLL_CTL_", 1);
 
@@ -641,6 +655,10 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
          { .scnprintf  = SCA_STRARRAY, \
            .parm       = &strarray__##array, }
 
+#define STRARRAY_FLAGS(name, array) \
+         { .scnprintf  = SCA_STRARRAY_FLAGS, \
+           .parm       = &strarray__##array, }
+
 #include "trace/beauty/arch_errno_names.c"
 #include "trace/beauty/eventfd.c"
 #include "trace/beauty/futex_op.c"
@@ -712,6 +730,15 @@ static struct syscall_fmt {
                   [2] = { .scnprintf =  SCA_FCNTL_ARG, /* arg */ }, }, },
        { .name     = "flock",
          .arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
+       { .name     = "fsconfig",
+         .arg = { [1] = STRARRAY(cmd, fsconfig_cmds), }, },
+       { .name     = "fsmount",
+         .arg = { [1] = STRARRAY_FLAGS(flags, fsmount_flags),
+                  [2] = { .scnprintf = SCA_FSMOUNT_ATTR_FLAGS, /* attr_flags */ }, }, },
+       { .name     = "fspick",
+         .arg = { [0] = { .scnprintf = SCA_FDAT,         /* dfd */ },
+                  [1] = { .scnprintf = SCA_FILENAME,     /* path */ },
+                  [2] = { .scnprintf = SCA_FSPICK_FLAGS, /* flags */ }, }, },
        { .name     = "fstat", .alias = "newfstat", },
        { .name     = "fstatat", .alias = "newfstatat", },
        { .name     = "futex",
@@ -774,6 +801,12 @@ static struct syscall_fmt {
          .arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ },
                   [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
                           .mask_val  = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
+       { .name     = "move_mount",
+         .arg = { [0] = { .scnprintf = SCA_FDAT,       /* from_dfd */ },
+                  [1] = { .scnprintf = SCA_FILENAME, /* from_pathname */ },
+                  [2] = { .scnprintf = SCA_FDAT,       /* to_dfd */ },
+                  [3] = { .scnprintf = SCA_FILENAME, /* to_pathname */ },
+                  [4] = { .scnprintf = SCA_MOVE_MOUNT_FLAGS, /* flags */ }, }, },
        { .name     = "mprotect",
          .arg = { [0] = { .scnprintf = SCA_HEX,        /* start */ },
                   [2] = { .scnprintf = SCA_MMAP_PROT,  /* prot */ }, }, },
@@ -878,6 +911,8 @@ static struct syscall_fmt {
          .arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
        { .name     = "symlinkat",
          .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
+       { .name     = "sync_file_range",
+         .arg = { [3] = { .scnprintf = SCA_SYNC_FILE_RANGE_FLAGS, /* flags */ }, }, },
        { .name     = "tgkill",
          .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
        { .name     = "tkill",
index 2422894..68a3d61 100644 (file)
@@ -87,7 +87,7 @@ struct augmented_filename {
 #define SYS_SYMLINKAT          266
 #define SYS_MEMFD_CREATE       319
 
-/* syscalls where the first arg is a string */
+/* syscalls where the second arg is a string */
 
 #define SYS_PWRITE64            18
 #define SYS_EXECVE              59
@@ -117,6 +117,8 @@ struct augmented_filename {
 #define SYS_RENAMEAT2          316
 #define SYS_EXECVEAT           322
 #define SYS_STATX              332
+#define SYS_MOVE_MOUNT         429
+#define SYS_FSPICK             433
 
 pid_filter(pids_filtered);
 
@@ -252,11 +254,22 @@ int sys_enter(struct syscall_enter_args *args)
        case SYS_FINIT_MODULE:
        case SYS_FREMOVEXATTR:
        case SYS_FSETXATTR:
+       case SYS_FSPICK:
        case SYS_FUTIMESAT:
        case SYS_INOTIFY_ADD_WATCH:
        case SYS_LINKAT:
        case SYS_MKDIRAT:
        case SYS_MKNODAT:
+       // case SYS_MOVE_MOUNT:
+       // For now don't copy move_mount first string arg, as it has two and
+       // 'perf trace's syscall_arg__scnprintf_filename() will use the one
+       // copied here, the first, for both args, duplicating the first and
+       // ignoring the second.
+       //
+       // We need to copy both here and make syscall_arg__scnprintf_filename
+       // skip the first when reading the second, using the size of the first, etc.
+       // Shouldn't be difficult, but now its perf/urgent time, lets wait for
+       // the next devel window.
        case SYS_MQ_TIMEDSEND:
        case SYS_NAME_TO_HANDLE_AT:
        case SYS_NEWFSTATAT:
index 74e4627..0b96545 100644 (file)
@@ -104,11 +104,6 @@ fix_buildid_cache_permissions()
 
        USER_HOME=$(bash <<< "echo ~$SUDO_USER")
 
-       if [ "$HOME" != "$USER_HOME" ] ; then
-               echo "Fix unnecessary because root has a home: $HOME" >&2
-               exit 1
-       fi
-
        echo "Fixing buildid cache permissions"
 
        find "$USER_HOME/.debug" -xdev -type d          ! -user "$SUDO_USER" -ls -exec chown    "$SUDO_USER" \{\} \;
index c3eae1d..b2f481b 100644 (file)
@@ -27,18 +27,31 @@ import datetime
 #
 # fedora:
 #
-#      $ sudo yum install postgresql postgresql-server python-pyside qt-postgresql
+#      $ sudo yum install postgresql postgresql-server qt-postgresql
 #      $ sudo su - postgres -c initdb
 #      $ sudo service postgresql start
 #      $ sudo su - postgres
-#      $ createuser <your user id here>
+#      $ createuser -s <your user id here>    # Older versions may not support -s, in which case answer the prompt below:
 #      Shall the new role be a superuser? (y/n) y
+#      $ sudo yum install python-pyside
+#
+#      Alternately, to use Python3 and/or pyside 2, one of the following:
+#              $ sudo yum install python3-pyside
+#              $ pip install --user PySide2
+#              $ pip3 install --user PySide2
 #
 # ubuntu:
 #
-#      $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql
+#      $ sudo apt-get install postgresql
 #      $ sudo su - postgres
 #      $ createuser -s <your user id here>
+#      $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
+#
+#      Alternately, to use Python3 and/or pyside 2, one of the following:
+#
+#              $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
+#              $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
+#              $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
 #
 # An example of using this script with Intel PT:
 #
@@ -199,7 +212,16 @@ import datetime
 #                   print "{0:>6}  {1:>10}  {2:>9}  {3:<30}  {4:>6}  {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
 #                   call_path_id = query.value(6)
 
-from PySide.QtSql import *
+pyside_version_1 = True
+if not "pyside-version-1" in sys.argv:
+       try:
+               from PySide2.QtSql import *
+               pyside_version_1 = False
+       except:
+               pass
+
+if pyside_version_1:
+       from PySide.QtSql import *
 
 if sys.version_info < (3, 0):
        def toserverstr(str):
@@ -255,11 +277,12 @@ def printdate(*args, **kw_args):
         print(datetime.datetime.today(), *args, sep=' ', **kw_args)
 
 def usage():
-       printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]")
-       printerr("where:        columns         'all' or 'branches'")
-       printerr("              calls           'calls' => create calls and call_paths table")
-       printerr("              callchains      'callchains' => create call_paths table")
-       raise Exception("Too few arguments")
+       printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
+       printerr("where:  columns            'all' or 'branches'");
+       printerr("        calls              'calls' => create calls and call_paths table");
+       printerr("        callchains         'callchains' => create call_paths table");
+       printerr("        pyside-version-1   'pyside-version-1' => use pyside version 1");
+       raise Exception("Too few or bad arguments")
 
 if (len(sys.argv) < 2):
        usage()
@@ -281,6 +304,8 @@ for i in range(3,len(sys.argv)):
                perf_db_export_calls = True
        elif (sys.argv[i] == "callchains"):
                perf_db_export_callchains = True
+       elif (sys.argv[i] == "pyside-version-1"):
+               pass
        else:
                usage()
 
index bf271fb..f617e51 100644 (file)
@@ -21,6 +21,26 @@ import datetime
 # provides LGPL-licensed Python bindings for Qt.  You will also need the package
 # libqt4-sql-sqlite for Qt sqlite3 support.
 #
+# Examples of installing pyside:
+#
+# ubuntu:
+#
+#      $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
+#
+#      Alternately, to use Python3 and/or pyside 2, one of the following:
+#
+#              $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
+#              $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
+#              $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
+# fedora:
+#
+#      $ sudo yum install python-pyside
+#
+#      Alternately, to use Python3 and/or pyside 2, one of the following:
+#              $ sudo yum install python3-pyside
+#              $ pip install --user PySide2
+#              $ pip3 install --user PySide2
+#
 # An example of using this script with Intel PT:
 #
 #      $ perf record -e intel_pt//u ls
@@ -49,7 +69,16 @@ import datetime
 # difference is  the 'transaction' column of the 'samples' table which is
 # renamed 'transaction_' in sqlite because 'transaction' is a reserved word.
 
-from PySide.QtSql import *
+pyside_version_1 = True
+if not "pyside-version-1" in sys.argv:
+       try:
+               from PySide2.QtSql import *
+               pyside_version_1 = False
+       except:
+               pass
+
+if pyside_version_1:
+       from PySide.QtSql import *
 
 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
        '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
@@ -69,11 +98,12 @@ def printdate(*args, **kw_args):
         print(datetime.datetime.today(), *args, sep=' ', **kw_args)
 
 def usage():
-       printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>]");
-       printerr("where:        columns         'all' or 'branches'");
-       printerr("              calls           'calls' => create calls and call_paths table");
-       printerr("              callchains      'callchains' => create call_paths table");
-       raise Exception("Too few arguments")
+       printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
+       printerr("where:  columns            'all' or 'branches'");
+       printerr("        calls              'calls' => create calls and call_paths table");
+       printerr("        callchains         'callchains' => create call_paths table");
+       printerr("        pyside-version-1   'pyside-version-1' => use pyside version 1");
+       raise Exception("Too few or bad arguments")
 
 if (len(sys.argv) < 2):
        usage()
@@ -95,6 +125,8 @@ for i in range(3,len(sys.argv)):
                perf_db_export_calls = True
        elif (sys.argv[i] == "callchains"):
                perf_db_export_callchains = True
+       elif (sys.argv[i] == "pyside-version-1"):
+               pass
        else:
                usage()
 
index affed7d..6fe5532 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
 # SPDX-License-Identifier: GPL-2.0
 # exported-sql-viewer.py: view data from sql database
 # Copyright (c) 2014-2018, Intel Corporation.
@@ -91,6 +91,7 @@
 from __future__ import print_function
 
 import sys
+import argparse
 import weakref
 import threading
 import string
@@ -104,10 +105,23 @@ except ImportError:
        glb_nsz = 16
 import re
 import os
-from PySide.QtCore import *
-from PySide.QtGui import *
-from PySide.QtSql import *
+
 pyside_version_1 = True
+if not "--pyside-version-1" in sys.argv:
+       try:
+               from PySide2.QtCore import *
+               from PySide2.QtGui import *
+               from PySide2.QtSql import *
+               from PySide2.QtWidgets import *
+               pyside_version_1 = False
+       except:
+               pass
+
+if pyside_version_1:
+       from PySide.QtCore import *
+       from PySide.QtGui import *
+       from PySide.QtSql import *
+
 from decimal import *
 from ctypes import *
 from multiprocessing import Process, Array, Value, Event
@@ -2754,7 +2768,7 @@ class WindowMenu():
                        action = self.window_menu.addAction(label)
                        action.setCheckable(True)
                        action.setChecked(sub_window == self.mdi_area.activeSubWindow())
-                       action.triggered.connect(lambda x=nr: self.setActiveSubWindow(x))
+                       action.triggered.connect(lambda a=None,x=nr: self.setActiveSubWindow(x))
                        self.window_menu.addAction(action)
                        nr += 1
 
@@ -3114,14 +3128,14 @@ class MainWindow(QMainWindow):
                        event = event.split(":")[0]
                        if event == "branches":
                                label = "All branches" if branches_events == 1 else "All branches " + "(id=" + dbid + ")"
-                               reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda x=dbid: self.NewBranchView(x), self))
+                               reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda a=None,x=dbid: self.NewBranchView(x), self))
                                label = "Selected branches" if branches_events == 1 else "Selected branches " + "(id=" + dbid + ")"
-                               reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda x=dbid: self.NewSelectedBranchView(x), self))
+                               reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda a=None,x=dbid: self.NewSelectedBranchView(x), self))
 
        def TableMenu(self, tables, menu):
                table_menu = menu.addMenu("&Tables")
                for table in tables:
-                       table_menu.addAction(CreateAction(table, "Create a new window containing a table view", lambda t=table: self.NewTableView(t), self))
+                       table_menu.addAction(CreateAction(table, "Create a new window containing a table view", lambda a=None,t=table: self.NewTableView(t), self))
 
        def NewCallGraph(self):
                CallGraphWindow(self.glb, self)
@@ -3361,18 +3375,27 @@ class DBRef():
 # Main
 
 def Main():
-       if (len(sys.argv) < 2):
-               printerr("Usage is: exported-sql-viewer.py {<database name> | --help-only}");
-               raise Exception("Too few arguments")
-
-       dbname = sys.argv[1]
-       if dbname == "--help-only":
+       usage_str =     "exported-sql-viewer.py [--pyside-version-1] <database name>\n" \
+                       "   or: exported-sql-viewer.py --help-only"
+       ap = argparse.ArgumentParser(usage = usage_str, add_help = False)
+       ap.add_argument("--pyside-version-1", action='store_true')
+       ap.add_argument("dbname", nargs="?")
+       ap.add_argument("--help-only", action='store_true')
+       args = ap.parse_args()
+
+       if args.help_only:
                app = QApplication(sys.argv)
                mainwindow = HelpOnlyWindow()
                mainwindow.show()
                err = app.exec_()
                sys.exit(err)
 
+       dbname = args.dbname
+       if dbname is None:
+               ap.print_usage()
+               print("Too few arguments")
+               sys.exit(1)
+
        is_sqlite3 = False
        try:
                f = open(dbname, "rb")
index 0b2b830..4afb631 100644 (file)
@@ -50,6 +50,7 @@ perf-y += perf-hooks.o
 perf-y += clang.o
 perf-y += unit_number__scnprintf.o
 perf-y += mem2node.o
+perf-y += map_groups.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
        $(call rule_mkdir)
index 9852b5d..941c545 100644 (file)
@@ -290,6 +290,10 @@ static struct test generic_tests[] = {
                .func = test__mem2node,
        },
        {
+               .desc = "map_groups__merge_in",
+               .func = test__map_groups__merge_in,
+       },
+       {
                .func = NULL,
        },
 };
diff --git a/tools/perf/tests/map_groups.c b/tools/perf/tests/map_groups.c
new file mode 100644 (file)
index 0000000..70d96ac
--- /dev/null
@@ -0,0 +1,120 @@
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include "tests.h"
+#include "map.h"
+#include "map_groups.h"
+#include "dso.h"
+#include "debug.h"
+
+struct map_def {
+       const char *name;
+       u64 start;
+       u64 end;
+};
+
+static int check_maps(struct map_def *merged, unsigned int size, struct map_groups *mg)
+{
+       struct map *map;
+       unsigned int i = 0;
+
+       map = map_groups__first(mg);
+       while (map) {
+               TEST_ASSERT_VAL("wrong map start",  map->start == merged[i].start);
+               TEST_ASSERT_VAL("wrong map end",    map->end == merged[i].end);
+               TEST_ASSERT_VAL("wrong map name",  !strcmp(map->dso->name, merged[i].name));
+               TEST_ASSERT_VAL("wrong map refcnt", refcount_read(&map->refcnt) == 2);
+
+               i++;
+               map = map_groups__next(map);
+
+               TEST_ASSERT_VAL("less maps expected", (map && i < size) || (!map && i == size));
+       }
+
+       return TEST_OK;
+}
+
+int test__map_groups__merge_in(struct test *t __maybe_unused, int subtest __maybe_unused)
+{
+       struct map_groups mg;
+       unsigned int i;
+       struct map_def bpf_progs[] = {
+               { "bpf_prog_1", 200, 300 },
+               { "bpf_prog_2", 500, 600 },
+               { "bpf_prog_3", 800, 900 },
+       };
+       struct map_def merged12[] = {
+               { "kcore1",     100,  200 },
+               { "bpf_prog_1", 200,  300 },
+               { "kcore1",     300,  500 },
+               { "bpf_prog_2", 500,  600 },
+               { "kcore1",     600,  800 },
+               { "bpf_prog_3", 800,  900 },
+               { "kcore1",     900, 1000 },
+       };
+       struct map_def merged3[] = {
+               { "kcore1",      100,  200 },
+               { "bpf_prog_1",  200,  300 },
+               { "kcore1",      300,  500 },
+               { "bpf_prog_2",  500,  600 },
+               { "kcore1",      600,  800 },
+               { "bpf_prog_3",  800,  900 },
+               { "kcore1",      900, 1000 },
+               { "kcore3",     1000, 1100 },
+       };
+       struct map *map_kcore1, *map_kcore2, *map_kcore3;
+       int ret;
+
+       map_groups__init(&mg, NULL);
+
+       for (i = 0; i < ARRAY_SIZE(bpf_progs); i++) {
+               struct map *map;
+
+               map = dso__new_map(bpf_progs[i].name);
+               TEST_ASSERT_VAL("failed to create map", map);
+
+               map->start = bpf_progs[i].start;
+               map->end   = bpf_progs[i].end;
+               map_groups__insert(&mg, map);
+               map__put(map);
+       }
+
+       map_kcore1 = dso__new_map("kcore1");
+       TEST_ASSERT_VAL("failed to create map", map_kcore1);
+
+       map_kcore2 = dso__new_map("kcore2");
+       TEST_ASSERT_VAL("failed to create map", map_kcore2);
+
+       map_kcore3 = dso__new_map("kcore3");
+       TEST_ASSERT_VAL("failed to create map", map_kcore3);
+
+       /* kcore1 map overlaps over all bpf maps */
+       map_kcore1->start = 100;
+       map_kcore1->end   = 1000;
+
+       /* kcore2 map hides behind bpf_prog_2 */
+       map_kcore2->start = 550;
+       map_kcore2->end   = 570;
+
+       /* kcore3 map hides behind bpf_prog_3, kcore1 and adds new map */
+       map_kcore3->start = 880;
+       map_kcore3->end   = 1100;
+
+       ret = map_groups__merge_in(&mg, map_kcore1);
+       TEST_ASSERT_VAL("failed to merge map", !ret);
+
+       ret = check_maps(merged12, ARRAY_SIZE(merged12), &mg);
+       TEST_ASSERT_VAL("merge check failed", !ret);
+
+       ret = map_groups__merge_in(&mg, map_kcore2);
+       TEST_ASSERT_VAL("failed to merge map", !ret);
+
+       ret = check_maps(merged12, ARRAY_SIZE(merged12), &mg);
+       TEST_ASSERT_VAL("merge check failed", !ret);
+
+       ret = map_groups__merge_in(&mg, map_kcore3);
+       TEST_ASSERT_VAL("failed to merge map", !ret);
+
+       ret = check_maps(merged3, ARRAY_SIZE(merged3), &mg);
+       TEST_ASSERT_VAL("merge check failed", !ret);
+       return TEST_OK;
+}
index 399f18c..e5e3a57 100644 (file)
@@ -107,6 +107,7 @@ const char *test__clang_subtest_get_desc(int subtest);
 int test__clang_subtest_get_nr(void);
 int test__unit_number__scnprint(struct test *test, int subtest);
 int test__mem2node(struct test *t, int subtest);
+int test__map_groups__merge_in(struct test *t, int subtest);
 
 bool test__bp_signal_is_supported(void);
 bool test__wp_is_supported(void);
index 85f328d..afa75a7 100644 (file)
@@ -1,11 +1,14 @@
 perf-y += clone.o
 perf-y += fcntl.o
 perf-y += flock.o
+perf-y += fsmount.o
+perf-y += fspick.o
 ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
 perf-y += ioctl.o
 endif
 perf-y += kcmp.o
 perf-y += mount_flags.o
+perf-y += move_mount.o
 perf-y += pkey_alloc.o
 perf-y += arch_prctl.o
 perf-y += prctl.o
@@ -13,3 +16,4 @@ perf-y += renameat.o
 perf-y += sockaddr.o
 perf-y += socket.o
 perf-y += statx.o
+perf-y += sync_file_range.o
index 139d485..7e06605 100644 (file)
@@ -108,6 +108,9 @@ struct syscall_arg {
 
 unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
 
+size_t syscall_arg__scnprintf_strarray_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STRARRAY_FLAGS syscall_arg__scnprintf_strarray_flags
+
 size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
 
@@ -141,6 +144,12 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar
 size_t syscall_arg__scnprintf_flock(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_FLOCK syscall_arg__scnprintf_flock
 
+size_t syscall_arg__scnprintf_fsmount_attr_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FSMOUNT_ATTR_FLAGS syscall_arg__scnprintf_fsmount_attr_flags
+
+size_t syscall_arg__scnprintf_fspick_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FSPICK_FLAGS syscall_arg__scnprintf_fspick_flags
+
 size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd
 
@@ -156,6 +165,9 @@ unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg, unsigne
 size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_MOUNT_FLAGS syscall_arg__scnprintf_mount_flags
 
+size_t syscall_arg__scnprintf_move_mount_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_MOVE_MOUNT_FLAGS syscall_arg__scnprintf_move_mount_flags
+
 size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
 
@@ -189,6 +201,9 @@ size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_
 size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
 #define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
 
+size_t syscall_arg__scnprintf_sync_file_range_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_SYNC_FILE_RANGE_FLAGS syscall_arg__scnprintf_sync_file_range_flags
+
 size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix);
 
 void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
index 6eb9a66..1a8d3be 100644 (file)
@@ -25,6 +25,7 @@ static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size,
        P_FLAG(FS);
        P_FLAG(FILES);
        P_FLAG(SIGHAND);
+       P_FLAG(PIDFD);
        P_FLAG(PTRACE);
        P_FLAG(VFORK);
        P_FLAG(PARENT);
diff --git a/tools/perf/trace/beauty/fsconfig.sh b/tools/perf/trace/beauty/fsconfig.sh
new file mode 100755 (executable)
index 0000000..83fb24d
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+       linux_header_dir=tools/include/uapi/linux
+else
+       linux_header_dir=$1
+fi
+
+linux_mount=${linux_header_dir}/mount.h
+
+printf "static const char *fsconfig_cmds[] = {\n"
+regex='^[[:space:]]*+FSCONFIG_([[:alnum:]_]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*,[[:space:]]*.*'
+egrep $regex ${linux_mount} | \
+       sed -r "s/$regex/\2 \1/g"       | \
+       xargs printf "\t[%s] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/fsmount.c b/tools/perf/trace/beauty/fsmount.c
new file mode 100644 (file)
index 0000000..30c8c08
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * trace/beauty/fsmount.c
+ *
+ *  Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/log2.h>
+#include <uapi/linux/mount.h>
+
+static size_t fsmount__scnprintf_attr_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+{
+#include "trace/beauty/generated/fsmount_arrays.c"
+       static DEFINE_STRARRAY(fsmount_attr_flags, "MOUNT_ATTR_");
+       size_t printed = 0;
+
+       if ((flags & ~MOUNT_ATTR__ATIME) != 0)
+              printed += strarray__scnprintf_flags(&strarray__fsmount_attr_flags, bf, size, show_prefix, flags);
+
+       if ((flags & MOUNT_ATTR__ATIME) == MOUNT_ATTR_RELATIME) {
+              printed += scnprintf(bf + printed, size - printed, "%s%s%s",
+                                   printed ? "|" : "", show_prefix ? "MOUNT_ATTR_" : "", "RELATIME");
+       }
+
+       return printed;
+}
+
+size_t syscall_arg__scnprintf_fsmount_attr_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       unsigned long flags = arg->val;
+
+       return fsmount__scnprintf_attr_flags(flags, bf, size, arg->show_string_prefix);
+}
diff --git a/tools/perf/trace/beauty/fsmount.sh b/tools/perf/trace/beauty/fsmount.sh
new file mode 100755 (executable)
index 0000000..615cc0f
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+       linux_header_dir=tools/include/uapi/linux
+else
+       linux_header_dir=$1
+fi
+
+linux_mount=${linux_header_dir}/mount.h
+
+# Remove MOUNT_ATTR_RELATIME as it is zeros, handle it a special way in the beautifier
+# Only handle MOUNT_ATTR_ followed by a capital letter/num as __ is special case
+# for things like MOUNT_ATTR__ATIME that is a mask for the possible ATIME handling
+# bits. Special case it as well in the beautifier
+
+printf "static const char *fsmount_attr_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOUNT_ATTR_([[:alnum:]][[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+egrep $regex ${linux_mount} | grep -v MOUNT_ATTR_RELATIME | \
+       sed -r "s/$regex/\2 \1/g"       | \
+       xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/fspick.c b/tools/perf/trace/beauty/fspick.c
new file mode 100644 (file)
index 0000000..c402479
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * trace/beauty/fspick.c
+ *
+ *  Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/log2.h>
+
+static size_t fspick__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+{
+#include "trace/beauty/generated/fspick_arrays.c"
+       static DEFINE_STRARRAY(fspick_flags, "FSPICK_");
+
+       return strarray__scnprintf_flags(&strarray__fspick_flags, bf, size, show_prefix, flags);
+}
+
+size_t syscall_arg__scnprintf_fspick_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       unsigned long flags = arg->val;
+
+       return fspick__scnprintf_flags(flags, bf, size, arg->show_string_prefix);
+}
diff --git a/tools/perf/trace/beauty/fspick.sh b/tools/perf/trace/beauty/fspick.sh
new file mode 100755 (executable)
index 0000000..b220e07
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+       linux_header_dir=tools/include/uapi/linux
+else
+       linux_header_dir=$1
+fi
+
+linux_mount=${linux_header_dir}/mount.h
+
+printf "static const char *fspick_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+FSPICK_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+egrep $regex ${linux_mount} | \
+       sed -r "s/$regex/\2 \1/g"       | \
+       xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/move_mount.c b/tools/perf/trace/beauty/move_mount.c
new file mode 100644 (file)
index 0000000..78ed803
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * trace/beauty/move_mount.c
+ *
+ *  Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/log2.h>
+
+static size_t move_mount__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+{
+#include "trace/beauty/generated/move_mount_flags_array.c"
+       static DEFINE_STRARRAY(move_mount_flags, "MOVE_MOUNT_");
+
+       return strarray__scnprintf_flags(&strarray__move_mount_flags, bf, size, show_prefix, flags);
+}
+
+size_t syscall_arg__scnprintf_move_mount_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       unsigned long flags = arg->val;
+
+       return move_mount__scnprintf_flags(flags, bf, size, arg->show_string_prefix);
+}
diff --git a/tools/perf/trace/beauty/move_mount_flags.sh b/tools/perf/trace/beauty/move_mount_flags.sh
new file mode 100755 (executable)
index 0000000..55e5924
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+       linux_header_dir=tools/include/uapi/linux
+else
+       linux_header_dir=$1
+fi
+
+linux_mount=${linux_header_dir}/mount.h
+
+printf "static const char *move_mount_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOVE_MOUNT_([FT]_[[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+egrep $regex ${linux_mount} | \
+       sed -r "s/$regex/\2 \1/g"       | \
+       xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/sync_file_range.c b/tools/perf/trace/beauty/sync_file_range.c
new file mode 100644 (file)
index 0000000..1c425f0
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * trace/beauty/sync_file_range.c
+ *
+ *  Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/log2.h>
+#include <uapi/linux/fs.h>
+
+static size_t sync_file_range__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix)
+{
+#include "trace/beauty/generated/sync_file_range_arrays.c"
+       static DEFINE_STRARRAY(sync_file_range_flags, "SYNC_FILE_RANGE_");
+       size_t printed = 0;
+
+       if ((flags & SYNC_FILE_RANGE_WRITE_AND_WAIT) == SYNC_FILE_RANGE_WRITE_AND_WAIT) {
+               printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? "SYNC_FILE_RANGE_" : "", "WRITE_AND_WAIT");
+              flags &= ~SYNC_FILE_RANGE_WRITE_AND_WAIT;
+       }
+
+       return printed + strarray__scnprintf_flags(&strarray__sync_file_range_flags, bf + printed, size - printed, show_prefix, flags);
+}
+
+size_t syscall_arg__scnprintf_sync_file_range_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       unsigned long flags = arg->val;
+
+       return sync_file_range__scnprintf_flags(flags, bf, size, arg->show_string_prefix);
+}
diff --git a/tools/perf/trace/beauty/sync_file_range.sh b/tools/perf/trace/beauty/sync_file_range.sh
new file mode 100755 (executable)
index 0000000..7a9282d
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1
+
+if [ $# -ne 1 ] ; then
+       linux_header_dir=tools/include/uapi/linux
+else
+       linux_header_dir=$1
+fi
+
+linux_fs=${linux_header_dir}/fs.h
+
+printf "static const char *sync_file_range_flags[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+SYNC_FILE_RANGE_([[:alnum:]_]+)[[:space:]]+([[:xdigit:]]+)[[:space:]]*.*'
+egrep $regex ${linux_fs} | \
+       sed -r "s/$regex/\2 \1/g"       | \
+       xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
+printf "};\n"
index 98d934a..b0d089a 100644 (file)
@@ -97,11 +97,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
        struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
        struct annotation *notes = browser__annotation(browser);
        struct annotation_line *al = list_entry(entry, struct annotation_line, node);
+       const bool is_current_entry = ui_browser__is_current_entry(browser, row);
        struct annotation_write_ops ops = {
                .first_line              = row == 0,
-               .current_entry           = ui_browser__is_current_entry(browser, row),
+               .current_entry           = is_current_entry,
                .change_color            = (!notes->options->hide_src_code &&
-                                           (!ops.current_entry ||
+                                           (!is_current_entry ||
                                             (browser->use_navkeypressed &&
                                              !browser->navkeypressed))),
                .width                   = browser->width,
index 3802cee..59241ff 100755 (executable)
@@ -19,7 +19,7 @@ TAG=
 if test -d ../../.git -o -f ../../.git
 then
        TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
-       CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
+       CID=$(git log -1 --abbrev=12 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
 elif test -f ../../PERF-VERSION-FILE
 then
        TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g')
index 66e82bd..cfdbf65 100644 (file)
@@ -1001,7 +1001,8 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
        }
 
        if (!str) {
-               itrace_synth_opts__set_default(synth_opts, false);
+               itrace_synth_opts__set_default(synth_opts,
+                                              synth_opts->default_no_sample);
                return 0;
        }
 
index e059976..1fb1829 100644 (file)
@@ -9,6 +9,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
+#include <bpf/libbpf.h>
+#include "bpf-event.h"
 #include "compress.h"
 #include "namespaces.h"
 #include "path.h"
@@ -706,6 +708,44 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
        return false;
 }
 
+static ssize_t bpf_read(struct dso *dso, u64 offset, char *data)
+{
+       struct bpf_prog_info_node *node;
+       ssize_t size = DSO__DATA_CACHE_SIZE;
+       u64 len;
+       u8 *buf;
+
+       node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
+       if (!node || !node->info_linear) {
+               dso->data.status = DSO_DATA_STATUS_ERROR;
+               return -1;
+       }
+
+       len = node->info_linear->info.jited_prog_len;
+       buf = (u8 *)(uintptr_t)node->info_linear->info.jited_prog_insns;
+
+       if (offset >= len)
+               return -1;
+
+       size = (ssize_t)min(len - offset, (u64)size);
+       memcpy(data, buf + offset, size);
+       return size;
+}
+
+static int bpf_size(struct dso *dso)
+{
+       struct bpf_prog_info_node *node;
+
+       node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
+       if (!node || !node->info_linear) {
+               dso->data.status = DSO_DATA_STATUS_ERROR;
+               return -1;
+       }
+
+       dso->data.file_size = node->info_linear->info.jited_prog_len;
+       return 0;
+}
+
 static void
 dso_cache__free(struct dso *dso)
 {
@@ -794,48 +834,53 @@ dso_cache__memcpy(struct dso_cache *cache, u64 offset,
        return cache_size;
 }
 
-static ssize_t
-dso_cache__read(struct dso *dso, struct machine *machine,
-               u64 offset, u8 *data, ssize_t size)
+static ssize_t file_read(struct dso *dso, struct machine *machine,
+                        u64 offset, char *data)
 {
-       struct dso_cache *cache;
-       struct dso_cache *old;
        ssize_t ret;
 
-       do {
-               u64 cache_offset;
+       pthread_mutex_lock(&dso__data_open_lock);
 
-               cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
-               if (!cache)
-                       return -ENOMEM;
+       /*
+        * dso->data.fd might be closed if other thread opened another
+        * file (dso) due to open file limit (RLIMIT_NOFILE).
+        */
+       try_to_open_dso(dso, machine);
 
-               pthread_mutex_lock(&dso__data_open_lock);
+       if (dso->data.fd < 0) {
+               dso->data.status = DSO_DATA_STATUS_ERROR;
+               ret = -errno;
+               goto out;
+       }
 
-               /*
-                * dso->data.fd might be closed if other thread opened another
-                * file (dso) due to open file limit (RLIMIT_NOFILE).
-                */
-               try_to_open_dso(dso, machine);
+       ret = pread(dso->data.fd, data, DSO__DATA_CACHE_SIZE, offset);
+out:
+       pthread_mutex_unlock(&dso__data_open_lock);
+       return ret;
+}
 
-               if (dso->data.fd < 0) {
-                       ret = -errno;
-                       dso->data.status = DSO_DATA_STATUS_ERROR;
-                       break;
-               }
+static ssize_t
+dso_cache__read(struct dso *dso, struct machine *machine,
+               u64 offset, u8 *data, ssize_t size)
+{
+       u64 cache_offset = offset & DSO__DATA_CACHE_MASK;
+       struct dso_cache *cache;
+       struct dso_cache *old;
+       ssize_t ret;
 
-               cache_offset = offset & DSO__DATA_CACHE_MASK;
+       cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
+       if (!cache)
+               return -ENOMEM;
 
-               ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
-               if (ret <= 0)
-                       break;
+       if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
+               ret = bpf_read(dso, cache_offset, cache->data);
+       else
+               ret = file_read(dso, machine, cache_offset, cache->data);
 
+       if (ret > 0) {
                cache->offset = cache_offset;
                cache->size   = ret;
-       } while (0);
-
-       pthread_mutex_unlock(&dso__data_open_lock);
 
-       if (ret > 0) {
                old = dso_cache__insert(dso, cache);
                if (old) {
                        /* we lose the race */
@@ -898,18 +943,12 @@ static ssize_t cached_read(struct dso *dso, struct machine *machine,
        return r;
 }
 
-int dso__data_file_size(struct dso *dso, struct machine *machine)
+static int file_size(struct dso *dso, struct machine *machine)
 {
        int ret = 0;
        struct stat st;
        char sbuf[STRERR_BUFSIZE];
 
-       if (dso->data.file_size)
-               return 0;
-
-       if (dso->data.status == DSO_DATA_STATUS_ERROR)
-               return -1;
-
        pthread_mutex_lock(&dso__data_open_lock);
 
        /*
@@ -938,6 +977,20 @@ out:
        return ret;
 }
 
+int dso__data_file_size(struct dso *dso, struct machine *machine)
+{
+       if (dso->data.file_size)
+               return 0;
+
+       if (dso->data.status == DSO_DATA_STATUS_ERROR)
+               return -1;
+
+       if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
+               return bpf_size(dso);
+
+       return file_size(dso, machine);
+}
+
 /**
  * dso__data_size - Return dso data size
  * @dso: dso object
index d1ad6c4..c9c6857 100644 (file)
@@ -1486,7 +1486,7 @@ static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp)
 
 size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
 {
-       return fprintf(fp, " ksymbol event with addr %" PRIx64 " len %u type %u flags 0x%x name %s\n",
+       return fprintf(fp, " addr %" PRIx64 " len %u type %u flags 0x%x name %s\n",
                       event->ksymbol_event.addr, event->ksymbol_event.len,
                       event->ksymbol_event.ksym_type,
                       event->ksymbol_event.flags, event->ksymbol_event.name);
@@ -1494,7 +1494,7 @@ size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
 
 size_t perf_event__fprintf_bpf_event(union perf_event *event, FILE *fp)
 {
-       return fprintf(fp, " bpf event with type %u, flags %u, id %u\n",
+       return fprintf(fp, " type %u, flags %u, id %u\n",
                       event->bpf_event.type, event->bpf_event.flags,
                       event->bpf_event.id);
 }
index 7ace7a1..fb3271f 100644 (file)
@@ -2561,7 +2561,7 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh
        char unit;
        int printed;
        const struct dso *dso = hists->dso_filter;
-       const struct thread *thread = hists->thread_filter;
+       struct thread *thread = hists->thread_filter;
        int socket_id = hists->socket_filter;
        unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
        u64 nr_events = hists->stats.total_period;
index d6f1b2a..9276506 100644 (file)
@@ -1850,7 +1850,6 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
 
        switch (ptq->switch_state) {
        case INTEL_PT_SS_NOT_TRACING:
-               ptq->next_tid = -1;
                break;
        case INTEL_PT_SS_UNKNOWN:
        case INTEL_PT_SS_TRACING:
@@ -1870,13 +1869,14 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
                ptq->switch_state = INTEL_PT_SS_TRACING;
                break;
        case INTEL_PT_SS_EXPECTING_SWITCH_IP:
-               ptq->next_tid = tid;
                intel_pt_log("ERROR: cpu %d expecting switch ip\n", cpu);
                break;
        default:
                break;
        }
 
+       ptq->next_tid = -1;
+
        return 1;
 }
 
@@ -1905,6 +1905,44 @@ static int intel_pt_process_switch(struct intel_pt *pt,
        return machine__set_current_tid(pt->machine, cpu, -1, tid);
 }
 
+static int intel_pt_context_switch_in(struct intel_pt *pt,
+                                     struct perf_sample *sample)
+{
+       pid_t pid = sample->pid;
+       pid_t tid = sample->tid;
+       int cpu = sample->cpu;
+
+       if (pt->sync_switch) {
+               struct intel_pt_queue *ptq;
+
+               ptq = intel_pt_cpu_to_ptq(pt, cpu);
+               if (ptq && ptq->sync_switch) {
+                       ptq->next_tid = -1;
+                       switch (ptq->switch_state) {
+                       case INTEL_PT_SS_NOT_TRACING:
+                       case INTEL_PT_SS_UNKNOWN:
+                       case INTEL_PT_SS_TRACING:
+                               break;
+                       case INTEL_PT_SS_EXPECTING_SWITCH_EVENT:
+                       case INTEL_PT_SS_EXPECTING_SWITCH_IP:
+                               ptq->switch_state = INTEL_PT_SS_TRACING;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * If the current tid has not been updated yet, ensure it is now that
+        * a "switch in" event has occurred.
+        */
+       if (machine__get_current_tid(pt->machine, cpu) == tid)
+               return 0;
+
+       return machine__set_current_tid(pt->machine, cpu, pid, tid);
+}
+
 static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
                                   struct perf_sample *sample)
 {
@@ -1916,7 +1954,7 @@ static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
 
        if (pt->have_sched_switch == 3) {
                if (!out)
-                       return 0;
+                       return intel_pt_context_switch_in(pt, sample);
                if (event->header.type != PERF_RECORD_SWITCH_CPU_WIDE) {
                        pr_err("Expecting CPU-wide context switch event\n");
                        return -EINVAL;
@@ -2579,7 +2617,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
        } else {
                itrace_synth_opts__set_default(&pt->synth_opts,
                                session->itrace_synth_opts->default_no_sample);
-               if (use_browser != -1) {
+               if (!session->itrace_synth_opts->default_no_sample &&
+                   !session->itrace_synth_opts->inject) {
                        pt->synth_opts.branches = false;
                        pt->synth_opts.callchain = true;
                }
index dc7aafe..17eec39 100644 (file)
@@ -704,12 +704,12 @@ static int machine__process_ksymbol_register(struct machine *machine,
                        return -ENOMEM;
 
                map->start = event->ksymbol_event.addr;
-               map->pgoff = map->start;
                map->end = map->start + event->ksymbol_event.len;
                map_groups__insert(&machine->kmaps, map);
        }
 
-       sym = symbol__new(event->ksymbol_event.addr, event->ksymbol_event.len,
+       sym = symbol__new(map->map_ip(map, map->start),
+                         event->ksymbol_event.len,
                          0, 0, event->ksymbol_event.name);
        if (!sym)
                return -ENOMEM;
@@ -1241,9 +1241,9 @@ static char *get_kernel_version(const char *root_dir)
                return NULL;
 
        tmp = fgets(version, sizeof(version), file);
-       if (!tmp)
-               *version = '\0';
        fclose(file);
+       if (!tmp)
+               return NULL;
 
        name = strstr(version, prefix);
        if (!name)
index ee71efb..6fce983 100644 (file)
@@ -405,6 +405,7 @@ size_t map__fprintf(struct map *map, FILE *fp)
 
 size_t map__fprintf_dsoname(struct map *map, FILE *fp)
 {
+       char buf[symbol_conf.pad_output_len_dso + 1];
        const char *dsoname = "[unknown]";
 
        if (map && map->dso) {
@@ -414,6 +415,11 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
                        dsoname = map->dso->name;
        }
 
+       if (symbol_conf.pad_output_len_dso) {
+               scnprintf_pad(buf, symbol_conf.pad_output_len_dso, "%s", dsoname);
+               dsoname = buf;
+       }
+
        return fprintf(fp, "%s", dsoname);
 }
 
index 4dcda33..5f25efa 100644 (file)
@@ -88,4 +88,6 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE
 
 struct map *map_groups__find_by_name(struct map_groups *mg, const char *name);
 
+int map_groups__merge_in(struct map_groups *kmaps, struct map *new_map);
+
 #endif // __PERF_MAP_GROUPS_H
index 5b5a167..a1a68a2 100644 (file)
@@ -17,6 +17,8 @@ if cc == "clang":
             vars[var] = sub("-fcf-protection", "", vars[var])
         if not clang_has_option("-fstack-clash-protection"):
             vars[var] = sub("-fstack-clash-protection", "", vars[var])
+        if not clang_has_option("-fstack-protector-strong"):
+            vars[var] = sub("-fstack-protector-strong", "", vars[var])
 
 from distutils.core import setup, Extension
 
index 5cbad55..f4540f8 100644 (file)
@@ -1166,6 +1166,85 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
        return 0;
 }
 
+/*
+ * Merges map into map_groups by splitting the new map
+ * within the existing map regions.
+ */
+int map_groups__merge_in(struct map_groups *kmaps, struct map *new_map)
+{
+       struct map *old_map;
+       LIST_HEAD(merged);
+
+       for (old_map = map_groups__first(kmaps); old_map;
+            old_map = map_groups__next(old_map)) {
+
+               /* no overload with this one */
+               if (new_map->end < old_map->start ||
+                   new_map->start >= old_map->end)
+                       continue;
+
+               if (new_map->start < old_map->start) {
+                       /*
+                        * |new......
+                        *       |old....
+                        */
+                       if (new_map->end < old_map->end) {
+                               /*
+                                * |new......|     -> |new..|
+                                *       |old....| ->       |old....|
+                                */
+                               new_map->end = old_map->start;
+                       } else {
+                               /*
+                                * |new.............| -> |new..|       |new..|
+                                *       |old....|    ->       |old....|
+                                */
+                               struct map *m = map__clone(new_map);
+
+                               if (!m)
+                                       return -ENOMEM;
+
+                               m->end = old_map->start;
+                               list_add_tail(&m->node, &merged);
+                               new_map->start = old_map->end;
+                       }
+               } else {
+                       /*
+                        *      |new......
+                        * |old....
+                        */
+                       if (new_map->end < old_map->end) {
+                               /*
+                                *      |new..|   -> x
+                                * |old.........| -> |old.........|
+                                */
+                               map__put(new_map);
+                               new_map = NULL;
+                               break;
+                       } else {
+                               /*
+                                *      |new......| ->         |new...|
+                                * |old....|        -> |old....|
+                                */
+                               new_map->start = old_map->end;
+                       }
+               }
+       }
+
+       while (!list_empty(&merged)) {
+               old_map = list_entry(merged.next, struct map, node);
+               list_del_init(&old_map->node);
+               map_groups__insert(kmaps, old_map);
+               map__put(old_map);
+       }
+
+       if (new_map) {
+               map_groups__insert(kmaps, new_map);
+               map__put(new_map);
+       }
+       return 0;
+}
+
 static int dso__load_kcore(struct dso *dso, struct map *map,
                           const char *kallsyms_filename)
 {
@@ -1222,7 +1301,12 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
        while (old_map) {
                struct map *next = map_groups__next(old_map);
 
-               if (old_map != map)
+               /*
+                * We need to preserve eBPF maps even if they are
+                * covered by kcore, because we need to access
+                * eBPF dso for source data.
+                */
+               if (old_map != map && !__map__is_bpf_prog(old_map))
                        map_groups__remove(kmaps, old_map);
                old_map = next;
        }
@@ -1256,11 +1340,16 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
                        map_groups__remove(kmaps, map);
                        map_groups__insert(kmaps, map);
                        map__put(map);
+                       map__put(new_map);
                } else {
-                       map_groups__insert(kmaps, new_map);
+                       /*
+                        * Merge kcore map into existing maps,
+                        * and ensure that current maps (eBPF)
+                        * stay intact.
+                        */
+                       if (map_groups__merge_in(kmaps, new_map))
+                               goto out_err;
                }
-
-               map__put(new_map);
        }
 
        if (machine__is(machine, "x86_64")) {
index 6c55fa6..382ba63 100644 (file)
@@ -69,6 +69,7 @@ struct symbol_conf {
                        *tid_list;
        const char      *symfs;
        int             res_sample;
+       int             pad_output_len_dso;
 };
 
 extern struct symbol_conf symbol_conf;
index b413ba5..aab7807 100644 (file)
@@ -141,13 +141,13 @@ static struct namespaces *__thread__namespaces(const struct thread *thread)
        return list_first_entry(&thread->namespaces_list, struct namespaces, list);
 }
 
-struct namespaces *thread__namespaces(const struct thread *thread)
+struct namespaces *thread__namespaces(struct thread *thread)
 {
        struct namespaces *ns;
 
-       down_read((struct rw_semaphore *)&thread->namespaces_lock);
+       down_read(&thread->namespaces_lock);
        ns = __thread__namespaces(thread);
-       up_read((struct rw_semaphore *)&thread->namespaces_lock);
+       up_read(&thread->namespaces_lock);
 
        return ns;
 }
@@ -271,13 +271,13 @@ static const char *__thread__comm_str(const struct thread *thread)
        return comm__str(comm);
 }
 
-const char *thread__comm_str(const struct thread *thread)
+const char *thread__comm_str(struct thread *thread)
 {
        const char *str;
 
-       down_read((struct rw_semaphore *)&thread->comm_lock);
+       down_read(&thread->comm_lock);
        str = __thread__comm_str(thread);
-       up_read((struct rw_semaphore *)&thread->comm_lock);
+       up_read(&thread->comm_lock);
 
        return str;
 }
index cf8375c..e97ef69 100644 (file)
@@ -76,7 +76,7 @@ static inline void thread__exited(struct thread *thread)
        thread->dead = true;
 }
 
-struct namespaces *thread__namespaces(const struct thread *thread);
+struct namespaces *thread__namespaces(struct thread *thread);
 int thread__set_namespaces(struct thread *thread, u64 timestamp,
                           struct namespaces_event *event);
 
@@ -93,7 +93,7 @@ int thread__set_comm_from_proc(struct thread *thread);
 int thread__comm_len(struct thread *thread);
 struct comm *thread__comm(const struct thread *thread);
 struct comm *thread__exec_comm(const struct thread *thread);
-const char *thread__comm_str(const struct thread *thread);
+const char *thread__comm_str(struct thread *thread);
 int thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
 size_t thread__fprintf(struct thread *thread, FILE *fp);