* [PATCH 1/2] cpu steal time accounting
@ 2006-02-21 0:51 Rik van Riel
2006-02-21 17:42 ` Keir Fraser
0 siblings, 1 reply; 20+ messages in thread
From: Rik van Riel @ 2006-02-21 0:51 UTC (permalink / raw)
To: xen-devel
Allow guest domains to get information from the hypervisor on how much
cpu time their virtual cpus have used. This is needed to estimate the
cpu steal time.
Signed-off-by: Rik van Riel <riel@redhat.com>
--- xen/include/public/vcpu.h.steal 2006-02-07 18:01:41.000000000 -0500
+++ xen/include/public/vcpu.h 2006-02-17 13:51:45.000000000 -0500
@@ -51,6 +51,14 @@
/* Returns 1 if the given VCPU is up. */
#define VCPUOP_is_up 3
+/*
+ * Get information on how much CPU time this VCPU has used, etc...
+ *
+ * @extra_arg == pointer to an empty dom0_getvcpuinfo_t, the "OUT" variables
+ * of which filled in with scheduler info.
+ */
+#define VCPUOP_cpu_info 4
+
#endif /* __XEN_PUBLIC_VCPU_H__ */
/*
--- xen/common/domain.c.steal 2006-02-07 18:01:40.000000000 -0500
+++ xen/common/domain.c 2006-02-17 13:52:44.000000000 -0500
@@ -451,8 +451,24 @@
case VCPUOP_is_up:
rc = !test_bit(_VCPUF_down, &v->vcpu_flags);
break;
+
+ case VCPUOP_cpu_info:
+ {
+ struct dom0_getvcpuinfo vi = { 0, };
+ vi.online = !test_bit(_VCPUF_down, &v->vcpu_flags);
+ vi.blocked = test_bit(_VCPUF_blocked, &v->vcpu_flags);
+ vi.running = test_bit(_VCPUF_running, &v->vcpu_flags);
+ vi.cpu_time = v->cpu_time;
+ vi.cpu = v->processor;
+ rc = 0;
+
+ if ( copy_to_user(arg, &vi, sizeof(dom0_getvcpuinfo_t)) )
+ rc = -EFAULT;
+ break;
+ }
}
+
return rc;
}
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 1/2] cpu steal time accounting
@ 2006-02-21 9:05 Tian, Kevin
2006-02-21 12:56 ` Rik van Riel
0 siblings, 1 reply; 20+ messages in thread
From: Tian, Kevin @ 2006-02-21 9:05 UTC (permalink / raw)
To: Rik van Riel, xen-devel
Why do you need to add a new VCPUOP while doing same thing as DOM0_GETVCPUINFO?
Thanks,
Kevin
>-----Original Message-----
>From: xen-devel-bounces@lists.xensource.com
>[mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Rik van Riel
>Sent: 2006年2月21日 8:51
>To: xen-devel@lists.xensource.com
>Subject: [Xen-devel] [PATCH 1/2] cpu steal time accounting
>
>Allow guest domains to get information from the hypervisor on how much
>cpu time their virtual cpus have used. This is needed to estimate the
>cpu steal time.
>
>Signed-off-by: Rik van Riel <riel@redhat.com>
>
>--- xen/include/public/vcpu.h.steal 2006-02-07 18:01:41.000000000 -0500
>+++ xen/include/public/vcpu.h 2006-02-17 13:51:45.000000000 -0500
>@@ -51,6 +51,14 @@
> /* Returns 1 if the given VCPU is up. */
> #define VCPUOP_is_up 3
>
>+/*
>+ * Get information on how much CPU time this VCPU has used, etc...
>+ *
>+ * @extra_arg == pointer to an empty dom0_getvcpuinfo_t, the "OUT" variables
>+ * of which filled in with scheduler info.
>+ */
>+#define VCPUOP_cpu_info 4
>+
> #endif /* __XEN_PUBLIC_VCPU_H__ */
>
> /*
>--- xen/common/domain.c.steal 2006-02-07 18:01:40.000000000 -0500
>+++ xen/common/domain.c 2006-02-17 13:52:44.000000000 -0500
>@@ -451,8 +451,24 @@
> case VCPUOP_is_up:
> rc = !test_bit(_VCPUF_down, &v->vcpu_flags);
> break;
>+
>+ case VCPUOP_cpu_info:
>+ {
>+ struct dom0_getvcpuinfo vi = { 0, };
>+ vi.online = !test_bit(_VCPUF_down, &v->vcpu_flags);
>+ vi.blocked = test_bit(_VCPUF_blocked, &v->vcpu_flags);
>+ vi.running = test_bit(_VCPUF_running, &v->vcpu_flags);
>+ vi.cpu_time = v->cpu_time;
>+ vi.cpu = v->processor;
>+ rc = 0;
>+
>+ if ( copy_to_user(arg, &vi, sizeof(dom0_getvcpuinfo_t)) )
>+ rc = -EFAULT;
>+ break;
>+ }
> }
>
>+
> return rc;
> }
>
>
>_______________________________________________
>Xen-devel mailing list
>Xen-devel@lists.xensource.com
>http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 1/2] cpu steal time accounting
2006-02-21 9:05 Tian, Kevin
@ 2006-02-21 12:56 ` Rik van Riel
0 siblings, 0 replies; 20+ messages in thread
From: Rik van Riel @ 2006-02-21 12:56 UTC (permalink / raw)
To: Tian, Kevin; +Cc: xen-devel
On Tue, 21 Feb 2006, Tian, Kevin wrote:
> Why do you need to add a new VCPUOP while doing same thing as
> DOM0_GETVCPUINFO?
Because the dom0_ops only work for dom0 and reworking that
function to allow non-privileged domains to get info just
on themselves would end up being a way uglier patch.
--
All Rights Reversed
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH 1/2] cpu steal time accounting
@ 2006-02-21 14:06 Tian, Kevin
0 siblings, 0 replies; 20+ messages in thread
From: Tian, Kevin @ 2006-02-21 14:06 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
>From: Rik van Riel [mailto:riel@redhat.com]
>Sent: 2006年2月21日 20:56
>
>On Tue, 21 Feb 2006, Tian, Kevin wrote:
>
>> Why do you need to add a new VCPUOP while doing same thing as
>> DOM0_GETVCPUINFO?
>
>Because the dom0_ops only work for dom0 and reworking that
>function to allow non-privileged domains to get info just
>on themselves would end up being a way uglier patch.
>
See your point now. Since physical processor id is also exported in your patch, will it cause a trend to allow non-privileged domain to query more physical context information about domain itself? Like GETDOMAININFO, GETVCPUCONTEXT, etc. For example, guest may use gap info between max_pages and tot_pages to decide whether eagerly adding free pages as caches. It can also consider that info as an indicator of some type of tight resource contention. If it's the usage model, maybe we can consider move them out of dom0_ prefix and make it common.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-21 0:51 Rik van Riel
@ 2006-02-21 17:42 ` Keir Fraser
2006-02-21 19:32 ` Rik van Riel
0 siblings, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-21 17:42 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
On 21 Feb 2006, at 00:51, Rik van Riel wrote:
> Allow guest domains to get information from the hypervisor on how much
> cpu time their virtual cpus have used. This is needed to estimate the
> cpu steal time.
>
> Signed-off-by: Rik van Riel <riel@redhat.com>
Probably we'll kill off the dom0_op instead (or at least rename the
info structure and leave the old dom0_op just as a legacy placeholder
for a while).
Looking at the other patch, I think I'm missing higher level context
regarding what this patch is about. I grepped around for
account_steal_time() -- looks like it's currently used by s390, but as
part of a rather bigger patch that also calls
account_user_time/account_system_time.
Is there a lkml thread I should read to get up to speed on this? Should
your patch be using those other functions in this account_foo_time api?
What functionality do we currently miss by not targetting that api?
thanks,
Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-21 17:42 ` Keir Fraser
@ 2006-02-21 19:32 ` Rik van Riel
2006-02-21 21:24 ` Diwaker Gupta
2006-02-22 9:00 ` Keir Fraser
0 siblings, 2 replies; 20+ messages in thread
From: Rik van Riel @ 2006-02-21 19:32 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
On Tue, 21 Feb 2006, Keir Fraser wrote:
> Looking at the other patch, I think I'm missing higher level context
> regarding what this patch is about. I grepped around for
> account_steal_time() -- looks like it's currently used by s390, but as
> part of a rather bigger patch that also calls
> account_user_time/account_system_time.
Basically steal time is the amount of time when:
1) we had a runnable task, but
2) it was not running, because our vcpu was scheduled
away by the hypervisor
Thus, steal time measures how much a particular workload
inside a virtual machine is impacted by contention on the
cpu between different virtual machines.
It also makes sure that time the vcpu itself was not running
is not erroneously accounted to the currently running process,
which matters when a user is trying to determine how much CPU
time a particular task needs.
--
All Rights Reversed
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-21 19:32 ` Rik van Riel
@ 2006-02-21 21:24 ` Diwaker Gupta
2006-02-22 9:00 ` Keir Fraser
1 sibling, 0 replies; 20+ messages in thread
From: Diwaker Gupta @ 2006-02-21 21:24 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
> Basically steal time is the amount of time when:
> 1) we had a runnable task, but
> 2) it was not running, because our vcpu was scheduled
> away by the hypervisor
Just FYI: XenMon provides a similar metric which we call Waiting Time
-- the time a domain was runnable but not running. Of course, yours is
a different use case, since you want to query the stolen time from
within the guest.
Diwaker
--
Web/Blog/Gallery: http://floatingsun.net/blog
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-21 19:32 ` Rik van Riel
2006-02-21 21:24 ` Diwaker Gupta
@ 2006-02-22 9:00 ` Keir Fraser
2006-02-22 14:27 ` Rik van Riel
1 sibling, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-22 9:00 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
On 21 Feb 2006, at 19:32, Rik van Riel wrote:
> Basically steal time is the amount of time when:
> 1) we had a runnable task, but
> 2) it was not running, because our vcpu was scheduled
> away by the hypervisor
>
> Thus, steal time measures how much a particular workload
> inside a virtual machine is impacted by contention on the
> cpu between different virtual machines.
>
> It also makes sure that time the vcpu itself was not running
> is not erroneously accounted to the currently running process,
> which matters when a user is trying to determine how much CPU
> time a particular task needs.
Is accounting user/system time an unnecessary extra? I guess we already
do it by sampling at tick granularity anyway?
Should 'steal time' include blocked time when the guest had no work to
execute?
Also, given the logic currently only triggers when the guest detects it
'missed a tick', would it be good enough simply to account
#missed_ticks as steal time. It would certainly be a lot simpler to
implement, and you end up dividing everything down to tick granularity
anyway. :-)
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 9:00 ` Keir Fraser
@ 2006-02-22 14:27 ` Rik van Riel
2006-02-22 17:08 ` Keir Fraser
0 siblings, 1 reply; 20+ messages in thread
From: Rik van Riel @ 2006-02-22 14:27 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
On Wed, 22 Feb 2006, Keir Fraser wrote:
> Is accounting user/system time an unnecessary extra? I guess we already
> do it by sampling at tick granularity anyway?
>
> Should 'steal time' include blocked time when the guest had no work to
> execute?
No, this is idle time. If the guest had no work to do,
it wasn't suffering from contention of the CPU.
> Also, given the logic currently only triggers when the guest detects it
> 'missed a tick', would it be good enough simply to account #missed_ticks as
> steal time. It would certainly be a lot simpler to implement, and you end up
> dividing everything down to tick granularity anyway. :-)
Not good enough if the hypervisor ends up scheduling
guests on a granularity finer than the guest's own
timer ticks.
The reason for only checking steal time when we miss
a tick is that I don't want to run the (expensive?)
steal time logic on every timer interrupt.
--
All Rights Reversed
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 14:27 ` Rik van Riel
@ 2006-02-22 17:08 ` Keir Fraser
2006-02-22 17:11 ` Rik van Riel
0 siblings, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-22 17:08 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
On 22 Feb 2006, at 14:27, Rik van Riel wrote:
>
>> Is accounting user/system time an unnecessary extra? I guess we
>> already
>> do it by sampling at tick granularity anyway?
>>
>> Should 'steal time' include blocked time when the guest had no work to
>> execute?
>
> No, this is idle time. If the guest had no work to do,
> it wasn't suffering from contention of the CPU.
But the 'vcpu_time' you read out of Xen excludes time spent
blocked/unrunnable. Won't you end up accounting that as it it were
involuntary preemption? Also:
1. What if a guest gets preempted for lots of short time periods (less
than a jiffy). Then some arbitrary time in the future is preempted for
long enough to activate you stolen-time logic. Won't you end up
incorrectly accounting the accumulated short time periods?
2. Is the Xen provided 'vcpu_time', divided down into jiffies, even
comparable with the kstats that you sum? What about accumulated
rounding errors in 'vcpu_time' and the kstats causing relative drift
between them over time?
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 17:08 ` Keir Fraser
@ 2006-02-22 17:11 ` Rik van Riel
2006-02-22 17:45 ` Keir Fraser
0 siblings, 1 reply; 20+ messages in thread
From: Rik van Riel @ 2006-02-22 17:11 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
On Wed, 22 Feb 2006, Keir Fraser wrote:
> But the 'vcpu_time' you read out of Xen excludes time spent
> blocked/unrunnable. Won't you end up accounting that as it it were
> involuntary preemption? Also:
If the domain is unrunnable, surely there won't be a
process on the virtual cpu that is runnable? Or am
I overlooking something here?
> 1. What if a guest gets preempted for lots of short time periods (less
> than a jiffy). Then some arbitrary time in the future is preempted for
> long enough to activate you stolen-time logic. Won't you end up
> incorrectly accounting the accumulated short time periods?
This is true. I'm not sure we'd want to get the vcpu info
at every timer interrupt though, that could end up being
too expensive...
> 2. Is the Xen provided 'vcpu_time', divided down into jiffies, even
> comparable with the kstats that you sum? What about accumulated rounding
> errors in 'vcpu_time' and the kstats causing relative drift between them
> over time?
In the tests I ran the steal time seemed to work out quite
well with what I expected it to be, watching /proc/stat from
inside the guest and xentop from dom0 simultaneously.
The rounding errors happen occasionally (I added printks to
the if statements catching them), but not all that often...
--
All Rights Reversed
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 17:11 ` Rik van Riel
@ 2006-02-22 17:45 ` Keir Fraser
2006-02-24 19:04 ` Rik van Riel
0 siblings, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-22 17:45 UTC (permalink / raw)
To: Rik van Riel; +Cc: xen-devel
On 22 Feb 2006, at 17:11, Rik van Riel wrote:
> If the domain is unrunnable, surely there won't be a
> process on the virtual cpu that is runnable? Or am
> I overlooking something here?
Oh, I see, this is dealt with inside account_steal_time(). No problem
then.
>> 1. What if a guest gets preempted for lots of short time periods
>> (less
>> than a jiffy). Then some arbitrary time in the future is preempted for
>> long enough to activate you stolen-time logic. Won't you end up
>> incorrectly accounting the accumulated short time periods?
>
> This is true. I'm not sure we'd want to get the vcpu info
> at every timer interrupt though, that could end up being
> too expensive...
Having to call down to Xen to get that information is unfortunate.
Perhaps we can export it in shared_info, or have the guest register a
virtual address it would like the info written to.
> In the tests I ran the steal time seemed to work out quite
> well with what I expected it to be, watching /proc/stat from
> inside the guest and xentop from dom0 simultaneously.
>
> The rounding errors happen occasionally (I added printks to
> the if statements catching them), but not all that often...
I think the calculation of delta stolen time would be clearer as:
((system_time - prev_system_time) - (vcpu_time - prev_vcpu_time)) /
NS_PER_TICK
where system_time/vcpu_time become the prev_system_time/prev_vcpu_time
the next time your logic is triggered.
It has another advantage that it does not subtract quantities that can
slowly relatively drift over days/weeks.
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
[not found] <43FCCB2C.5000408@vmware.com>
@ 2006-02-22 23:58 ` Dan Hecht
2006-02-23 8:40 ` Keir Fraser
2006-02-23 8:48 ` Keir Fraser
0 siblings, 2 replies; 20+ messages in thread
From: Dan Hecht @ 2006-02-22 23:58 UTC (permalink / raw)
To: Keir.Fraser; +Cc: xen-devel
[-- Attachment #1: Type: text/plain, Size: 2937 bytes --]
> On 22 Feb 2006, at 17:11, Rik van Riel wrote:
>
>> If the domain is unrunnable, surely there won't be a
>> process on the virtual cpu that is runnable? Or am
>> I overlooking something here?
>
> Oh, I see, this is dealt with inside account_steal_time(). No problem then.
>
But, the guest will not be able to properly partition this time
correctly between the idle time stat and the steal time stat.
When the vcpu enters its idle loop and blocks, at some point it will
become ready to run again. But, it will not necessarily run right away.
Instead, it will sit in the hypervisors runqueue for some amount of
time. While in the runqueue, this time is "stolen", since the vcpu
wants to run but isn't (at this point it is involuntarily waiting).
Under a heavily overcommitted system, the amount of time in the runqueue
following the block may be nontrivial.
But, the guest (the code in account_steal_time()) cannot determine the
time at which the vcpu was requeued into the hypervisor's runqueue. It
will account all of this time toward the "idle time" stat, rather than
partitioning it between "idle time" and "steal time".
To solve this, it may be best to have the hypervisor interface expose
per-vcpu stolen time directly, rather than vcpu_time. Then the guest
does not need to try to guess whether to charge (system_time -
vcpu_time) against idle or steal.
>>> 1. What if a guest gets preempted for lots of short time periods (less
>>> than a jiffy). Then some arbitrary time in the future is preempted for
>>> long enough to activate you stolen-time logic. Won't you end up
>>> incorrectly accounting the accumulated short time periods?
>>
>> This is true. I'm not sure we'd want to get the vcpu info
>> at every timer interrupt though, that could end up being
>> too expensive...
>
> Having to call down to Xen to get that information is unfortunate.
> Perhaps we can export it in shared_info, or have the guest register a
> virtual address it would like the info written to.
>
If you do change how this information is passed through the interface,
then maybe this would be a good time to define the interface to export
"stolen time" computed by the hypervisor, rather than "vcpu time".
On a topic relating to these patches, the Linux scheduler also uses the
routine sched_clock() to calculate the run-time (and sleep-time) of
processes. With the current code, these calculations will include
stolen time in the total run-time of a process. Perhaps sched_clock()
should be a clock that does not advance when time is stolen by the
hypervisor?
We've been thinking about these issues also. I've attached a document
that describes our current thoughts. The document describes the portion
of the VMI that deals with time and describes the changes to Linux to
accommodate VMI Time (Rik, this is an updated draft of the document I
sent you before). Comments are welcome.
Thanks,
Dan
[-- Attachment #2: vmi_time_spec.txt --]
[-- Type: text/plain, Size: 23039 bytes --]
VMI - Time Interface; VMware, Inc.
In a virtualized environment, virtual machines (VM) will time share the
system with each other and with other processes running on the host
system. Therefore, a VM's virtual cpus (vcpus) will be executing on the
host's physical cpus (pcpus) for only some portion of time. This
section of the VMI exposes a paravirtual view of time to the guest
operating systems so that they may operate more effectively in a virtual
environment. The interface also provides a way for the vcpus to set
alarms in this paravirtual view of time.
-------------------------------------------------------------------------
Time Domains:
a) Wallclock Time:
Wallclock time exposed to the VM through this interface indicates the
number of nanoseconds since epoch, 1970-01-01T00:00:00Z (ISO 8601 date
format). If the host's wallclock time changes (say, when an error in
the host's clock is corrected), so does the wallclock time as viewed
through this interface.
b) Real Time:
Another view of time accessible through this interface is real time.
Real time always progresses except for when the VM is stopped or
suspended. Real time is presented to the guest as a counter which
increments at a constant rate defined (and presented) by the hypervisor.
All the vcpus of a VM share the same real time counter.
The unit of the counter is called "cycles". The unit and initial value
(corresponding to the time the VM enters para-virtual mode) are chosen
by the hypervisor so that the real time counter will not rollover in any
practical length of time. It is expected that the frequency (cycles per
second) is chosen such that this clock provides a "high-resolution" view
of time. The unit can only change when the VM (re)enters paravirtual
mode.
c) Stolen time and Available time:
A vcpu is always in one of three states: running, halted, or ready. The
vcpu is in the 'running' state if it is executing. When the vcpu
executes the VMI_Halt interface, the vcpu enters the 'halted' state and
remains halted until there is some work pending for the vcpu (e.g. an
alarm expires, host I/O completes on behalf of virtual I/O). At this
point, the vcpu enters the 'ready' state (waiting for the hypervisor to
reschedule it). Finally, at any time when the vcpu is not in the
'running' state nor the 'halted' state, it is in the 'ready' state.
For example, consider the following sequence of events, with times given
in real time:
(Example 1)
At 0 ms, VCPU executing guest code.
At 1 ms, VCPU requests virtual I/O.
At 2 ms, Host performs I/O for virtual I/0.
At 3 ms, VCPU executes VMI_Halt.
At 4 ms, Host completes I/O for virtual I/O request.
At 5 ms, VCPU begins executing guest code, vectoring to the interrupt
handler for the device initiating the virtual I/O.
At 6 ms, VCPU preempted by hypervisor.
At 9 ms, VCPU begins executing guest code.
>From 0 ms to 3 ms, VCPU is in the 'running' state. At 3 ms, VCPU enters
the 'halted' state and remains in this state until the 4 ms mark. From
4 ms to 5 ms, the VCPU is in the 'ready' state. At 5 ms, the VCPU
re-enters the 'running' state until it is preempted by the hypervisor at
the 6 ms mark. From 6 ms to 9 ms, VCPU is again in the 'ready' state,
and finally 'running' again after 9 ms.
Stolen time is defined per vcpu to progress at the rate of real time
when the vcpu is in the 'ready' state, and does not progress otherwise.
Available time is defined per vcpu to progress at the rate of real time
when the vcpu is in the 'running' and 'halted' states, and does not
progress when the vcpu is in the 'ready' state.
So, for the above example, the following table indicates these time
values for the vcpu at each ms boundary:
Real time Stolen time Available time
0 0 0
1 0 1
2 0 2
3 0 3
4 0 4
5 1 4
6 1 5
7 2 5
8 3 5
9 4 5
10 4 6
Notice that at any point:
real_time == stolen_time + available_time
Stolen time and available time are also presented as counters in
"cycles" units. The initial value of the stolen time counter is 0.
This implies the initial value of the available time counter is the same
as the real time counter.
Alarms:
Alarms can be set (armed) against the real time counter or the available
time counter. Alarms can be programmed to expire once (one-shot) or on a
regular period (periodic). They are armed by indicating an absolute
counter value expiry, and in the case of a periodic alarm, a non-zero
relative period counter value. [TBD: The method of wiring the alarms to
an interrupt vector is dependent upon the virtual interrupt controller
portion of the interface. Currently, the alarms may be wired as if they
are attached to IRQ0 or the vector in the local APIC LVTT. This way,
the alarms can be used as drop in replacements for the PIT or local APIC
timer.]
Alarms are per-vcpu mechanisms. An alarm set by vcpu0 will fire only on
vcpu0, while an alarm set by vcpu1 will only fire on vcpu1. If an alarm
is set relative to available time, its expiry is a value relative to the
available time counter of the vcpu that set it.
The interface includes a method to cancel (disarm) an alarm. On each
vcpu, one alarm can be set against each of the two counters (real time
and available time). A vcpu in the 'halted' state becomes 'ready' when
any of its alarm's counters reaches the expiry.
An alarm "fires" by signaling the virtual interrupt controller. An
alarm will fire as soon as possible after the counter value is greater
than or equal to the alarm's current expiry. However, an alarm can fire
only when its vcpu is in the 'running' state.
If the alarm is periodic, a sequence of expiry values,
E(i) = e0 + p * i , i = 0, 1, 2, 3, ...
where 'e0' is the expiry specified when setting the alarm and 'p' is the
period of the alarm, is used to arm the alarm. Initially, E(0) is used
as the expiry. When the alarm fires, the next expiry value in the
sequence that is greater than the current value of the counter is used
as the alarm's new expiry.
One-shot alarms have only one expiry. When a one-shot alarm fires, it
is automatically disarmed.
Suppose an alarm is set relative to real time with expiry at the 3 ms
mark and a period of 2 ms. It will expire on these real time marks: 3,
5, 7, 9. Note that even if the alarm does not fire during the 5 ms to 7
ms interval, the alarm can fire at most once during the 7 ms to 9 ms
interval (unless, of course, it is reprogrammed).
If an alarm is set relative to available time with expiry at the 1 ms
mark (in available time) and with a period of 2 ms, then it will expire
on these available time marks: 1, 3, 5. In the scenario described in
example 1, those available time values correspond to these values in
real time: 1, 3, 6.
-------------------------------------------------------------------------
Interface Details:
/* The cycle counters. */
#define VMI_CYCLES_REAL 0
#define VMI_CYCLES_AVAILABLE 1
#define VMI_CYCLES_STOLEN 2
/* Predefined rate of the wallclock. */
#define VMI_WALLCLOCK_HZ 1000000000
/* The alarm interface 'flags' bits. [TBD: exact format of 'flags'] */
#define VMI_ALARM_COUNTER_MASK 0x000000ff
#define VMI_ALARM_WIRED_IRQ0 0x00000000
#define VMI_ALARM_WIRED_LVTT 0x00010000
#define VMI_ALARM_IS_ONESHOT 0x00000000
#define VMI_ALARM_IS_PERIODIC 0x00000100
/* The time types. */
typedef unsigned char VMI_BOOL; /* FALSE==0, TRUE==!FALSE. */
typedef uint64 VMI_CYCLES;
typedef uint64 VMI_NANOSECS;
typedef sint64 VMI_NANOSECSDIFF;
/* The time functions. */
VMI_NANOSECS VMI_GetWallclockTime(void);
VMI_BOOL VMI_WallclockUpdated(void);
VMI_CYCLES VMI_GetCycleFrequency(void);
VMI_CYCLES VMI_GetCycleCounter(uint32 whichCounter);
void VMI_SetAlarm(uint32 flags, VMI_CYCLES expiry, VMI_CYCLES period);
VMI_BOOL VMI_CancelAlarm(uint32 flags);
VMI_GetWallclockTime returns the current wallclock time as the number of
nanoseconds since the epoch. Nanosecond resolution along with the
64-bit unsigned type provide over 580 years from epoch until rollover.
The wallclock time is relative to the host's wallclock time.
VMI_WallclockUpdated returns TRUE if the wallclock time has changed
relative to the real cycle counter since the previous time that
VMI_WallclockUpdated was polled. For example, while a VM is suspended,
the real cycle counter will halt, but wallclock time will continue to
advance. Upon resuming the VM, the first call to VMI_WallclockUpdated
will return TRUE.
VMI_GetCycleFrequency returns the number of cycles in one second. This
value can be used by the guest to convert between cycles and other time
units.
VMI_GetCycleCounter returns the current value, in cycles units, of the
counter corresponding to 'whichCounter' if it is one of VMI_CYCLES_REAL,
VMI_CYCLES_AVAILABLE or VMI_CYCLES_STOLEN. VMI_GetCycleCounter returns
0 for any other value of 'whichCounter'.
VMI_SetAlarm is used to arm the vcpu's alarms. The 'flags' parameter is
used to specify which counter's alarm is being set (VMI_CYCLES_REAL or
VMI_CYCLES_AVAILABLE), how to deliver the alarm to the vcpu
(VMI_ALARM_WIRED_IRQ0 or VMI_ALARM_WIRED_LVTT), and the mode
(VMI_ALARM_IS_ONESHOT or VMI_ALARM_IS_PERIODIC). If the alarm is set
against the VMI_ALARM_STOLEN counter or an undefined counter number, the
call is a nop. The 'expiry' parameter indicates the expiry of the
alarm, and for periodic alarms, the 'period' parameter indicates the
period of the alarm. If the value of 'period' is zero, the alarm is
armed as a one-shot alarm regardless of the mode specified by 'flags'.
Finally, a call to VMI_SetAlarm for an alarm that is already armed is
equivalent to first calling VMI_CancelAlarm and then calling
VMI_SetAlarm, except that the value returned by VMI_CancelAlarm is not
accessible.
VMI_CancelAlarm is used to disarm an alarm. The 'flags' parameter
indicates which alarm to cancel (VMI_CYCLES_REAL or
VMI_CYCLES_AVAILABLE). The return value indicates whether or not the
cancel succeeded. A return value of FALSE indicates that the alarm was
already disarmed either because a) the alarm was never set or b) it was
a one-shot alarm and has already fired (though perhaps not yet delivered
to the guest). TRUE indicates that the alarm was armed and either a)
the alarm was one-shot and has not yet fired (and will no longer fire
until it is rearmed) or b) the alarm was periodic.
-------------------------------------------------------------------------
Further discussion regarding the proposed interface:
1) Mechanism to atomically read the set of time values.
The interface does not provide a way for a vcpu to atomically read the
entire set of time values { wallclock time, real time counter, available
time counter, stolen time counter }. While it seems that such a
mechanism might be "nice" to have in theory, it seems unnecessary in
practice. Indeed, real hardware rarely provides this functionality.
One nice side effect of having this feature is that the explicit stolen
time counter (or available time counter) can be dropped entirely from
the interface, since its value can be inferred from the real time
counter and available time counter (or stolen time counter).
Two potential proposals that provide this feature are:
a) "Struct" return value style interface:
typedef struct VMITimeValues {
VMI_NANOSECS wallTime;
VMI_CYCLES realCounter;
VMI_CYCLES availableCounter;
} VMITimeValues;
VMITimeValues VMI_GetTimes(void); or, similarly,
void VMI_GetTimes(VMITimeValues *t);
Pros: Easy to understand interface. Implementation can provide atomicity
by returning all time values as a complete set.
Cons: Struct return value (indirect return) less efficient, especially
when caller only needs to use one of the time values. More difficult to
extend interface and maintain compatibility.
b) "Caching" mechanism added to current interface.
#define VMI_CYCLES_REAL 0
#define VMI_CYCLES_AVAILABLE 1
#define VMI_CYCLES_CACHED 0x80
VMI_NANOSECS VMI_GetWallclockTime(uint32 flags);
VMI_CYCLES VMI_GetCycleCounter(uint32 flags);
When the VMI_CYCLES_CACHED bit of the 'flags' parameter is not set, the
routines atomically cache the entire set of time values into the "time
cache". The requested time value is returned.
When the VMI_CYCLES_CACHED bit of the 'flags' parameters is set, the
routine returns the requested time value from the time cache.
Using this interface, along with guest provided synchronization, the
entire set of time values can be retrieved atomically.
Pros: Efficient calling convention, especially when only one time value
is desired. Easier to extend the interface and maintain compatibility.
Cons: Interface is perhaps more difficult to understand and use
correctly. Requires guest synchronization to ensure the cached values
remain consistent between VMI calls.
2) Mechanism to read the available time counter and stolen time counter
for another vcpu.
VCPU0 cannot read VCPU1's per-vcpu counters, and vice versa. This
feature is not required by Linux. Might there be some guest that
requires this ability?
The VMI_GetCycleCounter interface could be extended to index by vcpu ID
in order to provide this functionality.
3) Notification mechanism for relative change between wallclock time and
real cycle counter.
It is expected that the guest will usually read the wallclock time at
boot, and then apply an adjustment to this time using the real cycle
counter to calculate the current wallclock time. However, the wallclock
time and real cycle counter may become out of sync for a variety of
reasons. For example, when a VM is suspended, the real cycle counter
will stop advancing while the wallclock time continues to advance.
Additionally, when the host wallclock is corrected the real cycle
counter is not affected. Therefore, it is convenient for the guest to
receive notification that the wallclock time has changed relative to the
real cycle counter. Currently, a polling interface is provided for
this: VMI_WallclockUpdated.
Alternatively, an interrupt interface may be provided. An interrupt
would be sent to the guest to notify it of a change to the wallclock
time relative to the real cycle counter.
-------------------------------------------------------------------------
Use of VMI Time in Linux:
To paravirtualize time in the Linux kernel, we introduce a new timer
device module, timer_vmi.c (the VMI Time module), which parallels the
existing modules, e.g. arch/i386/kernel/timers/{timer_pit.c,
timer_tsc.c, timer_cyclone.c, timer_hpet.c, timer_pm.c}. The
timer_vmi.c module implements the low-level Linux kernel time routines
using the VMI Time interface.
The new VMI Time module is used only when a hypervisor is detected at
boot time. Otherwise, we fall back to one of the traditional modules
listed above. This provides "transparency" -- the same kernel binary
can run with the VMI Time device or with one of the traditional time
devices.
The Linux xtime variable is initialized to the wallclock time exposed by
the VMI.
The VMI Time module contains a timer interrupt that is driven by a
periodic VMI alarm set against the available time counter. The
interrupt calls the do_timer() routine every time the real time counter
advances cycles_per_second/HZ cycles (call this quantity
cycles_per_jiffy), as detected by any vcpu. do_timer() updates the
jiffies count and xtime count.
The timer interrupt additionally calls the update_process_times()
routine for every time the available time counter for the current vcpu
advances cycles_per_jiffy cycles. update_process_times() accounts user
time stats for the process and vcpu, accounts system time stats for the
process and cpu, runs the soft timers for the cpu, performs some RCU
work, calls the scheduler back via scheduler_tick() and runs posix
timers for the current task. The scheduler_tick() callback decrements
the current process' timeslice and makes scheduling decisions. The
profile_tick() routine is also called at each cycles_per_jiffy increment
of the available time counter on each vcpu.
Finally, the timer interrupt accounts the difference between the real
time counter and the available time counter (essentially the stolen time
counter) to the steal cpustat.
The sched_clock() scheduler callback is also modified to calculate time
using the available time counter. The effect of this is to compute
process' sleep_avg using available time. sleep_avg is used primarily to
compute the "effective priority" of a task.
Additionally, the i386 timer modules are called back via the active
timer_opts struct to get additional time information. arch/i386's
do_gettimeofday() and do_settimeofday() use the get_offset() callback to
offset the time from xtime. The VMI Time module implements this
callback using the real time counter. The monotonic clock callback is
also implemented using the real time counter.
The __delay() routine is implemented via a timer_opt callback in the VMI
Time module. When running under a hypervisor, delays are not necessary
when communicating with virtual devices. These delays are nops when
running under a hypervisor. However, the smpboot.c bootup sequence does
require delays, and these delays are implemented using the real time
counter.
The effect of these changes are that Linux's real time variables and
timers continue to run on real time. These include jiffies, xtime,
ITIMER_REAL timers, SIGALARM timers, posix-timers. Additionally, the
notion of process times remains consistent in the paravirtual
environment as compared with native. Since process time accounting is
done using available time, time that is stolen from the vcpu is not
accounted toward process times. This keeps the cpustats faithful and
virtual timers consistent (ITIMER_VIRT, SIGVTALARM, ITIMER_PROF,
SIGPROF). Additionally, the scheduler essentially runs in available
time, and so time stolen from the vcpu does not steal time from process'
timeslices. Finally, with process time accounting performed using
available time and with steal time accounting, the view of time (for
example, using the utilities 'top', 'time', etc.) from within
paravirtualized Linux is consistent with time viewed on the host and
from within other paravirtualized guests on the same host.
Some noteworthy characteristics of the VMI Time module are:
1) Cycle counter frequency is indicated by the VMI rather than needing
to be calculated by comparing the counter rate to a known interrupt
rate.
On native hardware, the TSC frequency is calculated by comparing the
rate at which the TSC advances with the (known) rate of a timer
interrupt. This method for determining a cycle counter frequency is
unreliable on virtual hardware since the vcpu may be preempted by the
hypervisor during this calculation.
Instead, the VMI Time device determines the frequency of the VMI cycle
counters by querying the VMI.
2) The timer_irq_works() algorithm is problematic in a virtual
environment for various reasons, and is avoided. When running on a
hypervisor, the kernel can assume that the alarm will be wired up
correctly to the interrupt controller and this logic is avoided
altogether.
3) Rather than keeping kernel time state (e.g. jiffies, xtime, time
slices) up to date by counting interrupts, the state is updated based on
the values of the VMI cycle counters.
Therefore, a vcpu only needs to receive timer interrupts while it is
running. This leads to better scaling of the number of virtual machines
that can be run on a single host.
4) As a consequence of #3, the interrupt rate of the alarm can be
dropped lower than HZ. It may be beneficial for the guest to request a
lower alarm rate to decrease the overhead of delivering virtual
interrupts. With #3, this is possible without changing the HZ constant
(which is important in order to allow for transparency with native
hardware using the normal HZ rate).
5) System wide time state (e.g. jiffies, xtime) is updated by all vcpus.
With the native x86 timer interrupts, only the boot processor's PIT
interrupt updates jiffies and xtime. With the VMI Time device, jiffies
and xtime are updated by all the vcpus of a VM. This is important since
the vcpus may be independently scheduled. Also, it allows for a simpler
NO_IDLE_HZ implementation.
6) The xtime counter is kept up with the wallclock time.
7) The jiffies counter is kept up with the real time cycle counter.
8) Scheduler time slices and sched_clock() are kept up with the
available time cycle counter.
When using the VMI Time device as the time source, the scheduler runs in
available time. Otherwise, processes would be charged for time stolen
from the vcpu (time in which the vcpu isn't even running). The
scheduler_tick() interface is called only for every tick of available
time. Also, sched_clock() is implemented using the available time
counter so that the scheduler's calculations of a process' run-time does
not charge stolen time.
9) Stolen time is computed by the hypervisor, not the Linux guest.
Only the hypervisor can accurately compute stolen time. On some
hypervisors, stolen time is computed by the guest by subtracting the
amount of time a vcpu has run on a pcpu from the amount of real time
that has passed. Then, the routine account_steal_time() is used to
charge this time difference to
a) steal time, if the current process is not the idle process, or
b) idle time, if the current process is the idle process.
The problem with that calculation is that when a vcpu's halt ends, it
will not necessarily run immediately. Instead, it will be transitioned
from the 'halted' state to the 'ready' state (i.e. added to the
hypervisor's runqueue) until the hypervisor chooses to run it. The time
the vcpu is 'ready' is not idle time, but instead stolen time. But,
implementations using account_steal_time() will account all of this time
to idle time, rather than partitioning the time such that the time spent
in the 'halted' state is idle time and the time spent in the 'ready'
state is stolen time.
Only the hypervisor can determine when the transition from 'halted' to
'ready' occurred (due to work becoming pending for the vcpu). So, the
VMI Time device queries the stolen time from the VMI rather than using
the faulty account_steal_time() algorithm.
10) A NO_IDLE_HZ implementation is provided.
When a vcpu enters its idle loop, it disables its periodic alarm and
sets up a one shot alarm for the next time event. That way, it does not
become ready to run just to service the periodic alarm
interrupt. Instead, it can remain halted until there is some real work
pending for it. This allows the hypervisor to use the physical
resources more effectively since idle vcpus will have lower overhead.
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 23:58 ` [PATCH 1/2] cpu steal time accounting Dan Hecht
@ 2006-02-23 8:40 ` Keir Fraser
2006-02-23 18:17 ` Dan Hecht
2006-02-23 8:48 ` Keir Fraser
1 sibling, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-23 8:40 UTC (permalink / raw)
To: Dan Hecht; +Cc: xen-devel
On 22 Feb 2006, at 23:58, Dan Hecht wrote:
> To solve this, it may be best to have the hypervisor interface expose
> per-vcpu stolen time directly, rather than vcpu_time. Then the guest
> does not need to try to guess whether to charge (system_time -
> vcpu_time) against idle or steal.
Yes, the distinction between stolen and available time does makes sense
(although I'm not sure 'available' is a great name) otherwise you can't
account for wakeup latencies. account_steal_time() would need to be
modified in Linux, though, as we would not need its dodgy heuristic for
deciding whether to account to stolen time or iowait/idle.
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 23:58 ` [PATCH 1/2] cpu steal time accounting Dan Hecht
2006-02-23 8:40 ` Keir Fraser
@ 2006-02-23 8:48 ` Keir Fraser
2006-02-23 10:04 ` Keir Fraser
2006-02-23 13:18 ` Rik van Riel
1 sibling, 2 replies; 20+ messages in thread
From: Keir Fraser @ 2006-02-23 8:48 UTC (permalink / raw)
To: Dan Hecht; +Cc: xen-devel
On 22 Feb 2006, at 23:58, Dan Hecht wrote:
> The interface does not provide a way for a vcpu to atomically read the
> entire set of time values { wallclock time, real time counter,
> available
> time counter, stolen time counter }. While it seems that such a
> mechanism might be "nice" to have in theory, it seems unnecessary in
> practice. Indeed, real hardware rarely provides this functionality.
>
> One nice side effect of having this feature is that the explicit stolen
> time counter (or available time counter) can be dropped entirely from
> the interface, since its value can be inferred from the real time
> counter and available time counter (or stolen time counter).
I don't understand the last paragraph here. It's not true that, for
example,
available_time = real_time - stolen_time
right?
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-23 8:48 ` Keir Fraser
@ 2006-02-23 10:04 ` Keir Fraser
2006-02-23 19:43 ` Dan Hecht
2006-02-23 13:18 ` Rik van Riel
1 sibling, 1 reply; 20+ messages in thread
From: Keir Fraser @ 2006-02-23 10:04 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel, Dan Hecht
On 23 Feb 2006, at 08:48, Keir Fraser wrote:
>> One nice side effect of having this feature is that the explicit
>> stolen
>> time counter (or available time counter) can be dropped entirely from
>> the interface, since its value can be inferred from the real time
>> counter and available time counter (or stolen time counter).
>
> I don't understand the last paragraph here. It's not true that, for
> example,
> available_time = real_time - stolen_time
> right?
Ah, okay, I see that in fact it is. :-)
Why not just have a halted_time instead? I think that's what we'd go
for in Xen.
-- Keir
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-23 8:48 ` Keir Fraser
2006-02-23 10:04 ` Keir Fraser
@ 2006-02-23 13:18 ` Rik van Riel
1 sibling, 0 replies; 20+ messages in thread
From: Rik van Riel @ 2006-02-23 13:18 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel, Dan Hecht
On Thu, 23 Feb 2006, Keir Fraser wrote:
> I don't understand the last paragraph here. It's not true that, for example,
> available_time = real_time - stolen_time
> right?
I think that is true. Not sure why it wouldn't be...
--
All Rights Reversed
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-23 8:40 ` Keir Fraser
@ 2006-02-23 18:17 ` Dan Hecht
0 siblings, 0 replies; 20+ messages in thread
From: Dan Hecht @ 2006-02-23 18:17 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
Keir Fraser wrote:
>
> On 22 Feb 2006, at 23:58, Dan Hecht wrote:
>
>> To solve this, it may be best to have the hypervisor interface expose
>> per-vcpu stolen time directly, rather than vcpu_time. Then the guest
>> does not need to try to guess whether to charge (system_time -
>> vcpu_time) against idle or steal.
>
> Yes, the distinction between stolen and available time does makes sense
> (although I'm not sure 'available' is a great name)
The term "available" came from looking at it from the perspective of the
vcpu, rather than the hypervisor. To the vcpu, the time that it's
running or halted is, in a sense, "available" to it (even though, (as an
optimization) the hypervisor might use the pcpu to do something else
when the vcpu is halted). But, anytime the hypervisor forces the vcpu
to wait involuntarily, the time is no longer "available" to it, but stolen.
Said another way, on native hardware, stolen time is zero. All time is
"available" to the OS. Though it might choose to halt for some of this
time, the time is still "available".
> otherwise you can't
> account for wakeup latencies. account_steal_time() would need to be
> modified in Linux, though, as we would not need its dodgy heuristic for
> deciding whether to account to stolen time or iowait/idle.
>
Exactly. We slightly refactor the account_steal_time() interface to
have an interface that bypasses the heuristic.
Dan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-23 10:04 ` Keir Fraser
@ 2006-02-23 19:43 ` Dan Hecht
0 siblings, 0 replies; 20+ messages in thread
From: Dan Hecht @ 2006-02-23 19:43 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
Keir Fraser wrote:
>
> On 23 Feb 2006, at 08:48, Keir Fraser wrote:
>
>>> One nice side effect of having this feature is that the explicit stolen
>>> time counter (or available time counter) can be dropped entirely from
>>> the interface, since its value can be inferred from the real time
>>> counter and available time counter (or stolen time counter).
>>
>> I don't understand the last paragraph here. It's not true that, for
>> example,
>> available_time = real_time - stolen_time
>> right?
>
> Ah, okay, I see that in fact it is. :-)
>
Yeah, by definition, available_time is (real_time - stolen_time).
> Why not just have a halted_time instead? I think that's what we'd go for
> in Xen.
>
I assume you mean have halted_time in addition to vcpu_time, since you'd
still need vcpu_time to determine stolen_time for the case a running
vcpu is made to involuntarily wait.
Essentially, by adding halted_time, the Xen and VMI interfaces would be
very similar in this regard. We'd have:
xen_system_time <==> vmi_real_time
xen_vcpu_time + xen_halted_time <==> vmi_available_time
xen_stolen_time <==> vmi_stolen_time
The reason the vmi does not further partition vmi_available_time into
vcpu_time and halted_time is because the guest is able to correctly do
this partitioning, if it chooses to do so. It can be done with:
halt_start = vmi_available_time counter;
Halt;
When the vcpu starts running again,
halt_end = vmi_available_time counter;
We know during this time, vcpu_time == 0. halted_time == (halt_end -
halt_start). And, when executing outside this region, any
vmi_available_time that passes is vcpu_time.
So, rather than potentially complicating the interface, the vmi leaves
the partitioning of vmi_available_time into vcpu_time and halted_time up
to the guest. Besides, perhaps there are other ways the guest may want
to partition vmi_available_time other than into vcpu_time/halted_time,
so why not leave this up to the guest OS?
Also, unless halted_time/vcpu_time is defined very carefully and
precisely, having it as part of the interface can become confusing in
the case the hypervisor wants to implement "halt" using a busy wait, or
when the paravirtualized kernel is run on native hardware. In these
cases, the vcpu is still hogging a pcpu, so it might be unclear whether
to consider that time vcpu_time or halted_time.
If vcpu_time is defined to be time in which a pcpu is dedicated to the
vcpu (even if the vcpu executed the "halt" interface and is busy
waiting), then halted_time would be defined to be time in which no pcpu
is dedicated to the vcpu but the vcpu is not involuntarily waiting (i.e.
the remaining time that is not stolen). But, why expose this hypervisor
implementation detail through the interface?
On the other hand, if vcpu_time is defined to be the time in which a
pcpu is dedicated to the vcpu *and* the vcpu is not halted, then
halted_time is defined to be the time the vcpu is halted (no matter how
the hypervisor implements the halt -- a pcpu may still be dedicated to
the vcpu). But, in this case, why not leave the partitioning of
available_time into vcpu_time/halted_time up to the guest OS?
Just trying to say that partitioning available_time into vcpu_time and
halted_time may just add confusion and make the interface more
complicated without making the interface any more powerful.
Dan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] cpu steal time accounting
2006-02-22 17:45 ` Keir Fraser
@ 2006-02-24 19:04 ` Rik van Riel
0 siblings, 0 replies; 20+ messages in thread
From: Rik van Riel @ 2006-02-24 19:04 UTC (permalink / raw)
To: Keir Fraser; +Cc: xen-devel
On Wed, 22 Feb 2006, Keir Fraser wrote:
> I think the calculation of delta stolen time would be clearer as:
> ((system_time - prev_system_time) - (vcpu_time - prev_vcpu_time)) /
> NS_PER_TICK
The "(system_time - prev_system_time)" above is equivalent
to the delta_cpu variable.
I agree on saving the prev_vcpu_time though, it makes the code
quite a bit nicer. I hope you like this patch ;)
Signed-off-by: Rik van Riel <riel@redhat.com>
--- linux-2.6.15.i686/arch/i386/kernel/time-xen.c.steal 2006-02-17 16:44:40.000000000 -0500
+++ linux-2.6.15.i686/arch/i386/kernel/time-xen.c 2006-02-24 13:53:08.000000000 -0500
@@ -48,6 +48,7 @@
#include <linux/mca.h>
#include <linux/sysctl.h>
#include <linux/percpu.h>
+#include <linux/kernel_stat.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -77,6 +78,7 @@
#include <asm/arch_hooks.h>
#include <xen/evtchn.h>
+#include <xen/interface/vcpu.h>
#if defined (__i386__)
#include <asm/i8259.h>
@@ -125,6 +127,9 @@ static u32 shadow_tv_version;
static u64 processed_system_time; /* System time (ns) at last processing. */
static DEFINE_PER_CPU(u64, processed_system_time);
+/* Keep track of how much time our vcpu used, for steal time calculation. */
+static DEFINE_PER_CPU(u64, prev_vcpu_time);
+
/* Must be signed, as it's compared with s64 quantities which can be -ve. */
#define NS_PER_TICK (1000000000LL/HZ)
@@ -624,7 +629,32 @@ irqreturn_t timer_interrupt(int irq, voi
* Local CPU jiffy work. No need to hold xtime_lock, and I'm not sure
* if there is risk of deadlock if we do (since update_process_times
* may do scheduler rebalancing work and thus acquire runqueue locks).
+ *
+ * If we have not run for a while, chances are this vcpu got scheduled
+ * away. Try to estimate how much time was stolen.
*/
+ if (delta_cpu > (s64)(2 * NS_PER_TICK)) {
+ dom0_getvcpuinfo_t vcpu = { 0, };
+ s64 steal;
+ u64 dvcpu;
+
+ if (HYPERVISOR_vcpu_op(VCPUOP_cpu_info, cpu, &vcpu) == 0) {
+ dvcpu = vcpu.cpu_time - per_cpu(prev_vcpu_time, cpu);
+ per_cpu(prev_vcpu_time, cpu) = vcpu.cpu_time;
+ steal = delta_cpu - (s64)dvcpu;
+
+ if (steal > 0) {
+ /* do_div modifies the variable in place. */
+ do_div(steal, NS_PER_TICK);
+
+ delta_cpu -= steal * NS_PER_TICK;
+ per_cpu(processed_system_time, cpu) +=
+ steal * NS_PER_TICK;
+ account_steal_time(current, (cputime_t)steal);
+ }
+ }
+ }
+
while (delta_cpu >= NS_PER_TICK) {
delta_cpu -= NS_PER_TICK;
per_cpu(processed_system_time, cpu) += NS_PER_TICK;
--- linux-2.6.15.i686/include/xen/interface/vcpu.h.steal 2006-02-17 16:14:17.000000000 -0500
+++ linux-2.6.15.i686/include/xen/interface/vcpu.h 2006-02-17 16:14:52.000000000 -0500
@@ -51,6 +51,14 @@
/* Returns 1 if the given VCPU is up. */
#define VCPUOP_is_up 3
+/*
+ * Get information on how much CPU time this VCPU has used, etc...
+ *
+ * @extra_arg == pointer to an empty dom0_getvcpuinfo_t, the "OUT" variables
+ * of which filled in with scheduler info.
+ */
+#define VCPUOP_cpu_info 4
+
#endif /* __XEN_PUBLIC_VCPU_H__ */
/*
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2006-02-24 19:04 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <43FCCB2C.5000408@vmware.com>
2006-02-22 23:58 ` [PATCH 1/2] cpu steal time accounting Dan Hecht
2006-02-23 8:40 ` Keir Fraser
2006-02-23 18:17 ` Dan Hecht
2006-02-23 8:48 ` Keir Fraser
2006-02-23 10:04 ` Keir Fraser
2006-02-23 19:43 ` Dan Hecht
2006-02-23 13:18 ` Rik van Riel
2006-02-21 14:06 Tian, Kevin
-- strict thread matches above, loose matches on Subject: below --
2006-02-21 9:05 Tian, Kevin
2006-02-21 12:56 ` Rik van Riel
2006-02-21 0:51 Rik van Riel
2006-02-21 17:42 ` Keir Fraser
2006-02-21 19:32 ` Rik van Riel
2006-02-21 21:24 ` Diwaker Gupta
2006-02-22 9:00 ` Keir Fraser
2006-02-22 14:27 ` Rik van Riel
2006-02-22 17:08 ` Keir Fraser
2006-02-22 17:11 ` Rik van Riel
2006-02-22 17:45 ` Keir Fraser
2006-02-24 19:04 ` Rik van Riel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.