select ARCH_THREAD_STACK_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
        select GENERIC_TIME_VSYSCALL
+       select LEGACY_TIMER_TICK
        select SWIOTLB
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select HAVE_MOD_ARCH_SPECIFIC
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id)
 {
-       unsigned long new_itm;
+       unsigned long cur_itm, new_itm, ticks;
 
        if (cpu_is_offline(smp_processor_id())) {
                return IRQ_HANDLED;
        }
 
        new_itm = local_cpu_data->itm_next;
+       cur_itm = ia64_get_itc();
 
-       if (!time_after(ia64_get_itc(), new_itm))
+       if (!time_after(cur_itm, new_itm)) {
                printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
-                      ia64_get_itc(), new_itm);
-
-       profile_tick(CPU_PROFILING);
-
-       while (1) {
-               update_process_times(user_mode(get_irq_regs()));
-
-               new_itm += local_cpu_data->itm_delta;
-
-               if (smp_processor_id() == time_keeper_id)
-                       xtime_update(1);
-
-               local_cpu_data->itm_next = new_itm;
+                      cur_itm, new_itm);
+               ticks = 1;
+       } else {
+               ticks = DIV_ROUND_UP(cur_itm - new_itm,
+                                    local_cpu_data->itm_delta);
+               new_itm += ticks * local_cpu_data->itm_delta;
+       }
 
-               if (time_after(new_itm, ia64_get_itc()))
-                       break;
+       if (smp_processor_id() != time_keeper_id)
+               ticks = 0;
 
-               /*
-                * Allow IPIs to interrupt the timer loop.
-                */
-               local_irq_enable();
-               local_irq_disable();
-       }
+       legacy_timer_tick(ticks);
 
        do {
                /*