Glauber de Oliveira Costa wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hi Folks, > > Here's an updated version of the kvm paravirt clock infrastructure. Some > of the issues you all raised were addressed, some were not. This work > basically focus on general issues / clocksource, so don't expect to see > much new things here in the clock events area. > >
Me like. Please separate the guest and host parts; this allows backporting the guest part to older kernels. > + > +/* This is our clockevents structure. We only support one shot operation */ > +static struct clock_event_device kvm_clockevent = { > + .name = "kvm-timer", > + .features = CLOCK_EVT_FEAT_ONESHOT, > + .shift = 0, > + .mult = 1, > + .max_delta_ns = 0xffffffff, > + .min_delta_ns = 1000000, > Why this particular number? Doesn't it depend on the host's clocksource? > @@ -1564,6 +1566,36 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) > } > EXPORT_SYMBOL_GPL(kvm_emulate_halt); > > +static struct kvm_hv_clock hv_clock; > + > +static void kvm_write_guest_time(struct kvm_vcpu *vcpu) > +{ > + struct kvm *kvm = vcpu->kvm; > + struct timespec ts; > + void *clock_addr; > + > + if ((!kvm->clock_page) || !(kvm->clock_gpa)) > + return; > Why two checks? > + > + clock_addr = kmap(kvm->clock_page); > kmap_atomic() is much faster and more akpm-resistant. > + > + /* Updates version to the next odd number, indicating we're writing */ > + hv_clock.version++; > + /* Updating the tsc count is the first thing we do */ > + kvm_get_msr(vcpu, MSR_IA32_TIME_STAMP_COUNTER, &hv_clock.last_tsc); > + ktime_get_ts(&ts); > + hv_clock.now_ns = ts.tv_nsec + NSEC_PER_SEC * ts.tv_sec; > + hv_clock.wc_sec = get_seconds(); > + hv_clock.version++; > + WARN_ON(hv_clock.version & 1); > smp_wmb()s are missing here. The guest can trigger the WARN_ON() by being naughty with .version. > + > + memcpy(clock_addr, &hv_clock, sizeof(hv_clock)); > + mark_page_dirty(kvm, kvm->clock_gpa >> PAGE_SHIFT); > + kunmap(kvm->clock_page); > + > + kvm->time_needs_update = 0; > +} > + > int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) > { > unsigned long nr, a0, a1, a2, a3, ret; > @@ -1584,7 +1616,37 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) > a3 &= 0xFFFFFFFF; > } > > + ret = 0; > switch (nr) { > + case KVM_HCALL_REGISTER_CLOCK: { > + if (!irqchip_in_kernel(vcpu->kvm)) { > + ret = -1; > Return a proper KVM error. > + break; > + } > + > + vcpu->kvm->clock_gpa = a0; > i386 gpas are 64-bit. Better define it as a gfn (that absolves you of checking alignment too). > + vcpu->kvm->clock_page = gfn_to_page(vcpu->kvm, a0 >> > PAGE_SHIFT); > + > You're touching shared state here. Can probably cause problems if the guest turns nasty. > static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, > diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h > index c6f3fd8..8dec29f 100644 > --- a/include/asm-x86/kvm_para.h > +++ b/include/asm-x86/kvm_para.h > @@ -10,9 +10,12 @@ > * paravirtualization, the appropriate feature bit should be checked. > */ > #define KVM_CPUID_FEATURES 0x40000001 > +#define KVM_FEATURE_CLOCKEVENTS 0 > +#define KVM_FEATURE_CLOCKSOURCE 1 > > #ifdef __KERNEL__ > #include <asm/processor.h> > +extern void kvmclock_init(void); > > /* This instruction is vmcall. On non-VT architectures, it will generate a > * trap that we will then rewrite to the appropriate instruction. > @@ -29,6 +32,26 @@ > * noted by the particular hypercall. > */ > > +#define KVM_HCALL_REGISTER_CLOCK 0 > Let's start hypercall numbers at 1 to trap some cases on uninitialized data coming that way. > long ret; > diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h > index e4db25f..4c2afd0 100644 > --- a/include/linux/kvm_para.h > +++ b/include/linux/kvm_para.h > @@ -9,6 +9,10 @@ > * - kvm_para_available > */ > > +#define KVM_CPUID_FEATURES 0x40000001 > +#define KVM_FEATURE_CLOCKEVENTS 0 > +#define KVM_FEATURE_CLOCKSOURCE 1 > + > /* Return values for hypercalls */ > #define KVM_ENOSYS 1000 > Need to expose the capability to userspace as well via KVM_CHECK_EXTENSION so userspace will know to expose it to the guest. Finally, how about making this per-vcpu? That solves problems with tscs running differently on different cpus, you don't need the wmb()s on the host side, is faster for the guest due to less cacheline bouncing, I could go on forever. -- error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel