1 /***************************************************************************
2  * time.c
3  *
4  * An implementation of some time related Viridian enlightenments.
5  * See Microsoft's Hypervisor Top Level Functional Specification.
6  * for more information.
7  */
8 
9 #include <xen/domain_page.h>
10 #include <xen/hypercall.h>
11 #include <xen/sched.h>
12 #include <xen/version.h>
13 
14 #include <asm/apic.h>
15 #include <asm/event.h>
16 #include <asm/guest/hyperv.h>
17 #include <asm/guest/hyperv-tlfs.h>
18 #include <asm/hvm/support.h>
19 
20 #include "private.h"
21 
update_reference_tsc(const struct domain * d,bool initialize)22 static void update_reference_tsc(const struct domain *d, bool initialize)
23 {
24     struct viridian_domain *vd = d->arch.hvm.viridian;
25     const struct viridian_time_ref_count *trc = &vd->time_ref_count;
26     const struct viridian_page *rt = &vd->reference_tsc;
27     HV_REFERENCE_TSC_PAGE *p = rt->ptr;
28     uint32_t seq;
29 
30     if ( initialize )
31         clear_page(p);
32 
33     /*
34      * This enlightenment must be disabled is the host TSC is not invariant.
35      * However it is also disabled if vtsc is true (which means rdtsc is
36      * being emulated). This generally happens when guest TSC freq and host
37      * TSC freq don't match. The TscScale value could be adjusted to cope
38      * with this, allowing vtsc to be turned off, but support for this is
39      * not yet present in the hypervisor. Thus is it is possible that
40      * migrating a Windows VM between hosts of differing TSC frequencies
41      * may result in large differences in guest performance. Any jump in
42      * TSC due to migration down-time can, however, be compensated for by
43      * setting the TscOffset value (see below).
44      */
45     if ( !host_tsc_is_safe() || d->arch.vtsc )
46     {
47         /*
48          * The value 0 is used to indicate this mechanism is no longer a
49          * reliable source of time and that the VM should fall back to a
50          * different source.
51          */
52         p->tsc_sequence = 0;
53 
54         printk(XENLOG_G_INFO "d%d: VIRIDIAN REFERENCE_TSC: invalidated\n",
55                d->domain_id);
56         return;
57     }
58 
59     /*
60      * The guest will calculate reference time according to the following
61      * formula:
62      *
63      * ReferenceTime = ((RDTSC() * TscScale) >> 64) + TscOffset
64      *
65      * Windows uses a 100ns tick, so we need a scale which is cpu
66      * ticks per 100ns shifted left by 64.
67      * The offset value is calculated on restore after migration and
68      * ensures that Windows will not see a large jump in ReferenceTime.
69      */
70     p->tsc_scale = ((10000ul << 32) / d->arch.tsc_khz) << 32;
71     p->tsc_offset = trc->off;
72     smp_wmb();
73 
74     seq = p->tsc_sequence + 1;
75     p->tsc_sequence = seq ? seq : 1; /* Avoid 'invalid' value 0 */
76 }
77 
trc_val(const struct domain * d,int64_t offset)78 static uint64_t trc_val(const struct domain *d, int64_t offset)
79 {
80     uint64_t tsc, scale;
81 
82     tsc = hvm_get_guest_tsc(pt_global_vcpu_target(d));
83     scale = ((10000ul << 32) / d->arch.tsc_khz) << 32;
84 
85     return hv_scale_tsc(tsc, scale, offset);
86 }
87 
time_ref_count_freeze(const struct domain * d)88 static void time_ref_count_freeze(const struct domain *d)
89 {
90     struct viridian_time_ref_count *trc =
91         &d->arch.hvm.viridian->time_ref_count;
92 
93     if ( test_and_clear_bit(_TRC_running, &trc->flags) )
94         trc->val = trc_val(d, trc->off);
95 }
96 
time_ref_count_thaw(const struct domain * d)97 static void time_ref_count_thaw(const struct domain *d)
98 {
99     struct viridian_domain *vd = d->arch.hvm.viridian;
100     struct viridian_time_ref_count *trc = &vd->time_ref_count;
101 
102     if ( d->is_shutting_down ||
103          test_and_set_bit(_TRC_running, &trc->flags) )
104         return;
105 
106     trc->off = (int64_t)trc->val - trc_val(d, 0);
107 
108     if ( vd->reference_tsc.msr.enabled )
109         update_reference_tsc(d, false);
110 }
111 
time_ref_count(const struct domain * d)112 static uint64_t time_ref_count(const struct domain *d)
113 {
114     const struct viridian_time_ref_count *trc =
115         &d->arch.hvm.viridian->time_ref_count;
116 
117     return trc_val(d, trc->off);
118 }
119 
stop_stimer(struct viridian_stimer * vs)120 static void stop_stimer(struct viridian_stimer *vs)
121 {
122     if ( !vs->started )
123         return;
124 
125     stop_timer(&vs->timer);
126     vs->started = false;
127 }
128 
stimer_expire(void * data)129 static void stimer_expire(void *data)
130 {
131     struct viridian_stimer *vs = data;
132     struct vcpu *v = vs->v;
133     struct viridian_vcpu *vv = v->arch.hvm.viridian;
134     unsigned int stimerx = vs - &vv->stimer[0];
135 
136     set_bit(stimerx, &vv->stimer_pending);
137     vcpu_kick(v);
138 }
139 
start_stimer(struct viridian_stimer * vs)140 static void start_stimer(struct viridian_stimer *vs)
141 {
142     const struct vcpu *v = vs->v;
143     struct viridian_vcpu *vv = v->arch.hvm.viridian;
144     unsigned int stimerx = vs - &vv->stimer[0];
145     int64_t now = time_ref_count(v->domain);
146     int64_t expiration;
147     s_time_t timeout;
148 
149     if ( !test_and_set_bit(stimerx, &vv->stimer_enabled) )
150         printk(XENLOG_G_INFO "%pv: VIRIDIAN STIMER%u: enabled\n", v,
151                stimerx);
152 
153     if ( vs->config.periodic )
154     {
155         /*
156          * The specification says that if the timer is lazy then we
157          * skip over any missed expirations so we can treat this case
158          * as the same as if the timer is currently stopped, i.e. we
159          * just schedule expiration to be 'count' ticks from now.
160          */
161         if ( !vs->started || vs->config.lazy )
162             expiration = now + vs->count;
163         else
164         {
165             unsigned int missed = 0;
166 
167             /*
168              * The timer is already started, so we're re-scheduling.
169              * Hence advance the timer expiration by one tick.
170              */
171             expiration = vs->expiration + vs->count;
172 
173             /* Now check to see if any expirations have been missed */
174             if ( expiration - now <= 0 )
175                 missed = ((now - expiration) / vs->count) + 1;
176 
177             /*
178              * The specification says that if the timer is not lazy then
179              * a non-zero missed count should be used to reduce the period
180              * of the timer until it catches up, unless the count has
181              * reached a 'significant number', in which case the timer
182              * should be treated as lazy. Unfortunately the specification
183              * does not state what that number is so the choice of number
184              * here is a pure guess.
185              */
186             if ( missed > 3 )
187                 expiration = now + vs->count;
188             else if ( missed )
189                 expiration = now + (vs->count / missed);
190         }
191     }
192     else
193     {
194         expiration = vs->count;
195         if ( expiration - now <= 0 )
196         {
197             vs->expiration = expiration;
198             stimer_expire(vs);
199             return;
200         }
201     }
202     ASSERT(expiration - now > 0);
203 
204     vs->expiration = expiration;
205     timeout = (expiration - now) * 100ull;
206 
207     vs->started = true;
208     clear_bit(stimerx, &vv->stimer_pending);
209     migrate_timer(&vs->timer, v->processor);
210     set_timer(&vs->timer, timeout + NOW());
211 }
212 
poll_stimer(struct vcpu * v,unsigned int stimerx)213 static void poll_stimer(struct vcpu *v, unsigned int stimerx)
214 {
215     struct viridian_vcpu *vv = v->arch.hvm.viridian;
216     struct viridian_stimer *vs = &vv->stimer[stimerx];
217 
218     /*
219      * Timer expiry may race with the timer being disabled. If the timer
220      * is disabled make sure the pending bit is cleared to avoid re-
221      * polling.
222      */
223     if ( !vs->config.enable )
224     {
225         clear_bit(stimerx, &vv->stimer_pending);
226         return;
227     }
228 
229     if ( !test_bit(stimerx, &vv->stimer_pending) )
230         return;
231 
232     if ( !viridian_synic_deliver_timer_msg(v, vs->config.sintx,
233                                            stimerx, vs->expiration,
234                                            time_ref_count(v->domain)) )
235         return;
236 
237     clear_bit(stimerx, &vv->stimer_pending);
238 
239     if ( vs->config.periodic )
240         start_stimer(vs);
241     else
242         vs->config.enable = 0;
243 }
244 
viridian_time_poll_timers(struct vcpu * v)245 void viridian_time_poll_timers(struct vcpu *v)
246 {
247     struct viridian_vcpu *vv = v->arch.hvm.viridian;
248     unsigned int i;
249 
250     if ( !vv->stimer_pending )
251        return;
252 
253     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
254         poll_stimer(v, i);
255 }
256 
time_vcpu_freeze(struct vcpu * v)257 static void time_vcpu_freeze(struct vcpu *v)
258 {
259     struct viridian_vcpu *vv = v->arch.hvm.viridian;
260     unsigned int i;
261 
262     if ( !is_viridian_vcpu(v) ||
263          !(viridian_feature_mask(v->domain) & HVMPV_stimer) )
264         return;
265 
266     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
267     {
268         struct viridian_stimer *vs = &vv->stimer[i];
269 
270         if ( vs->started )
271             stop_timer(&vs->timer);
272     }
273 }
274 
time_vcpu_thaw(struct vcpu * v)275 static void time_vcpu_thaw(struct vcpu *v)
276 {
277     struct viridian_vcpu *vv = v->arch.hvm.viridian;
278     unsigned int i;
279 
280     if ( !is_viridian_vcpu(v) ||
281          !(viridian_feature_mask(v->domain) & HVMPV_stimer) )
282         return;
283 
284     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
285     {
286         struct viridian_stimer *vs = &vv->stimer[i];
287 
288         if ( vs->config.enable )
289             start_stimer(vs);
290     }
291 }
292 
viridian_time_domain_freeze(const struct domain * d)293 void viridian_time_domain_freeze(const struct domain *d)
294 {
295     struct vcpu *v;
296 
297     if ( d->is_dying || !is_viridian_domain(d) )
298         return;
299 
300     for_each_vcpu ( d, v )
301         time_vcpu_freeze(v);
302 
303     time_ref_count_freeze(d);
304 }
305 
viridian_time_domain_thaw(const struct domain * d)306 void viridian_time_domain_thaw(const struct domain *d)
307 {
308     struct vcpu *v;
309 
310     if ( d->is_dying || !is_viridian_domain(d) )
311         return;
312 
313     time_ref_count_thaw(d);
314 
315     for_each_vcpu ( d, v )
316         time_vcpu_thaw(v);
317 }
318 
viridian_time_wrmsr(struct vcpu * v,uint32_t idx,uint64_t val)319 int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val)
320 {
321     struct viridian_vcpu *vv = v->arch.hvm.viridian;
322     struct domain *d = v->domain;
323     struct viridian_domain *vd = d->arch.hvm.viridian;
324 
325     switch ( idx )
326     {
327     case HV_X64_MSR_REFERENCE_TSC:
328         if ( !(viridian_feature_mask(d) & HVMPV_reference_tsc) )
329             return X86EMUL_EXCEPTION;
330 
331         viridian_unmap_guest_page(&vd->reference_tsc);
332         vd->reference_tsc.msr.raw = val;
333         viridian_dump_guest_page(v, "REFERENCE_TSC", &vd->reference_tsc);
334         if ( vd->reference_tsc.msr.enabled )
335         {
336             viridian_map_guest_page(d, &vd->reference_tsc);
337             update_reference_tsc(d, true);
338         }
339         break;
340 
341     case HV_X64_MSR_TIME_REF_COUNT:
342         return X86EMUL_EXCEPTION;
343 
344     case HV_X64_MSR_STIMER0_CONFIG:
345     case HV_X64_MSR_STIMER1_CONFIG:
346     case HV_X64_MSR_STIMER2_CONFIG:
347     case HV_X64_MSR_STIMER3_CONFIG:
348     {
349         unsigned int stimerx = (idx - HV_X64_MSR_STIMER0_CONFIG) / 2;
350         struct viridian_stimer *vs =
351             &array_access_nospec(vv->stimer, stimerx);
352 
353         if ( !(viridian_feature_mask(d) & HVMPV_stimer) )
354             return X86EMUL_EXCEPTION;
355 
356         stop_stimer(vs);
357 
358         vs->config.as_uint64 = val;
359 
360         if ( !vs->config.sintx )
361             vs->config.enable = 0;
362 
363         if ( vs->config.enable )
364             start_stimer(vs);
365 
366         break;
367     }
368 
369     case HV_X64_MSR_STIMER0_COUNT:
370     case HV_X64_MSR_STIMER1_COUNT:
371     case HV_X64_MSR_STIMER2_COUNT:
372     case HV_X64_MSR_STIMER3_COUNT:
373     {
374         unsigned int stimerx = (idx - HV_X64_MSR_STIMER0_CONFIG) / 2;
375         struct viridian_stimer *vs =
376             &array_access_nospec(vv->stimer, stimerx);
377 
378         if ( !(viridian_feature_mask(d) & HVMPV_stimer) )
379             return X86EMUL_EXCEPTION;
380 
381         stop_stimer(vs);
382 
383         vs->count = val;
384 
385         if ( !vs->count  )
386             vs->config.enable = 0;
387         else if ( vs->config.auto_enable )
388             vs->config.enable = 1;
389 
390         if ( vs->config.enable )
391             start_stimer(vs);
392 
393         break;
394     }
395 
396     default:
397         gdprintk(XENLOG_INFO, "%s: unimplemented MSR %#x (%016"PRIx64")\n",
398                  __func__, idx, val);
399         return X86EMUL_EXCEPTION;
400     }
401 
402     return X86EMUL_OKAY;
403 }
404 
viridian_time_rdmsr(const struct vcpu * v,uint32_t idx,uint64_t * val)405 int viridian_time_rdmsr(const struct vcpu *v, uint32_t idx, uint64_t *val)
406 {
407     const struct viridian_vcpu *vv = v->arch.hvm.viridian;
408     const struct domain *d = v->domain;
409     struct viridian_domain *vd = d->arch.hvm.viridian;
410 
411     switch ( idx )
412     {
413     case HV_X64_MSR_TSC_FREQUENCY:
414         if ( viridian_feature_mask(d) & HVMPV_no_freq )
415             return X86EMUL_EXCEPTION;
416 
417         *val = (uint64_t)d->arch.tsc_khz * 1000ull;
418         break;
419 
420     case HV_X64_MSR_APIC_FREQUENCY:
421         if ( viridian_feature_mask(d) & HVMPV_no_freq )
422             return X86EMUL_EXCEPTION;
423 
424         *val = 1000000000ull / APIC_BUS_CYCLE_NS;
425         break;
426 
427     case HV_X64_MSR_REFERENCE_TSC:
428         if ( !(viridian_feature_mask(d) & HVMPV_reference_tsc) )
429             return X86EMUL_EXCEPTION;
430 
431         *val = vd->reference_tsc.msr.raw;
432         break;
433 
434     case HV_X64_MSR_TIME_REF_COUNT:
435     {
436         struct viridian_time_ref_count *trc = &vd->time_ref_count;
437 
438         if ( !(viridian_feature_mask(d) & HVMPV_time_ref_count) )
439             return X86EMUL_EXCEPTION;
440 
441         if ( !test_and_set_bit(_TRC_accessed, &trc->flags) )
442             printk(XENLOG_G_INFO "d%d: VIRIDIAN MSR_TIME_REF_COUNT: accessed\n",
443                    d->domain_id);
444 
445         *val = time_ref_count(d);
446         break;
447     }
448 
449     case HV_X64_MSR_STIMER0_CONFIG:
450     case HV_X64_MSR_STIMER1_CONFIG:
451     case HV_X64_MSR_STIMER2_CONFIG:
452     case HV_X64_MSR_STIMER3_CONFIG:
453     {
454         unsigned int stimerx = (idx - HV_X64_MSR_STIMER0_CONFIG) / 2;
455         const struct viridian_stimer *vs =
456             &array_access_nospec(vv->stimer, stimerx);
457         union hv_stimer_config config = vs->config;
458 
459         if ( !(viridian_feature_mask(d) & HVMPV_stimer) )
460             return X86EMUL_EXCEPTION;
461 
462         /*
463          * If the timer is single-shot and it has expired, make sure
464          * the enabled flag is clear.
465          */
466         if ( !config.periodic && test_bit(stimerx, &vv->stimer_pending) )
467             config.enable = 0;
468 
469         *val = config.as_uint64;
470         break;
471     }
472 
473     case HV_X64_MSR_STIMER0_COUNT:
474     case HV_X64_MSR_STIMER1_COUNT:
475     case HV_X64_MSR_STIMER2_COUNT:
476     case HV_X64_MSR_STIMER3_COUNT:
477     {
478         unsigned int stimerx = (idx - HV_X64_MSR_STIMER0_CONFIG) / 2;
479         const struct viridian_stimer *vs =
480             &array_access_nospec(vv->stimer, stimerx);
481 
482         if ( !(viridian_feature_mask(d) & HVMPV_stimer) )
483             return X86EMUL_EXCEPTION;
484 
485         *val = vs->count;
486         break;
487     }
488 
489     default:
490         gdprintk(XENLOG_INFO, "%s: unimplemented MSR %#x\n", __func__, idx);
491         return X86EMUL_EXCEPTION;
492     }
493 
494     return X86EMUL_OKAY;
495 }
496 
viridian_time_vcpu_init(struct vcpu * v)497 int viridian_time_vcpu_init(struct vcpu *v)
498 {
499     struct viridian_vcpu *vv = v->arch.hvm.viridian;
500     unsigned int i;
501 
502     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
503     {
504         struct viridian_stimer *vs = &vv->stimer[i];
505 
506         vs->v = v;
507         init_timer(&vs->timer, stimer_expire, vs, v->processor);
508     }
509 
510     return 0;
511 }
512 
viridian_time_domain_init(const struct domain * d)513 int viridian_time_domain_init(const struct domain *d)
514 {
515     return 0;
516 }
517 
viridian_time_vcpu_deinit(const struct vcpu * v)518 void viridian_time_vcpu_deinit(const struct vcpu *v)
519 {
520     struct viridian_vcpu *vv = v->arch.hvm.viridian;
521     unsigned int i;
522 
523     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
524     {
525         struct viridian_stimer *vs = &vv->stimer[i];
526 
527         if ( !vs->v )
528             continue;
529         kill_timer(&vs->timer);
530         vs->v = NULL;
531     }
532 }
533 
viridian_time_domain_deinit(const struct domain * d)534 void viridian_time_domain_deinit(const struct domain *d)
535 {
536     viridian_unmap_guest_page(&d->arch.hvm.viridian->reference_tsc);
537 }
538 
viridian_time_save_vcpu_ctxt(const struct vcpu * v,struct hvm_viridian_vcpu_context * ctxt)539 void viridian_time_save_vcpu_ctxt(
540     const struct vcpu *v, struct hvm_viridian_vcpu_context *ctxt)
541 {
542     const struct viridian_vcpu *vv = v->arch.hvm.viridian;
543     unsigned int i;
544 
545     BUILD_BUG_ON(ARRAY_SIZE(vv->stimer) !=
546                  ARRAY_SIZE(ctxt->stimer_config_msr));
547     BUILD_BUG_ON(ARRAY_SIZE(vv->stimer) !=
548                  ARRAY_SIZE(ctxt->stimer_count_msr));
549 
550     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
551     {
552         const struct viridian_stimer *vs = &vv->stimer[i];
553 
554         ctxt->stimer_config_msr[i] = vs->config.as_uint64;
555         ctxt->stimer_count_msr[i] = vs->count;
556     }
557 }
558 
viridian_time_load_vcpu_ctxt(struct vcpu * v,const struct hvm_viridian_vcpu_context * ctxt)559 void viridian_time_load_vcpu_ctxt(
560     struct vcpu *v, const struct hvm_viridian_vcpu_context *ctxt)
561 {
562     struct viridian_vcpu *vv = v->arch.hvm.viridian;
563     unsigned int i;
564 
565     for ( i = 0; i < ARRAY_SIZE(vv->stimer); i++ )
566     {
567         struct viridian_stimer *vs = &vv->stimer[i];
568 
569         vs->config.as_uint64 = ctxt->stimer_config_msr[i];
570         vs->count = ctxt->stimer_count_msr[i];
571     }
572 }
573 
viridian_time_save_domain_ctxt(const struct domain * d,struct hvm_viridian_domain_context * ctxt)574 void viridian_time_save_domain_ctxt(
575     const struct domain *d, struct hvm_viridian_domain_context *ctxt)
576 {
577     const struct viridian_domain *vd = d->arch.hvm.viridian;
578 
579     ctxt->time_ref_count = vd->time_ref_count.val;
580     ctxt->reference_tsc = vd->reference_tsc.msr.raw;
581 }
582 
viridian_time_load_domain_ctxt(struct domain * d,const struct hvm_viridian_domain_context * ctxt)583 void viridian_time_load_domain_ctxt(
584     struct domain *d, const struct hvm_viridian_domain_context *ctxt)
585 {
586     struct viridian_domain *vd = d->arch.hvm.viridian;
587 
588     vd->time_ref_count.val = ctxt->time_ref_count;
589     vd->reference_tsc.msr.raw = ctxt->reference_tsc;
590 
591     if ( vd->reference_tsc.msr.enabled )
592         viridian_map_guest_page(d, &vd->reference_tsc);
593 }
594 
595 /*
596  * Local variables:
597  * mode: C
598  * c-file-style: "BSD"
599  * c-basic-offset: 4
600  * tab-width: 4
601  * indent-tabs-mode: nil
602  * End:
603  */
604