/**
  * struct hrtimer_base - the timer base for a specific clock
  *
- * @index:     clock type index for per_cpu support when moving a timer
- *             to a base on another cpu.
- * @lock:      lock protecting the base and associated timers
- * @active:    red black tree root node for the active timers
- * @first:     pointer to the timer node which expires first
- * @resolution:        the resolution of the clock, in nanoseconds
- * @get_time:  function to retrieve the current time of the clock
- * @curr_timer:        the timer which is executing a callback right now
+ * @index:             clock type index for per_cpu support when moving a timer
+ *                     to a base on another cpu.
+ * @lock:              lock protecting the base and associated timers
+ * @active:            red black tree root node for the active timers
+ * @first:             pointer to the timer node which expires first
+ * @resolution:                the resolution of the clock, in nanoseconds
+ * @get_time:          function to retrieve the current time of the clock
+ * @get_sofirq_time:   function to retrieve the current time from the softirq
+ * @curr_timer:                the timer which is executing a callback right now
+ * @softirq_time:      the time when running the hrtimer queue in the softirq
  */
 struct hrtimer_base {
        clockid_t               index;
        struct rb_node          *first;
        ktime_t                 resolution;
        ktime_t                 (*get_time)(void);
+       ktime_t                 (*get_softirq_time)(void);
        struct hrtimer          *curr_timer;
+       ktime_t                 softirq_time;
 };
 
 /*
 
 }
 EXPORT_SYMBOL_GPL(ktime_get_ts);
 
+/*
+ * Get the coarse grained time at the softirq based on xtime and
+ * wall_to_monotonic.
+ */
+static void hrtimer_get_softirq_time(struct hrtimer_base *base)
+{
+       ktime_t xtim, tomono;
+       unsigned long seq;
+
+       do {
+               seq = read_seqbegin(&xtime_lock);
+               xtim = timespec_to_ktime(xtime);
+               tomono = timespec_to_ktime(wall_to_monotonic);
+
+       } while (read_seqretry(&xtime_lock, seq));
+
+       base[CLOCK_REALTIME].softirq_time = xtim;
+       base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
+}
+
 /*
  * Functions and macros which are different for UP/SMP systems are kept in a
  * single place
  */
 static inline void run_hrtimer_queue(struct hrtimer_base *base)
 {
-       ktime_t now = base->get_time();
        struct rb_node *node;
 
+       if (base->get_softirq_time)
+               base->softirq_time = base->get_softirq_time();
+
        spin_lock_irq(&base->lock);
 
        while ((node = base->first)) {
                void *data;
 
                timer = rb_entry(node, struct hrtimer, node);
-               if (now.tv64 <= timer->expires.tv64)
+               if (base->softirq_time.tv64 <= timer->expires.tv64)
                        break;
 
                fn = timer->function;
        struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
        int i;
 
+       hrtimer_get_softirq_time(base);
+
        for (i = 0; i < MAX_HRTIMER_BASES; i++)
                run_hrtimer_queue(&base[i]);
 }