diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index 871448db1425ffe77a10be780d2fddb6901f2b6c..2ec331e03fa9ede01a5bed5bee5faf1043b9f6dd 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -494,7 +494,7 @@ struct paravirt_ops paravirt_ops = {
 	.memory_setup = machine_specific_memory_setup,
 	.get_wallclock = native_get_wallclock,
 	.set_wallclock = native_set_wallclock,
-	.time_init = time_init_hook,
+	.time_init = hpet_time_init,
 	.init_IRQ = native_init_IRQ,
 
 	.cpuid = native_cpuid,
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index a5350059557a6541c0c96b8f8ba6933073999d05..ccd3734edb8ff46112ff469a01fc3168f28b0d89 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -262,14 +262,22 @@ void notify_arch_cmos_timer(void)
 
 extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
-static void __init hpet_time_init(void)
+void __init hpet_time_init(void)
 {
 	if (!hpet_enable())
 		setup_pit_timer();
-	do_time_init();
+	time_init_hook();
 }
 
+/*
+ * This is called directly from init code; we must delay timer setup in the
+ * HPET case as we can't make the decision to turn on HPET this early in the
+ * boot process.
+ *
+ * The chosen time_init function will usually be hpet_time_init, above, but
+ * in the case of virtual hardware, an alternative function may be substituted.
+ */
 void __init time_init(void)
 {
-	late_time_init = hpet_time_init;
+	late_time_init = choose_time_init();
 }
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
index 1e4226a85263c73d0b270d33a7bb4a97c6d63f2f..f8319cae2ac5c6b789ed974c0de59a044efd9877 100644
--- a/include/asm-i386/paravirt.h
+++ b/include/asm-i386/paravirt.h
@@ -186,9 +186,9 @@ static inline int set_wallclock(unsigned long nowtime)
 	return paravirt_ops.set_wallclock(nowtime);
 }
 
-static inline void do_time_init(void)
+static inline void (*choose_time_init(void))(void)
 {
-	return paravirt_ops.time_init();
+	return paravirt_ops.time_init;
 }
 
 /* The paravirtualized CPUID instruction. */
diff --git a/include/asm-i386/time.h b/include/asm-i386/time.h
index ea8065af825a998654e23a92ffc18e60f34885ec..eac011366dc2c09337abfe3d146bafcb01b1d686 100644
--- a/include/asm-i386/time.h
+++ b/include/asm-i386/time.h
@@ -28,13 +28,16 @@ static inline int native_set_wallclock(unsigned long nowtime)
 	return retval;
 }
 
+extern void (*late_time_init)(void);
+extern void hpet_time_init(void);
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else /* !CONFIG_PARAVIRT */
 
 #define get_wallclock() native_get_wallclock()
 #define set_wallclock(x) native_set_wallclock(x)
-#define do_time_init() time_init_hook()
+#define choose_time_init() hpet_time_init
 
 #endif /* CONFIG_PARAVIRT */