diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-26 23:42:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-28 22:54:33 -0400 |
commit | 6c8dca5d53f95009d4fff00195bf38f277dc4366 (patch) | |
tree | 60cc83cf949d6e598e6dc80dc668aebd42c65540 /drivers/lguest/hypercalls.c | |
parent | a8a11f06973fa63ad692a8f97694cb5eeb70b3f3 (diff) |
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>
Diffstat (limited to 'drivers/lguest/hypercalls.c')
-rw-r--r-- | drivers/lguest/hypercalls.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 7a5299f9679d..db6caace3b9c 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c | |||
@@ -64,14 +64,6 @@ static void do_hcall(struct lguest *lg, struct lguest_regs *regs) | |||
64 | else | 64 | else |
65 | guest_pagetable_flush_user(lg); | 65 | guest_pagetable_flush_user(lg); |
66 | break; | 66 | break; |
67 | case LHCALL_GET_WALLCLOCK: { | ||
68 | /* The Guest wants to know the real time in seconds since 1970, | ||
69 | * in good Unix tradition. */ | ||
70 | struct timespec ts; | ||
71 | ktime_get_real_ts(&ts); | ||
72 | regs->eax = ts.tv_sec; | ||
73 | break; | ||
74 | } | ||
75 | case LHCALL_BIND_DMA: | 67 | case LHCALL_BIND_DMA: |
76 | /* BIND_DMA really wants four arguments, but it's the only call | 68 | /* BIND_DMA really wants four arguments, but it's the only call |
77 | * which does. So the Guest packs the number of buffers and | 69 | * which does. So the Guest packs the number of buffers and |
@@ -235,6 +227,9 @@ static void initialize(struct lguest *lg) | |||
235 | || put_user(lg->guestid, &lg->lguest_data->guestid)) | 227 | || put_user(lg->guestid, &lg->lguest_data->guestid)) |
236 | kill_guest(lg, "bad guest page %p", lg->lguest_data); | 228 | kill_guest(lg, "bad guest page %p", lg->lguest_data); |
237 | 229 | ||
230 | /* We write the current time into the Guest's data page once now. */ | ||
231 | write_timestamp(lg); | ||
232 | |||
238 | /* This is the one case where the above accesses might have been the | 233 | /* This is the one case where the above accesses might have been the |
239 | * first write to a Guest page. This may have caused a copy-on-write | 234 | * first write to a Guest page. This may have caused a copy-on-write |
240 | * fault, but the Guest might be referring to the old (read-only) | 235 | * fault, but the Guest might be referring to the old (read-only) |
@@ -293,3 +288,13 @@ void do_hypercalls(struct lguest *lg) | |||
293 | clear_hcall(lg); | 288 | clear_hcall(lg); |
294 | } | 289 | } |
295 | } | 290 | } |
291 | |||
292 | /* This routine supplies the Guest with time: it's used for wallclock time at | ||
293 | * initial boot and as a rough time source if the TSC isn't available. */ | ||
294 | void write_timestamp(struct lguest *lg) | ||
295 | { | ||
296 | struct timespec now; | ||
297 | ktime_get_real_ts(&now); | ||
298 | if (put_user(now, &lg->lguest_data->time)) | ||
299 | kill_guest(lg, "Writing timestamp"); | ||
300 | } | ||