From ba13dc980ddf4db54b7ed9ff0af75ee38340fd9f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 21 Mar 2007 12:03:27 -0400 Subject: [PATCH] lguest: TSC clocksource Add rudimentary TSC-based clocksource support. Needs to be enhanced for frequency scaling. Signed-off-by: James Morris --- arch/i386/kernel/tsc.c | 1 + arch/i386/lguest/hypercalls.c | 3 +++ arch/i386/lguest/lguest.c | 25 +++++++++++++++++++++++++ include/asm-i386/lguest.h | 2 ++ 4 files changed, 31 insertions(+), 0 deletions(-) diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index b5dc068..c1d05a8 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c @@ -24,6 +24,7 @@ #include "mach_timer.h" * an extra value to store the TSC freq */ unsigned int tsc_khz; +EXPORT_SYMBOL_GPL(tsc_khz); int tsc_disable; diff --git a/arch/i386/lguest/hypercalls.c b/arch/i386/lguest/hypercalls.c index 30b933f..faf5be0 100644 --- a/arch/i386/lguest/hypercalls.c +++ b/arch/i386/lguest/hypercalls.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -178,6 +179,8 @@ int hypercall(struct lguest *lg, struct /* We reserve the top pgd entry. */ put_user(4U*1024*1024, &lg->lguest_data->reserve_mem); put_user(lg->guestid, &lg->lguest_data->guestid); + put_user(clocksource_khz2mult(tsc_khz, 22), + &lg->lguest_data->clock_mult); return 0; } pending = do_hcall(lg, regs); diff --git a/arch/i386/lguest/lguest.c b/arch/i386/lguest/lguest.c index 9a273ad..a0b67e3 100644 --- a/arch/i386/lguest/lguest.c +++ b/arch/i386/lguest/lguest.c @@ -25,6 +25,7 @@ #include #include #include #include +#include #include #include #include @@ -358,8 +359,32 @@ static struct irq_chip lguest_irq_contro .unmask = enable_lguest_irq, }; +static cycle_t lguest_clock_read(void) +{ + /* FIXME: This is just the native one. Account stolen time! */ + return paravirt_ops.read_tsc(); +} + +/* FIXME: Update iff tsc rate changes. */ +static struct clocksource lguest_clock = { + .name = "lguest", + .rating = 400, + .read = lguest_clock_read, + .mask = CLOCKSOURCE_MASK(64), + .mult = 0, /* to be set */ + .shift = 22, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void lguest_setup_clocksource(void) +{ + lguest_clock.mult = lguest_data.clock_mult; + clocksource_register(&lguest_clock); +} + static void lguest_time_init(void) { + lguest_setup_clocksource(); set_irq_handler(0, lguest_time_irq); hcall(LHCALL_TIMER_START,HZ,0,0); } diff --git a/include/asm-i386/lguest.h b/include/asm-i386/lguest.h index e97650d..7e6a289 100644 --- a/include/asm-i386/lguest.h +++ b/include/asm-i386/lguest.h @@ -100,6 +100,8 @@ struct lguest_data unsigned long reserve_mem; /* ID of this guest (used by network driver to set ethernet address) */ u16 guestid; + /* Multiplier for TSC clock. */ + u32 clock_mult; /* Fields initialized by the guest at boot: */ /* Instruction range to suppress interrupts even if enabled */ -- 1.4.2.1