Provide timespec to guests rather than jiffies clock.

A non-periodic clock_event_device and the "jiffies" clock don't mix well:
tick_handle_periodic() can go into an infinite loop.

Currently lguest guests use the jiffies clock when the TSC is
unusable.  Instead, make the Host write the current time into the lguest
page on every interrupt.  This doesn't cost much but is more precise
and at least as accurate as the jiffies clock.  It also gets rid of
the GET_WALLCLOCK hypercall.

Also, delay setting sched_clock until our clock is set up, otherwise
the early printk timestamps can go backwards (not harmful, just ugly).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Rusty Russell
2007-07-27 13:42:52 +10:00
committed by Linus Torvalds
parent a8a11f0697
commit 6c8dca5d53
5 changed files with 60 additions and 25 deletions

View File

@@ -64,14 +64,6 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
else
guest_pagetable_flush_user(lg);
break;
case LHCALL_GET_WALLCLOCK: {
/* The Guest wants to know the real time in seconds since 1970,
* in good Unix tradition. */
struct timespec ts;
ktime_get_real_ts(&ts);
regs->eax = ts.tv_sec;
break;
}
case LHCALL_BIND_DMA:
/* BIND_DMA really wants four arguments, but it's the only call
* which does. So the Guest packs the number of buffers and
@@ -235,6 +227,9 @@ static void initialize(struct lguest *lg)
|| put_user(lg->guestid, &lg->lguest_data->guestid))
kill_guest(lg, "bad guest page %p", lg->lguest_data);
/* We write the current time into the Guest's data page once now. */
write_timestamp(lg);
/* This is the one case where the above accesses might have been the
* first write to a Guest page. This may have caused a copy-on-write
* fault, but the Guest might be referring to the old (read-only)
@@ -293,3 +288,13 @@ void do_hypercalls(struct lguest *lg)
clear_hcall(lg);
}
}
/* This routine supplies the Guest with time: it's used for wallclock time at
* initial boot and as a rough time source if the TSC isn't available. */
void write_timestamp(struct lguest *lg)
{
struct timespec now;
ktime_get_real_ts(&now);
if (put_user(now, &lg->lguest_data->time))
kill_guest(lg, "Writing timestamp");
}