Googler et ack-ing est terminé! J'ai une réponse.
Mais permettez-moi tout d'abord de clarifier un peu plus le but de la question: je veux distinguer clairement les processus indépendants du système et leurs compteurs de performance. Par exemple, un noyau d'un processeur, un périphérique non-core (appris récemment), un noyau ou une application utilisateur sur le processeur, un bus (= contrôleur de bus), un disque dur sont tous des processus indépendants, ils ne sont pas synchronisés par une horloge . Et de nos jours, tous ont probablement un compteur de surveillance de processus (PMC). J'aimerais comprendre de quels processus proviennent les compteurs. (Il est également utile pour la recherche sur Google: le "vendeur" d'une chose la met à zéro.)
En outre, le matériel utilisé pour la recherche: Ubuntu 14.04, linux 3.13.0-103-generic, processeur Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz( à partir /proc/cpuinfo, il dispose de 2 noyaux physiques et 4 virtuelles - la matière physique ici).
Terminologie, ce que la question implique
D'Intel:
- le processeur est un - coreappareil (c'est 1 appareil / processus) et un tas d'- uncoreappareils ,- corec'est ce qui exécute le programme (horloge, ALU, registres, etc.),- uncoresont des appareils mis sous tension, proches du processeur pour la vitesse et une faible latence (la vraie raison est "parce que le fabricant peut le faire"); si j'ai bien compris, c'est essentiellement le Northbridge, comme sur la carte mère du PC, plus les caches; et AMD appelle en fait ces appareils NorthBridge- instead ofuncore`;
 
- uboxqui apparaît dans mon- sysfs
 - $ find /sys/devices/ -type d -name events 
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
 - - est un - uncoreappareil qui gère Last Level Cache (LLC, le dernier avant de toucher la RAM); J'ai 2 cœurs, donc 2 LLC et 2- ubox;
 
- L'unité de surveillance du processeur (PMU) est un appareil séparé qui surveille les opérations d'un processeur et les enregistre dans le compteur de surveillance du processeur (PMC) (compte les échecs de cache, les cycles du processeur, etc.); ils existent sur - coreet les- uncoreappareils; les- corecelles sont accessibles avec- rdpmc(lecture PMC) instruction; les- uncore, puisque ces dispositifs dépendent du processeur réel à portée de main, sont accessibles via des registres spécifiques au modèle (MSR) via- rdmsr(naturellement);
 - apparemment, le flux de travail avec eux se fait via des paires de registres - 1 jeux de registres qui événements le compteur compte, 2 registre est la valeur dans le compteur; le compteur peut être configuré pour incrémenter après un tas d'événements, pas seulement 1; + il y a des interruptions / technologies remarquant des débordements dans ces compteurs; 
- on en trouvera plus dans le chapitre 18 du manuel "IA-32 Software Developer's Manual Vol 3B" "SURVEILLANCE DES PERFORMANCES"; - aussi, le format du MSR concrètement pour ces - uncorePMC pour la version "Architectural Performance Monitoring Version 1" (il y a les versions 1-4 dans le manuel, je ne sais pas laquelle est mon processeur) est décrit dans "Figure 18-1. Disposition de IA32_PERFEVTSELx MSR "(page 18-3 dans la mienne), et la section" 18.2.1.2 Événements de performances architecturales prédéfinies "avec" Tableau 18-1. Codages UMask et Event Select pour les événements de performances architecturales prédéfinis ", qui montre la les événements qui apparaissent comme- Hardware eventdans- perf list.
 
Depuis le noyau Linux:
- le noyau a un système (abstraction / couche) pour gérer les compteurs de performance d'origine différente, à la fois logiciel (noyau) et matériel, il est décrit dans - linux-source-3.13.0/tools/perf/design.txt; un événement dans ce système est défini comme- struct perf_event_attr(fichier- linux-source-3.13.0/include/uapi/linux/perf_event.h), dont la partie principale est probablement un- __u64 configchamp - il peut contenir à la fois une définition d'événement spécifique au processeur (le mot 64 bits au format décrit sur les figures d'Intel) ou un événement du noyau
 - 
  - Le MSB du mot de configuration signifie si le reste contient [l'événement CPU ou noyau brut] 
 - l'événement du noyau défini avec 7 bits pour le type et 56 pour l'identifiant de l'événement, qui sont - enum-s dans le code, qui dans mon cas sont:
 - $ ak PERF_TYPE linux-source-3.13.0/include/
...
linux-source-3.13.0/include/uapi/linux/perf_event.h
29: PERF_TYPE_HARDWARE      = 0,
30: PERF_TYPE_SOFTWARE      = 1,
31: PERF_TYPE_TRACEPOINT    = 2,
32: PERF_TYPE_HW_CACHE      = 3,
33: PERF_TYPE_RAW           = 4,
34: PERF_TYPE_BREAKPOINT    = 5,
36: PERF_TYPE_MAX,         /* non-ABI */
 - ( - akest mon alias- ack-grep, qui est le nom de- acksur Debian; et- ackest génial);
 - dans le code source du noyau, on peut voir des opérations comme "enregistrer tous les PMU découverts sur le système" et les types de structure - struct pmu, qui sont passés à quelque chose comme- int perf_pmu_register(struct pmu *pmu, const char *name, int type)- ainsi, on pourrait simplement appeler ce système "PMU du noyau", qui serait une agrégation de toutes les UGP du système; mais ce nom pourrait être interprété comme un système de surveillance des opérations du noyau, ce qui serait trompeur;
 - appelons ce sous-système - perf_eventspour plus de clarté;
 
- comme tout sous-système de noyau, ce sous-système peut être exporté vers - sysfs(qui est conçu pour exporter des sous-systèmes de noyau pour que les gens les utilisent); et c'est ce que sont ces- eventsrépertoires dans mon- /sys/- le sous-système exporté (parties de?)- perf_events;
 
- en outre, l'utilitaire d'espace utilisateur - perf(intégré à Linux) est toujours un programme distinct et possède ses propres abstractions; il représente un événement demandé pour la surveillance par l'utilisateur en tant que- perf_evsel(fichiers- linux-source-3.13.0/tools/perf/util/evsel.{h,c}) - cette structure a un champ- struct perf_event_attr attr;, mais aussi un champ comme- struct cpu_map *cpus;c'est ainsi que l'- perfutilitaire attribue un événement à tous les CPU ou à certains CPU.
 
Réponse
- En effet, - Hardware cache eventsont des "raccourcis" vers les événements des périphériques de cache (- uboxdes périphériques d'Intel- uncore), qui sont spécifiques au processeur, et sont accessibles via le protocole- Raw hardware event descriptor. Et- Hardware eventsont plus stables au sein de l'architecture, qui, si je comprends bien, nomme les événements de l'- coreappareil. Il n'y a pas d'autres "raccourcis" dans mon noyau- 3.13vers d'autres- uncoreévénements et compteurs. Tous les autres -- Softwareet- Tracepoints- sont des événements du noyau.
 - Je me demande si le - corede »- Hardware eventde s sont accessibles via le même- Raw hardware event descriptorprotocole. Ils pourraient ne pas - puisque le compteur / PMU est assis- core, il est peut-être accessible différemment. Par exemple, avec cette- rdpmuinstruction, au lieu de- rdmsr, qui accède- uncore. Mais ce n'est pas si important.
 
- Kernel PMU eventne sont que les événements, qui sont exportés dans- sysfs. Je ne sais pas comment cela se fait (automatiquement par le noyau tous les PMC découverts sur le système, ou simplement quelque chose de codé en dur, et si j'ajoute un- kprobe- est-il exporté? Etc.). Mais l'essentiel est qu'il s'agit des mêmes événements que- Hardware eventtout autre événement du- perf_eventsystème interne .
 - Et je ne sais pas ce que ces - $ ls /sys/devices/uncore_cbox_0/events
clockticks
 - sont. 
Détails sur Kernel PMU event
La recherche dans le code conduit à:
$ ak "Kernel PMU" linux-source-3.13.0/tools/perf/
linux-source-3.13.0/tools/perf/util/pmu.c                                                            
629:                printf("  %-50s [Kernel PMU event]\n", aliases[j]);
- ce qui se passe dans la fonction
void print_pmu_events(const char *event_glob, bool name_only) {
   ...
        while ((pmu = perf_pmu__scan(pmu)) != NULL)
                list_for_each_entry(alias, &pmu->aliases, list) {...}
   ... 
   /* b.t.w. list_for_each_entry is an iterator
    * apparently, it takes a block of {code} and runs over some lost
    * Ruby built in kernel!
    */
    // then there is a loop over these aliases and
    loop{ ... printf("  %-50s [Kernel PMU event]\n", aliases[j]); ... }
}
et se perf_pmu__scantrouve dans le même fichier:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
    ...
                pmu_read_sysfs(); // that's what it calls
}
- qui se trouve également dans le même fichier:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
C'est ça.
Détails sur Hardware eventetHardware cache event
Apparemment, cela Hardware eventvient de ce qu'Intel appelle "Evénements de performances architecturales prédéfinies", 18.2.1.2 dans le Manuel du développeur du logiciel IA-32 Vol 3B. Et "18.1 APERÇU DE LA SURVEILLANCE DES PERFORMANCES" du manuel les décrit comme:
  La deuxième classe de capacités de surveillance des performances est appelée surveillance des performances architecturales. Cette classe prend en charge les mêmes utilisations d'échantillonnage d'événements de comptage et d'interruption, avec un plus petit ensemble d'événements disponibles. Le comportement visible des événements de performances architecturales est cohérent dans toutes les implémentations de processeur. La disponibilité des capacités de surveillance des performances architecturales est énumérée à l'aide du CPUID.0AH. Ces événements sont traités dans la section 18.2.
- l'autre type est:
  À partir des processeurs Intel Core Solo et Intel Core Duo, il existe deux classes de capacités de surveillance des performances. La première classe prend en charge les événements pour surveiller les performances en utilisant le comptage ou l'utilisation d'échantillonnage d'événements basé sur les interruptions. Ces événements sont non architecturaux et varient d'un modèle de processeur à l'autre ...
Et ces événements ne sont en effet que des liens vers des événements matériels "bruts" sous-jacents, accessibles via l' perfutilitaire as Raw hardware event descriptor.
Pour vérifier celui-ci regarde linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c:
/*
 * Intel PerfMon, used on Core and later.
 */
static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
{
    [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
    [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
    [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
    [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
    ...
}
- et 0x412ese trouve exactement dans le "Tableau 18-1. Codages UMask et Event Select pour les événements de performances architecturales prédéfinis" pour "LLC Misses":
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
                        4 | LLC Misses | 41H   | 2EH
- Hest pour hex. Tous les 7 sont dans la structure, plus [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *. (Le nom est un peu différent, les adresses sont les mêmes.)
Ensuite, les Hardware cache events sont dans des structures comme (dans le même fichier):
static __initconst const u64 snb_hw_cache_extra_regs
                            [PERF_COUNT_HW_CACHE_MAX]
                            [PERF_COUNT_HW_CACHE_OP_MAX]
                            [PERF_COUNT_HW_CACHE_RESULT_MAX] =
{...}
- lequel devrait être pour le pont de sable?
L'un d'eux - snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]est rempli SNB_DMND_WRITE|SNB_L3_ACCESS, d'où les def-s ci-dessus:
#define SNB_L3_ACCESS           SNB_RESP_ANY
#define SNB_RESP_ANY            (1ULL << 16)                                                                            
#define SNB_DMND_WRITE          (SNB_DMND_RFO|SNB_LLC_RFO)
#define SNB_DMND_RFO            (1ULL << 1)
#define SNB_LLC_RFO             (1ULL << 8)
qui devrait être égal à 0x00010102, mais je ne sais pas comment le vérifier avec une table.
Et cela donne une idée de la façon dont il est utilisé dans perf_events:
$ ak hw_cache_extra_regs linux-source-3.13.0/arch/x86/kernel/cpu/
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.c
50:u64 __read_mostly hw_cache_extra_regs
292:    attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.h
521:extern u64 __read_mostly hw_cache_extra_regs
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
272:static __initconst const u64 snb_hw_cache_extra_regs
567:static __initconst const u64 nehalem_hw_cache_extra_regs
915:static __initconst const u64 slm_hw_cache_extra_regs
2364:       memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2365:              sizeof(hw_cache_extra_regs));
2407:       memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
2408:              sizeof(hw_cache_extra_regs));
2424:       memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2425:              sizeof(hw_cache_extra_regs));
2452:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2453:              sizeof(hw_cache_extra_regs));
2483:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2484:              sizeof(hw_cache_extra_regs));
2516:       memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
$
Les memcpys sont terminés __init int intel_pmu_init(void) {... case:...}.
C'est attr->config1un peu bizarre. Mais il est là, dans perf_event_attr(même linux-source-3.13.0/include/uapi/linux/perf_event.hfichier):
...
    union {
            __u64           bp_addr;
            __u64           config1; /* extension of config */                                                      
    };
    union {
            __u64           bp_len;
            __u64           config2; /* extension of config1 */
    };
...
Ils sont enregistrés dans le perf_eventssystème du noyau avec des appels à int perf_pmu_register(struct pmu *pmu, const char *name, int type)(définis dans linux-source-3.13.0/kernel/events/core.c:):
- static int __init init_hw_perf_events(void)(fichier- arch/x86/kernel/cpu/perf_event.c) avec appel- perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 
- static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)(fichier- arch/x86/kernel/cpu/perf_event_intel_uncore.c, il y en a aussi- arch/x86/kernel/cpu/perf_event_amd_uncore.c) avec appel- ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
 
Donc, finalement, tous les événements proviennent du matériel et tout va bien. Mais ici, on pourrait remarquer: pourquoi avons-nous LLC-loadsen perf listet non ubox1 LLC-loads, car ce sont des événements HW et ils viennent réellement d' uboxes?
C'est une chose de l' perfutilité et de sa perf_evselstructure: lorsque vous demandez un événement HW à perfvous, définissez l'événement à partir de quels processeurs vous le souhaitez (par défaut c'est tout), et il configure perf_evselavec l'événement et les processeurs demandés, puis lors de l'agrégation est additionne les compteurs de tous les processeurs perf_evsel(ou fait d'autres statistiques avec eux).
On peut le voir dans tools/perf/builtin-stat.c:
/*
 * Read out the results of a single counter:
 * aggregate counts across CPUs in system-wide mode
 */
static int read_counter_aggr(struct perf_evsel *counter)
{
    struct perf_stat *ps = counter->priv;
    u64 *count = counter->counts->aggr.values;
    int i;
    if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
                           thread_map__nr(evsel_list->threads), scale) < 0)
            return -1;
    for (i = 0; i < 3; i++)
            update_stats(&ps->res_stats[i], count[i]);
    if (verbose) {
            fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
                    perf_evsel__name(counter), count[0], count[1], count[2]);
    }
    /*
     * Save the full runtime - to allow normalization during printout:
     */
    update_shadow_stats(counter, count);
    return 0;
}
(Donc, pour l'utilitaire, perfun "compteur unique" n'est même pas un perf_event_attr, qui est une forme générale, s'adaptant aux événements SW et HW, c'est un événement de votre requête - les mêmes événements peuvent provenir de différents appareils et ils sont agrégés .)
Également un avis: struct perf_evselcontient seulement 1 struct perf_evevent_attr, mais il a également un champ struct perf_evsel *leader;- il est imbriqué. Il existe une fonctionnalité de "groupes d'événements (hiérarchiques)" dans perf_events, lorsque vous pouvez répartir un groupe de compteurs ensemble, afin qu'ils puissent être comparés entre eux et ainsi de suite. Je ne sais pas comment cela fonctionne avec des événements indépendants de kernel, core, ubox. Mais cette imbrication l' perf_evselest. Et, très probablement, c'est ainsi que perfgère une requête de plusieurs événements ensemble.