31
31
*/
32
32
33
33
#include <pthread.h>
34
- #include <assert.h>
35
34
#include <errno.h>
36
35
#include <stdbool.h>
37
36
#include <stdio.h>
37
+ #include <err.h>
38
+ #include <sysexits.h>
38
39
#include <string.h>
39
40
#include <unistd.h>
40
41
58
59
*/
59
60
#define VHPET_NUM_TIMERS (8)
60
61
61
- #define VHPET_LOCK () \
62
- do { \
63
- int err; \
64
- err = pthread_mutex_lock(&vhpet_mtx); \
65
- assert(err == 0); \
62
+ #define VHPET_LOCK () \
63
+ do { \
64
+ int err; \
65
+ err = pthread_mutex_lock(&vhpet_mtx); \
66
+ if (err) \
67
+ errx(EX_SOFTWARE, "pthread_mutex_lock returned %s", \
68
+ strerror(err)); \
66
69
} while (0)
67
70
68
- #define VHPET_UNLOCK () \
69
- do { \
70
- int err; \
71
- err = pthread_mutex_unlock(&vhpet_mtx); \
72
- assert(err == 0); \
71
+ #define VHPET_UNLOCK () \
72
+ do { \
73
+ int err; \
74
+ err = pthread_mutex_unlock(&vhpet_mtx); \
75
+ if (err) \
76
+ errx(EX_SOFTWARE, "pthread_mutex_unlock returned %s", \
77
+ strerror(err)); \
73
78
} while (0)
74
79
75
80
#define vhpet_ts_to_ticks (ts ) ts_to_ticks(HPET_FREQ, ts)
@@ -196,13 +201,15 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr)
196
201
val = vhpet -> countbase ;
197
202
198
203
if (vhpet_counter_enabled (vhpet )) {
199
- if (clock_gettime (CLOCK_REALTIME , & now )) {
200
- perror ("clock_gettime failed" );
201
- assert (0 );
202
- }
204
+ if (clock_gettime (CLOCK_REALTIME , & now ))
205
+ errx (EX_SOFTWARE , "clock_gettime returned: %s" , strerror (errno ));
203
206
204
207
/* delta = now - countbase_ts */
205
- assert (timespeccmp (& now , & vhpet -> countbase_ts , >=));
208
+ if (timespeccmp (& now , & vhpet -> countbase_ts , < )) {
209
+ warnx ("vhpet counter going backwards" );
210
+ vhpet -> countbase_ts = now ;
211
+ }
212
+
206
213
delta = now ;
207
214
timespecsub (& delta , & vhpet -> countbase_ts );
208
215
val += vhpet_ts_to_ticks (& delta );
@@ -212,10 +219,15 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr)
212
219
} else {
213
220
/*
214
221
* The timespec corresponding to the 'countbase' is
215
- * meaningless when the counter is disabled. Make sure
216
- * that the caller doesn't want to use it.
222
+ * meaningless when the counter is disabled. Warn if
223
+ * the caller wants to use it.
217
224
*/
218
- assert (nowptr == NULL );
225
+ if (nowptr ) {
226
+ warnx ("vhpet unexpected nowptr" );
227
+ if (clock_gettime (CLOCK_REALTIME , nowptr ))
228
+ errx (EX_SOFTWARE , "clock_gettime returned: %s" ,
229
+ strerror (errno ));
230
+ }
219
231
}
220
232
221
233
return val ;
@@ -228,8 +240,12 @@ vhpet_timer_clear_isr(struct vhpet *vhpet, int n)
228
240
229
241
if (vhpet -> isr & (1 << n )) {
230
242
pin = vhpet_timer_ioapic_pin (vhpet , n );
231
- assert (pin != 0 );
232
- vm_set_gsi_irq (vhpet -> vm , pin , GSI_SET_LOW );
243
+
244
+ if (pin )
245
+ vm_set_gsi_irq (vhpet -> vm , pin , GSI_SET_LOW );
246
+ else
247
+ warnx ("vhpet t%d intr asserted without a valid intr route" , n );
248
+
233
249
vhpet -> isr &= ~(1 << n );
234
250
}
235
251
}
@@ -263,8 +279,8 @@ vhpet_timer_running(struct vhpet *vhpet, int n)
263
279
static inline bool
264
280
vhpet_timer_edge_trig (struct vhpet * vhpet , int n )
265
281
{
266
- assert (!vhpet_timer_msi_enabled (vhpet , n ));
267
- return ( (vhpet -> timer [n ].cap_config & HPET_TCNF_INT_TYPE ) == 0 );
282
+ return (!vhpet_timer_msi_enabled (vhpet , n ) &&
283
+ (vhpet -> timer [n ].cap_config & HPET_TCNF_INT_TYPE ) == 0 );
268
284
}
269
285
270
286
static void
@@ -279,10 +295,17 @@ vhpet_timer_interrupt(struct vhpet *vhpet, int n)
279
295
/*
280
296
* If a level triggered interrupt is already asserted then just return.
281
297
*/
282
- if ((vhpet -> isr & (1 << n )) != 0 ) {
283
- assert (!vhpet_timer_edge_trig (vhpet , n ));
284
- DPRINTF (("hpet t%d intr is already asserted\n" , n ));
285
- return ;
298
+ if (vhpet -> isr & (1 << n )) {
299
+ if (!vhpet_timer_msi_enabled (vhpet , n ) &&
300
+ !vhpet_timer_edge_trig (vhpet , n )) {
301
+ DPRINTF (("hpet t%d intr is already asserted\n" , n ));
302
+ return ;
303
+ } else {
304
+ warnx ("vhpet t%d intr asserted in %s mode" , n ,
305
+ vhpet_timer_msi_enabled (vhpet , n ) ?
306
+ "msi" : "edge-triggered" );
307
+ vhpet -> isr &= ~(1 << n );
308
+ }
286
309
}
287
310
288
311
if (vhpet_timer_msi_enabled (vhpet , n )) {
@@ -331,23 +354,27 @@ vhpet_timer_handler(void *a, uint64_t nexp)
331
354
/* Bail if timer was stopped */
332
355
if (!arg -> running ) {
333
356
DPRINTF (("hpet t%d(%p) already stopped\n" , n , arg ));
334
- assert (ts_is_zero (& vhpet -> timer [n ].expts ));
357
+ if (!ts_is_zero (& vhpet -> timer [n ].expts )) {
358
+ warnx ("vhpet t%d stopped with an expiration time" , n );
359
+ ts_set_zero (& vhpet -> timer [n ].expts );
360
+ }
361
+ goto done ;
362
+ } else if (arg != vhpet_tmrarg (vhpet , n )) {
363
+ warnx ("vhpet t%d observes a stale timer arg" , n );
335
364
goto done ;
336
- } else
337
- assert (arg == vhpet_tmrarg (vhpet , n ));
365
+ }
338
366
339
367
vhpet_timer_interrupt (vhpet , n );
340
368
341
- if (clock_gettime (CLOCK_REALTIME , & now )) {
342
- perror ("clock_gettime failed" );
343
- assert (0 );
344
- }
369
+ if (clock_gettime (CLOCK_REALTIME , & now ))
370
+ errx (EX_SOFTWARE , "clock_gettime returned: %s" , strerror (errno ));
345
371
346
372
if (acrn_timer_gettime (vhpet_tmr (vhpet , n ), & tmrts ))
347
- assert ( 0 );
373
+ errx ( EX_SOFTWARE , "acrn_timer_gettime returned: %s" , strerror ( errno ) );
348
374
349
375
/* One-shot mode has a periodicity of 2^32 ticks */
350
- assert (!ts_is_zero (& tmrts .it_interval ));
376
+ if (ts_is_zero (& tmrts .it_interval ))
377
+ warnx ("vhpet t%d has no periodicity" , n );
351
378
352
379
/*
353
380
* The actual expiration time will be slightly later than expts.
@@ -386,8 +413,8 @@ vhpet_adjust_compval(struct vhpet *vhpet, int n, const struct timespec *now)
386
413
compval = vhpet -> timer [n ].compval ;
387
414
comprate = vhpet -> timer [n ].comprate ;
388
415
389
- assert ( comprate != 0 );
390
- assert ( timespeccmp ( & vhpet -> timer [ n ]. expts , now , < )) ;
416
+ if (! comprate || timespeccmp ( & vhpet -> timer [ n ]. expts , now , >=))
417
+ return ;
391
418
392
419
/* delta = now - expts */
393
420
delta = * now ;
@@ -420,8 +447,11 @@ vhpet_stop_timer(struct vhpet *vhpet, int n, const struct timespec *now,
420
447
{
421
448
struct vhpet_timer_arg * arg ;
422
449
423
- assert (vhpet_timer_running (vhpet , n ));
424
- assert (!ts_is_zero (& vhpet -> timer [n ].expts ));
450
+ if (!vhpet_timer_running (vhpet , n ))
451
+ return ;
452
+
453
+ if (ts_is_zero (& vhpet -> timer [n ].expts ))
454
+ warnx ("vhpet t%d is running without an expiration time" , n );
425
455
426
456
DPRINTF (("hpet t%d stopped\n" , n ));
427
457
@@ -430,12 +460,16 @@ vhpet_stop_timer(struct vhpet *vhpet, int n, const struct timespec *now,
430
460
431
461
/* Cancel the existing timer */
432
462
if (acrn_timer_settime (vhpet_tmr (vhpet , n ), & zero_ts ))
433
- assert ( 0 );
463
+ errx ( EX_SOFTWARE , "acrn_timer_settime returned: %s" , strerror ( errno ) );
434
464
435
465
if (++ vhpet -> timer [n ].tmridx == nitems (vhpet -> timer [n ].tmrlst ))
436
466
vhpet -> timer [n ].tmridx = 0 ;
437
467
438
- assert (!vhpet_timer_running (vhpet , n ));
468
+ if (vhpet_timer_running (vhpet , n )) {
469
+ warnx ("vhpet t%d timer %d is still running" ,
470
+ n , vhpet -> timer [n ].tmridx );
471
+ vhpet_stop_timer (vhpet , n , & zero_ts .it_value , false);
472
+ }
439
473
440
474
/*
441
475
* If the timer was scheduled to expire in the past but hasn't
@@ -444,15 +478,17 @@ vhpet_stop_timer(struct vhpet *vhpet, int n, const struct timespec *now,
444
478
* in the guest. This is especially bad in one-shot mode because
445
479
* the next interrupt has to wait for the counter to wrap around.
446
480
*/
447
- if (timespeccmp (& vhpet -> timer [n ].expts , now , < )) {
448
- DPRINTF (("hpet t%d interrupt triggered after "
449
- "stopping timer\n" , n ));
450
- if (adj_compval && vhpet -> timer [n ].comprate != 0 )
451
- vhpet_adjust_compval (vhpet , n , now );
452
- vhpet_timer_interrupt (vhpet , n );
453
- }
481
+ if (!ts_is_zero (& vhpet -> timer [n ].expts )) {
482
+ if (timespeccmp (& vhpet -> timer [n ].expts , now , < )) {
483
+ DPRINTF (("hpet t%d interrupt triggered after "
484
+ "stopping timer\n" , n ));
485
+ if (adj_compval )
486
+ vhpet_adjust_compval (vhpet , n , now );
487
+ vhpet_timer_interrupt (vhpet , n );
488
+ }
454
489
455
- ts_set_zero (& vhpet -> timer [n ].expts );
490
+ ts_set_zero (& vhpet -> timer [n ].expts );
491
+ }
456
492
}
457
493
458
494
static void
@@ -463,8 +499,7 @@ vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter,
463
499
uint32_t delta ;
464
500
struct vhpet_timer_arg * arg ;
465
501
466
- if (vhpet_timer_running (vhpet , n ))
467
- vhpet_stop_timer (vhpet , n , now , adj_compval );
502
+ vhpet_stop_timer (vhpet , n , now , adj_compval );
468
503
469
504
DPRINTF (("hpet t%d started\n" , n ));
470
505
@@ -484,14 +519,13 @@ vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter,
484
519
vhpet_ticks_to_ts (1ULL << 32 , & ts .it_interval );
485
520
486
521
arg = vhpet_tmrarg (vhpet , n );
487
- assert (!arg -> running );
488
522
arg -> running = true;
489
523
490
524
/* Arm the new timer */
491
525
if (acrn_timer_settime_abs (vhpet_tmr (vhpet , n ), & ts ))
492
- assert (0 );
526
+ errx (EX_SOFTWARE , "acrn_timer_settime_abs returned: %s" ,
527
+ strerror (errno ));
493
528
494
- assert (ts_is_zero (& vhpet -> timer [n ].expts ));
495
529
vhpet -> timer [n ].expts = ts .it_value ;
496
530
}
497
531
@@ -514,18 +548,18 @@ vhpet_start_counting(struct vhpet *vhpet)
514
548
{
515
549
int i ;
516
550
517
- if (clock_gettime (CLOCK_REALTIME , & vhpet -> countbase_ts )) {
518
- perror ("clock_gettime failed" );
519
- assert (0 );
520
- }
551
+ if (clock_gettime (CLOCK_REALTIME , & vhpet -> countbase_ts ))
552
+ errx (EX_SOFTWARE , "clock_gettime returned: %s" , strerror (errno ));
521
553
522
554
/* Restart the timers based on the main counter base value */
523
555
for (i = 0 ; i < VHPET_NUM_TIMERS ; i ++ ) {
524
556
if (vhpet_timer_enabled (vhpet , i ))
525
557
vhpet_start_timer (vhpet , i , vhpet -> countbase ,
526
558
& vhpet -> countbase_ts , true);
527
- else
528
- assert (!vhpet_timer_running (vhpet , i ));
559
+ else if (vhpet_timer_running (vhpet , i )) {
560
+ warnx ("vhpet t%d's timer is disabled but running" , i );
561
+ vhpet_stop_timer (vhpet , i , & zero_ts .it_value , false);
562
+ }
529
563
}
530
564
}
531
565
@@ -541,8 +575,10 @@ vhpet_stop_counting(struct vhpet *vhpet, uint32_t counter,
541
575
for (i = 0 ; i < VHPET_NUM_TIMERS ; i ++ ) {
542
576
if (vhpet_timer_enabled (vhpet , i ))
543
577
vhpet_stop_timer (vhpet , i , now , true);
544
- else
545
- assert (!vhpet_timer_running (vhpet , i ));
578
+ else if (vhpet_timer_running (vhpet , i )) {
579
+ warnx ("vhpet t%d's timer is disabled but running" , i );
580
+ vhpet_stop_timer (vhpet , i , & zero_ts .it_value , false);
581
+ }
546
582
}
547
583
}
548
584
@@ -564,8 +600,14 @@ vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data,
564
600
struct timespec now ;
565
601
566
602
if (vhpet_timer_msi_enabled (vhpet , n ) ||
567
- vhpet_timer_edge_trig (vhpet , n ))
568
- assert (!(vhpet -> isr & (1 << n )));
603
+ vhpet_timer_edge_trig (vhpet , n )) {
604
+ if (vhpet -> isr & (1 << n )) {
605
+ warnx ("vhpet t%d intr asserted in %s mode" , n ,
606
+ vhpet_timer_msi_enabled (vhpet , n ) ?
607
+ "msi" : "edge-triggered" );
608
+ vhpet -> isr &= ~(1 << n );
609
+ }
610
+ }
569
611
570
612
old_pin = vhpet_timer_ioapic_pin (vhpet , n );
571
613
oldval = vhpet -> timer [n ].cap_config ;
@@ -597,10 +639,9 @@ vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data,
597
639
* - Timer remains in periodic mode
598
640
*/
599
641
if (!vhpet_timer_enabled (vhpet , n )) {
600
- if (clock_gettime (CLOCK_REALTIME , & now )) {
601
- perror ("clock_gettime failed" );
602
- assert (0 );
603
- }
642
+ if (clock_gettime (CLOCK_REALTIME , & now ))
643
+ errx (EX_SOFTWARE , "clock_gettime returned: %s" ,
644
+ strerror (errno ));
604
645
vhpet_stop_timer (vhpet , n , & now , true);
605
646
} else if (!(oldval & (HPET_TCNF_TYPE | HPET_TCNF_INT_ENB )) ||
606
647
((oldval ^ newval ) & HPET_TCNF_TYPE ))
@@ -633,8 +674,10 @@ vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data,
633
674
* not remain asserted forever.
634
675
*/
635
676
if (vhpet -> isr & (1 << n )) {
636
- assert (old_pin != 0 );
637
- if (!vhpet_timer_interrupt_enabled (vhpet , n ) ||
677
+ if (!old_pin ) {
678
+ warnx ("vhpet t%d intr asserted without a valid intr route" , n );
679
+ vhpet -> isr &= ~(1 << n );
680
+ } else if (!vhpet_timer_interrupt_enabled (vhpet , n ) ||
638
681
vhpet_timer_msi_enabled (vhpet , n ) ||
639
682
vhpet_timer_edge_trig (vhpet , n ) ||
640
683
new_pin != old_pin ) {
@@ -763,7 +806,11 @@ vhpet_mmio_write(struct vhpet *vhpet, int vcpuid, uint64_t gpa, uint64_t *wval,
763
806
HPET_TCNF_VAL_SET ) != 0 )
764
807
vhpet -> timer [i ].compval = val64 ;
765
808
} else {
766
- assert (vhpet -> timer [i ].comprate == 0 );
809
+ if (vhpet -> timer [i ].comprate ) {
810
+ warnx ("vhpet t%d's comprate is %u in non-periodic mode"
811
+ " - should be 0" , i , vhpet -> timer [i ].comprate );
812
+ vhpet -> timer [i ].comprate = 0 ;
813
+ }
767
814
val64 = vhpet -> timer [i ].compval ;
768
815
update_register (& val64 , data , mask );
769
816
vhpet -> timer [i ].compval = val64 ;
0 commit comments