LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

ARM A7 PMU+perf简单记录

关键词:pmu,perf等等。

简单记录PMU及其内核驱动,内核中perf相关内容,以及两者是如何关联的。然后记录perf应用是如何和PMU硬件关联的,以及如何使用perf查看PMU结果。

A7 PMU概要

PMU作为一个扩展功能,是一种非侵入式的调试组件。

对PMU寄存器的访问可以通过CP15协处理器指令和Memory-Mapped地址。

更详细内容参考:

Arm CoreSight Performance Monitoring Unit Architecture》:关于PMU架构介绍,包括寄存器解释、规格、安全等等。

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》:介绍了PMU在Armv7-A/R中的实现。

  《Chapter C12 The Performance Monitors Extension》:PMU基本功能介绍
  《Appendix D2 Recommended Memory-mapped and External Debug Interfaces for the Performance Monitors》:PMU寄存器介绍。

kernel PMU

Linux内核中已经集成了PMU代码,需要配置的是dts部分:

pmu-a7 {
    compatible = "arm,cortex-a7-pmu";
    interrupts = <GIC_SPI 12 (IRQ_TYPE_LEVEL_HIGH)>;
    interrupt-patent = <&gic>;
}

PMU默认使用CP15寄存器即可进行配置,还提供了Memory-Mapped方式。

这里主要配置了中断号。

arm_pmu_hp_init()注册CPU HogPlug时online和offline回调函数。

arm_pmu_hp_init
    ->cpuhp_setup_state_multi
      ->arm_perf_starting_cpu
    ->arm_perf_teardown_cpu

armv7 pmu驱动根据dts compatile匹配到对应的函数初始化struct armpmu结构体,并从dts中获取中断并注册。

然后对接perf,提供相关初始化函数。

armv7_pmu_driver(builtin_platfrom_driver)
    ->armv7_pmu_device_probe
      ->arm_pmu_device_probe
        ->armpmu_alloc
          ->__armpmu_alloc--分配struct pmu结构体,并给相关的处理函数赋值。
        ->pmu_parse_irqs
          ->platform_get_irq--从dts中获取中断号。
            ->__platform_get_irq
              ->of_irq_get
                ->of_irq_parse_one
                  ->of_irq_parse_raw
                    ->request_irq
                      ->request_threaded_irq
                        ->__setup_irq
                          ->__irq_set_trigger
                            ->gic_set_type--irq-gic.c中chip->irq_set_type,型号为GIC400。
                              ->gic_configure_irq
->of_id->data--根据“arm,cortex-a7-pmu”指向armv7_a7_pmu_init,对struct arm_pmu进行初始化。
->armv7_a7_pmu_init--“arm,cortex-a7-pmu”对应的初始化函数。
->armv7pmu_init--给struct arm_pmu结构体函数赋值。
->armv7_read_num_pmnc_events--读取PMCR寄存器,获取PMU支持的事件数量。
->armpmu_request_irqs
          ->armpmu_request_irq--注册pmu中断处理函数armpmu_dispatch_irq()。
      ->armpmu_register
          ->cpu_pmu_init
            ->cpuhp_state_add_instance
          ->cpu_pm_pmu_register
        ->perf_pmu_register--和perf工具相关的初始化,包括一些函数指针初始化。
            ->perf_pmu_register
  ->armv7_pmu_of_device_ids--支持的dts compatible列表。

kernel perf

perf的sw/hw等事件注册初始化。

start_kernel
    ->perf_event_init
      ->idr_init
    ->perf_event_init_all_cpus
    ->perf_pmu_register(perf_swevent/perf_cpu_clock/perf_task_clock)
    ->perf_tp_register
    ->perf_event_init_cpu
->perf_swevent_init_cpu
->register_reboot_notifier--注册reboot回调函数。 ->init_hw_breakpoint--perf使用断点初始化。

内核提供系统调用perf_event_open()返回CPU+PID组合的文件句柄,应用通过此句柄设置刚兴趣的事件。

在kernel/events/core.c中:

/**
 * sys_perf_event_open - open a performance event, associate it to a task/cpu
 *
 * @attr_uptr:    event_id type attributes for monitoring/sampling
 * @pid:        target pid
 * @cpu:        target cpu
 * @group_fd:        group leader event fd
 */
SYSCALL_DEFINE5(perf_event_open,
        struct perf_event_attr __user *, attr_uptr,
        pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
{
}

perf文件操作函数集是perf_fops:

static const struct file_operations perf_fops = {
    .llseek            = no_llseek,
    .release        = perf_release,
    .read            = perf_read,--读取结果。
    .poll            = perf_poll,
    .unlocked_ioctl        = perf_ioctl,--对event进行配置。
    .compat_ioctl        = perf_compat_ioctl,
    .mmap            = perf_mmap,
    .fasync            = perf_fasync,--
};

perf 

perf命令源码位于内核tools/perf中,有多个子命令组成,下面以perf list hw为例,简单看一下是如何和PMU关联的。

main
    ->commands
      ->cmd_list(list)
        ->print_symbol_events--perf list hw命令对应函数。
->is_event_supported
       ->evsel__new
->evsel__open
->perf_event_open
->sys_perf_event_open--对应内核的perf_event_open系统调用。
->cmd_record(record)

PMU+perf使用

perf list hw查看A7支持的PMU事件,在armv7_pmuv2_event_attrs中包含30个events

armv7cortex_a7/br_immed_retired
armv7_cortex_a7/br_mis_pred/
armv7_cortex_a7/br_pred/
armv7_cortex_a7/br_return_retired/
armv7_cortex_a7/bus_access/
armv7_cortex_a7/bus_cycles/
armv7_cortex_a7/cid_write_retired/
armv7_cortex_a7/cpu_cycles/
armv7_cortex_a7/exc_return/
armv7_cortex_a7/exc_taken/
armv7_cortex_a7/inst_retired/
armv7_cortex_a7/inst_spec/
armv7_cortex_a7/l1d_cache/
armv7_cortex_a7/l1d_cache_refill/
armv7_cortex_a7/l1d_cache_wb/
armv7_cortex_a7/l1d_tlb_refill/
armv7_cortex_a7/l1i_cache/
armv7_cortex_a7/l1i_cache_refill/
armv7_cortex_a7/lli_tlb_refill/
armv7_cortex_a7/12d_cache/
armv7_cortex_a7/l1d_cache_refill/
armv7_cortex_a7/12d_cache_wb/
armv7_cortex_a7/ld_retired/
armv7_cortex_a7/mem_access/
armv7_cortex_a7/memory_error/
armv7_cortex_a7/pc_write_retired/
armv7_cortex_a7/st_retired/
armv7_cortex_a7/sw_incr/
armv7_cortex_a7/ttbr_write_retired/
armv7_cortex_a7/unaligned_ldst_retired/

 如果想查看某一程序执行时PMU事件,比如bus-cycles:

perf stat -e bus-cycles xxx

posted on 2023-04-23 23:59  ArnoldLu  阅读(868)  评论(0编辑  收藏  举报

导航