Re: Added VM Exit on RDTSC, trouble handling in userspace

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux