Hi,

Is it bad if the olatch counts up if the host's wall clock
is set backward?  Or if the olatch makes a big jump for
the same reason?

Serious question: I don't have any EPT hardware to test
this (sorry).

While here, it looks like we can (a) roll the olatch-writing
parts of i8253_do_readback into a loop, and (b) use the
timespecsub macro from sys/time.h, to make the code briefer.

Anyone down to test?

--
Scott Cheloha

Index: usr.sbin/vmd/i8253.c
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/i8253.c,v
retrieving revision 1.17
diff -u -p -r1.17 i8253.c
--- usr.sbin/vmd/i8253.c        14 Aug 2017 19:46:44 -0000      1.17
+++ usr.sbin/vmd/i8253.c        18 Feb 2018 17:53:48 -0000
@@ -25,6 +25,7 @@
 #include <event.h>
 #include <string.h>
 #include <stddef.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "i8253.h"
@@ -53,7 +54,7 @@ void
 i8253_init(uint32_t vm_id)
 {
        memset(&i8253_channel, 0, sizeof(struct i8253_channel));
-       gettimeofday(&i8253_channel[0].tv, NULL);
+       clock_gettime(CLOCK_MONOTONIC, &i8253_channel[0].ts);
        i8253_channel[0].start = 0xFFFF;
        i8253_channel[0].mode = TIMER_INTTC;
        i8253_channel[0].last_r = 1;
@@ -86,8 +87,10 @@ i8253_init(uint32_t vm_id)
 void
 i8253_do_readback(uint32_t data)
 {
-       struct timeval now, delta;
+       struct timespec now, delta;
        uint64_t ns, ticks;
+       int readback_channel[3] = { TIMER_RB_C0, TIMER_RB_C1, TIMER_RB_C2 };
+       int i;
 
        /* bits are inverted here - !TIMER_RB_STATUS == enable chan readback */
        if (data & ~TIMER_RB_STATUS) {
@@ -98,73 +101,19 @@ i8253_do_readback(uint32_t data)
 
        /* !TIMER_RB_COUNT == enable counter readback */
        if (data & ~TIMER_RB_COUNT) {
-               if (data & TIMER_RB_C0) {
-                       gettimeofday(&now, NULL);
-                       delta.tv_sec = now.tv_sec - i8253_channel[0].tv.tv_sec;
-                       delta.tv_usec = now.tv_usec -
-                           i8253_channel[0].tv.tv_usec;
-                       if (delta.tv_usec < 0) {
-                               delta.tv_sec--;
-                               delta.tv_usec += 1000000;
+               for (i = 0; i < 3; i++) {
+                       if (data & readback_channel[i]) {
+                               clock_gettime(CLOCK_MONOTONIC, &now);
+                               timespecsub(&now, &i8253_channel[i].ts, &delta);
+                               ns = delta.tv_sec * 1000000000 + delta.tv_nsec;
+                               ticks = ns / NS_PER_TICK;
+                               if (i8253_channel[i].start)
+                                       i8253_channel[i].olatch =
+                                           i8253_channel[i].start -
+                                           ticks % i8253_channel[i].start;
+                               else
+                                       i8253_channel[i].olatch = 0;
                        }
-                       if (delta.tv_usec > 1000000) {
-                               delta.tv_sec++;
-                               delta.tv_usec -= 1000000;
-                       }
-                       ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
-                       ticks = ns / NS_PER_TICK;
-                       if (i8253_channel[0].start)
-                               i8253_channel[0].olatch =
-                                   i8253_channel[0].start -
-                                   ticks % i8253_channel[0].start;
-                       else
-                               i8253_channel[0].olatch = 0;
-               }
-
-               if (data & TIMER_RB_C1) {
-                       gettimeofday(&now, NULL);
-                       delta.tv_sec = now.tv_sec - i8253_channel[1].tv.tv_sec;
-                       delta.tv_usec = now.tv_usec -
-                           i8253_channel[1].tv.tv_usec;
-                       if (delta.tv_usec < 0) {
-                               delta.tv_sec--;
-                               delta.tv_usec += 1000000;
-                       }
-                       if (delta.tv_usec > 1000000) {
-                               delta.tv_sec++;
-                               delta.tv_usec -= 1000000;
-                       }
-                       ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
-                       ticks = ns / NS_PER_TICK;
-                       if (i8253_channel[1].start)
-                               i8253_channel[1].olatch =
-                                   i8253_channel[1].start -
-                                   ticks % i8253_channel[1].start;
-                       else
-                               i8253_channel[1].olatch = 0;
-               }
-
-               if (data & TIMER_RB_C2) {
-                       gettimeofday(&now, NULL);
-                       delta.tv_sec = now.tv_sec - i8253_channel[2].tv.tv_sec;
-                       delta.tv_usec = now.tv_usec -
-                           i8253_channel[2].tv.tv_usec;
-                       if (delta.tv_usec < 0) {
-                               delta.tv_sec--;
-                               delta.tv_usec += 1000000;
-                       }
-                       if (delta.tv_usec > 1000000) {
-                               delta.tv_sec++;
-                               delta.tv_usec -= 1000000;
-                       }
-                       ns = delta.tv_usec * 1000 + delta.tv_sec * 1000000000;
-                       ticks = ns / NS_PER_TICK;
-                       if (i8253_channel[2].start)
-                               i8253_channel[2].olatch =
-                                   i8253_channel[2].start -
-                                   ticks % i8253_channel[2].start;
-                       else
-                               i8253_channel[2].olatch = 0;
                }
        }
 }
@@ -188,7 +137,7 @@ vcpu_exit_i8253(struct vm_run_params *vr
        uint32_t out_data;
        uint8_t sel, rw, data, mode;
        uint64_t ns, ticks;
-       struct timeval now, delta;
+       struct timespec now, delta;
        union vm_exit *vei = vrp->vrp_exit;
 
        get_input_data(vei, &out_data);
@@ -216,21 +165,9 @@ vcpu_exit_i8253(struct vm_run_params *vr
                         * rate.
                         */
                        if (rw == TIMER_LATCH) {
-                               gettimeofday(&now, NULL);
-                               delta.tv_sec = now.tv_sec -
-                                   i8253_channel[sel].tv.tv_sec;
-                               delta.tv_usec = now.tv_usec -
-                                   i8253_channel[sel].tv.tv_usec;
-                               if (delta.tv_usec < 0) {
-                                       delta.tv_sec--;
-                                       delta.tv_usec += 1000000;
-                               }
-                               if (delta.tv_usec > 1000000) {
-                                       delta.tv_sec++;
-                                       delta.tv_usec -= 1000000;
-                               }
-                               ns = delta.tv_usec * 1000 +
-                                   delta.tv_sec * 1000000000;
+                               clock_gettime(CLOCK_MONOTONIC, &now);
+                               timespecsub(&now, &i8253_channel[sel].ts, 
&delta);
+                               ns = delta.tv_sec * 1000000000 + delta.tv_nsec;
                                ticks = ns / NS_PER_TICK;
                                if (i8253_channel[sel].start) {
                                        i8253_channel[sel].olatch =
Index: usr.sbin/vmd/i8253.h
===================================================================
RCS file: /cvs/src/usr.sbin/vmd/i8253.h,v
retrieving revision 1.7
diff -u -p -r1.7 i8253.h
--- usr.sbin/vmd/i8253.h        9 Jul 2017 00:51:40 -0000       1.7
+++ usr.sbin/vmd/i8253.h        18 Feb 2018 17:53:48 -0000
@@ -29,7 +29,7 @@
 
 /* i8253 registers */
 struct i8253_channel {
-       struct timeval tv;      /* timer start time */
+       struct timespec ts;     /* timer start time */
        uint16_t start;         /* starting value */
        uint16_t olatch;        /* output latch */
        uint16_t ilatch;        /* input latch */

Reply via email to