ChangeSet 1.1505, 2005/05/21 13:40:44+01:00, cl349@xxxxxxxxxxxxxxxxxxxx
Merge firebug.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into firebug.cl.cam.ac.uk:/local/scratch/cl349/xen-unstable.bk
time.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 87 insertions(+), 22 deletions(-)
diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c 2005-05-22
13:04:27 -04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c 2005-05-22
13:04:27 -04:00
@@ -47,6 +47,7 @@
#include <linux/efi.h>
#include <linux/mca.h>
#include <linux/sysctl.h>
+#include <linux/percpu.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -76,7 +77,20 @@
EXPORT_SYMBOL(jiffies_64);
+#if defined(__x86_64__)
+unsigned long vxtime_hz = PIT_TICK_RATE;
+struct vxtime_data __vxtime __section_vxtime; /* for vsyscalls */
+volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
+struct timespec __xtime __section_xtime;
+struct timezone __sys_tz __section_sys_tz;
+#endif
+
+#if defined(__x86_64__)
+unsigned int cpu_khz; /* Detected as we calibrate the TSC */
+#else
unsigned long cpu_khz; /* Detected as we calibrate the TSC */
+#endif
extern unsigned long wall_jiffies;
@@ -94,7 +108,6 @@
u64 shadow_system_time;
static u32 shadow_time_version;
static struct timeval shadow_tv;
-extern u64 processed_system_time;
/*
* We use this to ensure that gettimeofday() is monotonically increasing. We
@@ -111,7 +124,8 @@
static long last_update_from_xen; /* UTC seconds when last read Xen clock. */
/* Keep track of last time we did processing/updating of jiffies and xtime. */
-u64 processed_system_time; /* System time (ns) at last processing. */
+static u64 processed_system_time; /* System time (ns) at last processing. */
+static DEFINE_PER_CPU(u64, processed_system_time);
#define NS_PER_TICK (1000000000ULL/HZ)
@@ -378,39 +392,52 @@
struct pt_regs *regs)
{
time_t wtm_sec, sec;
- s64 delta, nsec;
+ s64 delta, delta_cpu, nsec;
long sec_diff, wtm_nsec;
+ int cpu = smp_processor_id();
do {
__get_time_values_from_xen();
- delta = (s64)(shadow_system_time +
- ((s64)cur_timer->get_offset() *
- (s64)NSEC_PER_USEC) -
- processed_system_time);
+ delta = delta_cpu = (s64)shadow_system_time +
+ ((s64)cur_timer->get_offset() * (s64)NSEC_PER_USEC);
+ delta -= processed_system_time;
+ delta_cpu -= per_cpu(processed_system_time, cpu);
}
while (!TIME_VALUES_UP_TO_DATE);
- if (unlikely(delta < 0)) {
- printk("Timer ISR: Time went backwards: %lld %lld %lld %lld\n",
- delta, shadow_system_time,
+ if (unlikely(delta < 0) || unlikely(delta_cpu < 0)) {
+ printk("Timer ISR/%d: Time went backwards: "
+ "delta=%lld cpu_delta=%lld shadow=%lld "
+ "off=%lld processed=%lld cpu_processed=%lld\n",
+ cpu, delta, delta_cpu, shadow_system_time,
((s64)cur_timer->get_offset() * (s64)NSEC_PER_USEC),
- processed_system_time);
+ processed_system_time,
+ per_cpu(processed_system_time, cpu));
+ for (cpu = 0; cpu < num_online_cpus(); cpu++)
+ printk(" %d: %lld\n", cpu,
+ per_cpu(processed_system_time, cpu));
return;
}
- /* Process elapsed jiffies since last call. */
+ /* System-wide jiffy work. */
while (delta >= NS_PER_TICK) {
delta -= NS_PER_TICK;
processed_system_time += NS_PER_TICK;
do_timer(regs);
-#ifndef CONFIG_SMP
+ }
+
+ /* Local CPU jiffy work. */
+ while (delta_cpu >= NS_PER_TICK) {
+ delta_cpu -= NS_PER_TICK;
+ per_cpu(processed_system_time, cpu) += NS_PER_TICK;
update_process_times(user_mode(regs));
-#endif
- if (regs)
- profile_tick(CPU_PROFILING, regs);
+ profile_tick(CPU_PROFILING, regs);
}
+ if (cpu != 0)
+ return;
+
/*
* Take synchronised time from Xen once a minute if we're not
* synchronised ourselves, and we haven't chosen to keep an independent
@@ -618,10 +645,10 @@
#endif
/* Dynamically-mapped IRQ. */
-static int TIMER_IRQ;
+static DEFINE_PER_CPU(int, timer_irq);
static struct irqaction irq_timer = {
- timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer",
+ timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer0",
NULL, NULL
};
@@ -643,14 +670,23 @@
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
processed_system_time = shadow_system_time;
+ per_cpu(processed_system_time, 0) = processed_system_time;
if (timer_tsc_init.init(NULL) != 0)
BUG();
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
- TIMER_IRQ = bind_virq_to_irq(VIRQ_TIMER);
+#if defined(__x86_64__)
+ vxtime.mode = VXTIME_TSC;
+ vxtime.quot = (1000000L << 32) / vxtime_hz;
+ vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+ vxtime.hz = vxtime_hz;
+ sync_core();
+ rdtscll(vxtime.last_tsc);
+#endif
- (void)setup_irq(TIMER_IRQ, &irq_timer);
+ per_cpu(timer_irq, 0) = bind_virq_to_irq(VIRQ_TIMER);
+ (void)setup_irq(per_cpu(timer_irq, 0), &irq_timer);
}
/* Convert jiffies to system time. Call with xtime_lock held for reading. */
@@ -679,16 +715,26 @@
u64 alarm = 0;
int ret = 0;
unsigned long j;
+#ifdef CONFIG_SMP
+ unsigned long seq;
+#endif
/*
* This is safe against long blocking (since calculations are
* not based on TSC deltas). It is also safe against warped
* system time since suspend-resume is cooperative and we
- * would first get locked out. It is safe against normal
- * updates of jiffies since interrupts are off.
+ * would first get locked out.
*/
+#ifdef CONFIG_SMP
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ j = jiffies + 1;
+ alarm = __jiffies_to_st(j);
+ } while (read_seqretry(&xtime_lock, seq));
+#else
j = next_timer_interrupt();
alarm = __jiffies_to_st(j);
+#endif
/* Failure is pretty bad, but we'd best soldier on. */
if ( HYPERVISOR_set_timer_op(alarm) != 0 )
@@ -713,6 +759,7 @@
/* Reset our own concept of passage of system time. */
processed_system_time = shadow_system_time;
+ per_cpu(processed_system_time, 0) = processed_system_time;
/* Accept a warp in UTC (wall-clock) time. */
last_seen_tv.tv_sec = 0;
@@ -720,6 +767,24 @@
/* Make sure we resync UTC time with Xen on next timer interrupt. */
last_update_from_xen = 0;
}
+
+#ifdef CONFIG_SMP
+static char timer_name[NR_CPUS][15];
+void local_setup_timer(void)
+{
+ int seq, cpu = smp_processor_id();
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ per_cpu(processed_system_time, cpu) = shadow_system_time;
+ } while (read_seqretry(&xtime_lock, seq));
+
+ per_cpu(timer_irq, cpu) = bind_virq_to_irq(VIRQ_TIMER);
+ sprintf(timer_name[cpu], "timer%d", cpu);
+ BUG_ON(request_irq(per_cpu(timer_irq, cpu), timer_interrupt,
+ SA_INTERRUPT, timer_name[cpu], NULL));
+}
+#endif
/*
* /proc/sys/xen: This really belongs in another file. It can stay here for
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|