-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi all,
In short, I have a need for trapping RDTSC with a VM Exit and this
works, but I'm having trouble handling it in userspace. I have added
the hooks I need (I only care about VMX right now), but a piece of the
puzzle is missing and I don't know which. When I go back to userspace,
it's triggering a different (faulty) execution vs. handling only in
the kernel. Here's what I've done:
1. Added the CPU_BASED_RDTSC_EXITING flag to
MSR_IA32_VMX_PROCBASED_CTLS in vmx.c:setup_vmcs_config()
2. Defined KVM_EXIT_RDTSC, and hooked into EXIT_REASON_RDTSC my
handler for the exit:
static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run) = {
// ...
[EXIT_REASON_RDTSC] = handle_rdtsc,
// ...
}
static int handle_rdtsc(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
u64 data;
if (vmx_get_msr(vcpu, MSR_IA32_TIME_STAMP_COUNTER, &data)) {
kvm_inject_gp(vcpu, 0);
return 1;
}
vcpu->run->exit_reason = KVM_EXIT_RDTSC;
vcpu->arch.regs[VCPU_REGS_RAX] = data & -1u;
vcpu->arch.regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
skip_emulated_instruction(vcpu);
// flag a need for userspace invervention
// note: this works when we return 1 and we don't involve userspace
return 0;
}
3. Handle KVM_EXIT_RDTSC in libkvm.c:kvm_run() :
case KVM_EXIT_RDTSC:
r = handle_rdtsc_usp(kvm, vcpu, env);
break;
via a handler where I do _nothing_ :
static int handle_rdtsc_usp(kvm_context_t kvm, int vcpu, void *data)
{
return 0;
}
All well and good, right? I can add print statements to my userspace
handle_rtsc_usp() and see I get in there just fine. However, when I
try to boot Linux, the following code is called over and over and
over, and Linux will never load:
Breakpoint 4, 0x00000000c01103d3 in ?? ()
(gdb) x/10i $rip-10
0xc01103c9: lea 0x0(%rdi,%riz,1),%edi
0xc01103d0: push %rbp
0xc01103d1: mov %esp,%ebp
0xc01103d3: rdtsc
0xc01103d5: pop %rbp
0xc01103d6: retq
If I only handle the exit in the kernel (by returning 1 from
handle_rdtsc()), everything works and Linux will load! I counted the
number of RDTSC exits before linux fully loads to be somewhere around
200000. If I exit all the way to userspace (return 0 in my
handle_rdtsc()) that count is infinitely surpassed in number of exits,
wall time, and the value of RDTSC.
So is anything glaringly wrong with my modifications? Maybe there is
there some extra state that needs to be restored on VM entry? Is there
an interrupt flag that needs to be cleared? Maybe I need to do
something with kvm_run.if_flag or
kvm_run.ready_for_interrupt_injection? Please, I need help, I'm losing
sleep over this!
Thanks,
Kurt
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)
iEYEARECAAYFAkrVZvQACgkQYFGmU9mnI1FqvgCcC/+PswoXHQ5kVgv5tC6UadiA
KKgAoKrLgsYSJN0+1d0pox9vzsLHoQIc
=cQzR
-----END PGP SIGNATURE-----
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html