PMU寄存器
1 | PMCEID0_EL0 event有无寄存器,每个bit表示对应的event有没有支持 |
基本逻辑
KVM中对PMU的模拟思路和其他设备的模拟思路是一致的,通过device相关的ioctl创建设备
和配置设备属性,CPU在EL1访问PMU相关寄存器的时候会trap的KVM进行模拟,因为host/guest
是共享PMU物理硬件的,vCPU上下线时需要保存和恢复PMU寄存器的状态。
整体的ARM KVM框架逻辑可以参考这里
注意一下几点,vPMU的初始化和配置通过KVM_ARM_VCPU_PMU_V3_*的ioctl进行,PMU相关的
系统寄存器的模拟逻辑在kvm_handle_sys_reg。
PMU vCPU上下线时保存和恢复寄存器的逻辑不是很直白,它应该在vCPU线程和perf相关的
sched_ini/sched_out的回调函数里。这个行为和KVM里PMU的模拟方式有直接的联系。
todo: PMU模拟方式。
代码分析
PMU相关的代码在arch/arm64/kvm/pmu.c、pmu-emul.c中。
vCPU创建时,kvm_vm_ioctl_create_vcpu->kvm_arch_vcpu_create:
1 | kvm_pmu_vcpu_init |
vCPU初始化时,kvm_arch_vcpu_ioctl_vcpu_init->kvm_vcpu_set_target->kvm_reset_vcpu:
1 | kvm_pmu_vcpu_reset |
对于vCPU fd ioctl的KVM_HAS/SET/GET_DEVICE_ATTR:
1 | KVM_SET_DEVICE_ATTR/KVM_ARM_VCPU_PMU_V3_CTRL -> kvm_arm_pmu_v3_set_attr: |
PMU的模拟逻辑。
杂项问题
KVM对guest呈现的PMU version的问题。KVM从host获得PMU的硬件版本,并把这个信息做一定
的限制后保存在kvm->kvm_arch->id_reg.dfr0寄存器中,后续KVM都是从这里拿vPMU的版本
信息。
1 | /* vCPU初始化的时候,在reset里从host拿信息并保存到如上KVM结构里 */ |