Re: [kvm-devel] [PATCH 0/2][KVM] guest time accounting

From: Laurent Vivier
Date: Mon Aug 13 2007 - 11:19:59 EST


Avi Kivity wrote:
> Laurent Vivier wrote:
>>> - perhaps the new fields should be guarded by a #ifdef CONFIG_HYPERVISOR
>>> (selected by CONFIG_KVM)? that way the (minor) additional overhead is
>>> only incurred if it can possibly be used. I imagine that our canine
>>> cousin will want to use this as well.
>>>
>>
>> There is also a CONFIG_VIRTUALIZATION and a CONFIG_VIRT_CPU_ACCOUNTING
>> (from
>> s390 and powerpc) Which one to use ?
>>
>
> Are these options for using the kernel as a guest or host? I'd guess
> the former.

I didn't find CONFIG_HYPERVISOR.
The good one seems to be CONFIG_VIRTUALIZATION that is used to activate CONFIG_KVM.

>> I'm wondering if we can have a more accurate accounting:
>>
>> - For the moment we add all system time since the previous entering to
>> the VCPU
>> to the guest time (and I guess there is some real system time in it ???)
>>
>> - Perhaps we can sum nanoseconds spent in the VCPU and add it to
>> cpustat when
>> these ns are greater than 1 ms ? (I'm trying to make something in this
>> way)
>>

Ingo (or other guru), could you have a look to the attached patch, it is what I
was thinking about when I wrote this.

Laurent
--
------------- Laurent.Vivier@xxxxxxxx --------------
"Software is hard" - Donald Knuth
Index: kvm/drivers/kvm/vmx.c
===================================================================
--- kvm.orig/drivers/kvm/vmx.c 2007-08-13 14:11:38.000000000 +0200
+++ kvm/drivers/kvm/vmx.c 2007-08-13 14:29:44.000000000 +0200
@@ -2052,6 +2052,7 @@
struct vcpu_vmx *vmx = to_vmx(vcpu);
u8 fail;
int r;
+ ktime_t now, delta;

preempted:
if (vcpu->guest_debug.enabled)
@@ -2078,6 +2079,7 @@
local_irq_disable();

vcpu->guest_mode = 1;
+ now = ktime_get();
if (vcpu->requests)
if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
vmx_flush_tlb(vcpu);
@@ -2198,6 +2200,8 @@
[cr2]"i"(offsetof(struct kvm_vcpu, cr2))
: "cc", "memory" );

+ delta = ktime_sub(ktime_get(), now);
+ current->vtime = ktime_add(current->vtime, delta);
vcpu->guest_mode = 0;
local_irq_enable();

Index: kvm/include/linux/sched.h
===================================================================
--- kvm.orig/include/linux/sched.h 2007-08-13 14:25:58.000000000 +0200
+++ kvm/include/linux/sched.h 2007-08-13 14:29:44.000000000 +0200
@@ -1192,6 +1192,9 @@
#ifdef CONFIG_FAULT_INJECTION
int make_it_fail;
#endif
+#ifdef CONFIG_VIRTUALIZATION
+ ktime_t vtime;
+#endif
};

/*
Index: kvm/kernel/sched.c
===================================================================
--- kvm.orig/kernel/sched.c 2007-08-13 14:11:38.000000000 +0200
+++ kvm/kernel/sched.c 2007-08-13 14:34:47.000000000 +0200
@@ -3212,6 +3212,29 @@
return ns;
}

+#ifdef CONFIG_VIRTUALIZATION
+static cputime_t account_guest_time(struct task_struct *p, cputime_t cputime)
+{
+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+ ktime_t kmsec = ktime_set(0, NSEC_PER_MSEC);
+ cputime_t cmsec = msecs_to_cputime(1);
+
+ while ((ktime_to_ns(p->vtime) >= NSEC_PER_MSEC) &&
+ (cputime_to_msecs(cputime) >= 1)) {
+ p->vtime = ktime_sub(p->vtime, kmsec);
+ p->utime = cputime_add(p->utime, cmsec);
+
+ cputime = cputime_sub(cputime, cmsec);
+
+ cpustat->guest = cputime64_add(cpustat->guest,
+ cputime_to_cputime64(cmsec));
+ cpustat->user = cputime64_add(cpustat->user,
+ cputime_to_cputime64(cmsec));
+ }
+ return cputime;
+}
+#endif
+
/*
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
@@ -3246,6 +3269,10 @@
struct rq *rq = this_rq();
cputime64_t tmp;

+#ifdef CONFIG_VIRTUALIZATION
+ cputime = account_guest_time(p, cputime);
+#endif
+
p->stime = cputime_add(p->stime, cputime);

/* Add system time to cpustat. */
Index: kvm/drivers/kvm/svm.c
===================================================================
--- kvm.orig/drivers/kvm/svm.c 2007-08-13 14:31:16.000000000 +0200
+++ kvm/drivers/kvm/svm.c 2007-08-13 14:33:10.000000000 +0200
@@ -1392,6 +1392,7 @@
u16 gs_selector;
u16 ldt_selector;
int r;
+ ktime_t now, delta;

again:
r = kvm_mmu_reload(vcpu);
@@ -1404,6 +1405,7 @@
clgi();

vcpu->guest_mode = 1;
+ now = ktime_get();
if (vcpu->requests)
if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
svm_flush_tlb(vcpu);
@@ -1536,6 +1538,8 @@
#endif
: "cc", "memory" );

+ delta = ktime_sub(ktime_get(), now);
+ current->vtime = ktime_add(current->vtime, delta);
vcpu->guest_mode = 0;

if (vcpu->fpu_active) {

Attachment: signature.asc
Description: OpenPGP digital signature