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