Get multiple Performance Monitoring Interrupt on qemu-kvv
Posted: Tue Apr 17, 2018 6:31 am
I am not able to get multiple performance monitoring interrupt (PMI - especially instruction counter) in my guest when running on qemu (kvm-enabled, cpu = host) unless I reset the cpu (triple fault).
The code below is intended to reprogram another PMI when it fires. It works fine on real machine but on qemu, after the first received PMI, no other follows. the only way to get another PMI, until now is to reset the CPU.
However, notice that the pmc register mask bit is cleared (perf_reg[bit 16] = 0) just after the first pmi. This is not normal, according to Intel specifications.
Any Idea?
The code below is intended to reprogram another PMI when it fires. It works fine on real machine but on qemu, after the first received PMI, no other follows. the only way to get another PMI, until now is to reset the CPU.
Code: Select all
// This code handles the PMI and programs another one.
pmi_handler() {
Console::print("PMI counter %llx perf_reg %x", Msr::read<uint64>(Msr::MSR_PERF_FIXED_CTR0),
read(LAPIC_LVT_PERFM)); // PMI counter 10 perf_reg a4
program_pmi();
Console::print("perf_reg %x", read(LAPIC_LVT_PERFM)); // perf_reg a4
}
program_pmi(){
uint64 msr_glb = Msr::read<uint64>(Msr::MSR_PERF_GLOBAL_CTRL);
Msr::write(Msr::MSR_PERF_GLOBAL_CTRL, msr_glb | (1ull<<32));
Msr::write(Msr::MSR_PERF_GLOBAL_OVF_CTRL, Msr::read<uint64>(Msr::MSR_PERF_GLOBAL_OVF_CTRL) & ~(1UL<<32));
set_perf_lvt(LAPIC_LVT_PERFM, DLV_FIXED, VEC_LVT_PERFM); // clear the pmc register mask bit
Msr::write(Msr::MSR_PERF_FIXED_CTR0, 0xffffffff0000);
Msr::write(Msr::MSR_PERF_FIXED_CTRL, 0xa);
}
Any Idea?