On Tue, Oct 13, 2009 at 10:51:48PM -0700, Kurt Kiefer wrote:
> -----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!
Can't see anything wrong. Perhaps the userspace exit breaks a latency
assumption of that algorithm (can you translate it to function names?).
Try the tsc.flat test (from qemu-kvm.git):
x86_64-softmmu/qemu-system-x86_64 -chardev file,path=/tmp/log.txt,id=testlog \
-device testdev,chardev=testlog -kernel kvm/user/test/x86/tsc.flat
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html