Commit e0b306fef90556233797d2e1747bd6a3ae35ea93
1 parent
886b470cb1
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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
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 | /** |