Commit e0b306fef90556233797d2e1747bd6a3ae35ea93

Authored by Marcelo Tosatti
1 parent 886b470cb1

time: export time information for KVM pvclock

As suggested by John, export time data similarly to how its
done by vsyscall support. This allows KVM to retrieve necessary
information to implement vsyscall support in KVM guests.

Acked-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

Showing 2 changed files with 59 additions and 0 deletions Side-by-side Diff

include/linux/pvclock_gtod.h
  1 +#ifndef _PVCLOCK_GTOD_H
  2 +#define _PVCLOCK_GTOD_H
  3 +
  4 +#include <linux/notifier.h>
  5 +
  6 +extern int pvclock_gtod_register_notifier(struct notifier_block *nb);
  7 +extern int pvclock_gtod_unregister_notifier(struct notifier_block *nb);
  8 +
  9 +#endif /* _PVCLOCK_GTOD_H */
kernel/time/timekeeping.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/time.h>
22 22 #include <linux/tick.h>
23 23 #include <linux/stop_machine.h>
  24 +#include <linux/pvclock_gtod.h>
24 25  
25 26  
26 27 static struct timekeeper timekeeper;
... ... @@ -180,6 +181,54 @@
180 181 return nsec + arch_gettimeoffset();
181 182 }
182 183  
  184 +static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
  185 +
  186 +static void update_pvclock_gtod(struct timekeeper *tk)
  187 +{
  188 + raw_notifier_call_chain(&pvclock_gtod_chain, 0, tk);
  189 +}
  190 +
  191 +/**
  192 + * pvclock_gtod_register_notifier - register a pvclock timedata update listener
  193 + *
  194 + * Must hold write on timekeeper.lock
  195 + */
  196 +int pvclock_gtod_register_notifier(struct notifier_block *nb)
  197 +{
  198 + struct timekeeper *tk = &timekeeper;
  199 + unsigned long flags;
  200 + int ret;
  201 +
  202 + write_seqlock_irqsave(&tk->lock, flags);
  203 + ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb);
  204 + /* update timekeeping data */
  205 + update_pvclock_gtod(tk);
  206 + write_sequnlock_irqrestore(&tk->lock, flags);
  207 +
  208 + return ret;
  209 +}
  210 +EXPORT_SYMBOL_GPL(pvclock_gtod_register_notifier);
  211 +
  212 +/**
  213 + * pvclock_gtod_unregister_notifier - unregister a pvclock
  214 + * timedata update listener
  215 + *
  216 + * Must hold write on timekeeper.lock
  217 + */
  218 +int pvclock_gtod_unregister_notifier(struct notifier_block *nb)
  219 +{
  220 + struct timekeeper *tk = &timekeeper;
  221 + unsigned long flags;
  222 + int ret;
  223 +
  224 + write_seqlock_irqsave(&tk->lock, flags);
  225 + ret = raw_notifier_chain_unregister(&pvclock_gtod_chain, nb);
  226 + write_sequnlock_irqrestore(&tk->lock, flags);
  227 +
  228 + return ret;
  229 +}
  230 +EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier);
  231 +
183 232 /* must hold write on timekeeper.lock */
184 233 static void timekeeping_update(struct timekeeper *tk, bool clearntp)
185 234 {
... ... @@ -188,6 +237,7 @@
188 237 ntp_clear();
189 238 }
190 239 update_vsyscall(tk);
  240 + update_pvclock_gtod(tk);
191 241 }
192 242  
193 243 /**