]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/*: Make timer interrupt frequency selectable
authorFlorian Schmidt <florian.schmidt@neclab.eu>
Wed, 2 Jan 2019 15:46:24 +0000 (16:46 +0100)
committerFlorian Schmidt <florian.schmidt@neclab.eu>
Thu, 3 Jan 2019 15:33:33 +0000 (16:33 +0100)
Add new configuration options for choosing a timer interrupt frequency.
The configured frequency is converted to the timer tick length which can
be of use for other modules (e.g., preemptive schedulers).

Previously, the tick was 100 Hz on KVM and 1000 Hz on Xen. The default
value is now 100 Hz across both platforms.

Signed-off-by: Costin Lupu <costin.lupu@cs.pub.ro>
Signed-off-by: Florian Schmidt <florian.schmidt@neclab.eu>
Reviewed-by: Yuri Volchkov <yuri.volchkov@neclab.eu>
include/uk/arch/time.h
include/uk/plat/time.h
plat/Config.uk
plat/kvm/x86/tscclock.c
plat/linuxu/include/linuxu/time.h
plat/linuxu/time.c
plat/xen/x86/arch_time.c

index 262fd3b1e1000913ae4252b13c2977a5b2f19b45..ac207887481bd848cd52bbbe6c83acad4245f035 100644 (file)
@@ -57,12 +57,14 @@ typedef __s64 __snsec;
 #define __SNSEC_MAX (__S64_MAX)
 #define __SNSEC_MIN (__S64_MIN)
 
-#define ukarch_time_nsec_to_sec(ns)      ((ns) / 1000000000ULL)
+#define UKARCH_NSEC_PER_SEC 1000000000ULL
+
+#define ukarch_time_nsec_to_sec(ns)      ((ns) / UKARCH_NSEC_PER_SEC)
 #define ukarch_time_nsec_to_msec(ns)     ((ns) / 1000000ULL)
 #define ukarch_time_nsec_to_usec(ns)     ((ns) / 1000UL)
 #define ukarch_time_subsec(ns)           ((ns) % 1000000000ULL)
 
-#define ukarch_time_sec_to_nsec(sec)     ((sec)  * 1000000000UL)
+#define ukarch_time_sec_to_nsec(sec)     ((sec)  * UKARCH_NSEC_PER_SEC)
 #define ukarch_time_msec_to_nsec(msec)   ((msec) * 1000000UL)
 #define ukarch_time_usec_to_nsec(usec)   ((usec) * 1000UL)
 
index 202e0f99307fdf431e6426f3e596f676590355ea..b402ec2488cd44e8f9106d402dd1805a90384af3 100644 (file)
@@ -47,6 +47,10 @@ void ukplat_time_fini(void);
 
 __nsec ukplat_monotonic_clock(void);
 
+/* Time tick length */
+#define UKPLAT_TIME_TICK_NSEC  (UKARCH_NSEC_PER_SEC / CONFIG_HZ)
+#define UKPLAT_TIME_TICK_MSEC  ukarch_time_nsec_to_msec(UKPLAT_TIME_TICK_NSEC)
+
 #ifdef __cplusplus
 }
 #endif
index b776c45183ac1bf3116d252f74e3c6b7a93ac994..8a878eb004de810524b350bd515965e8832c3c28 100644 (file)
@@ -17,3 +17,11 @@ config EARLY_PRINT_PL011_UART_ADDR
                Pl011 serial address used by early debug console.
 
 endmenu
+
+config HZ
+       int
+       prompt "Timer frequency (Hz)"
+       default 100
+       help
+               Configure the timer interrupt frequency.
+               Only change this if you know what you're doing.
index f3fa55a2be53d045df30e42b78552c856cf3bc26..86db814a54b5d35945ee00e5f3471a4013df1dc8 100644 (file)
@@ -60,8 +60,6 @@
 #include <uk/assert.h>
 #include <uk/bitops.h>
 
-#define NSEC_PER_SEC         1000000000ULL
-
 #define TIMER_CNTR           0x40
 #define TIMER_MODE           0x43
 #define TIMER_SEL0           0x00
 #define        RTC_STATUS_A         0x0a
 #define        RTC_UIP              (1<<7)
 
+/*
+ * Compile-time check to make sure we don't tick faster than the PIT can go.
+ * This is really only a basic sanity check. We'll run into serious issues WAY
+ * earlier.
+ */
+#if TIMER_HZ / CONFIG_HZ < 1
+#error Timer tick frequency (CONFIG_HZ) cannot be higher than PIT frequency!
+#endif
+
 /* RTC wall time offset at monotonic time base. */
 static __u64 rtc_epochoffset;
 
@@ -103,11 +110,11 @@ static __u32 tsc_mult;
  *
  * Calculated as:
  *
- *     f = NSEC_PER_SEC / TIMER_HZ   (0.31) fixed point.
- *     pit_mult = 1 / f              (1.32) fixed point.
+ *     f = UKARCH_NSEC_PER_SEC / TIMER_HZ   (0.31) fixed point.
+ *     pit_mult = 1 / f                     (1.32) fixed point.
  */
 static const __u32 pit_mult =
-       (1ULL << 63) / ((NSEC_PER_SEC << 31) / TIMER_HZ);
+       (1ULL << 63) / ((UKARCH_NSEC_PER_SEC << 31) / TIMER_HZ);
 
 
 /*
@@ -131,7 +138,7 @@ static void i8254_delay(unsigned int n)
 {
        unsigned int cur_tick, initial_tick;
        int remaining;
-       const unsigned long timer_rval = TIMER_HZ / 100;
+       const unsigned long timer_rval = TIMER_HZ / CONFIG_HZ;
 
        initial_tick = i8254_gettick();
 
@@ -211,10 +218,10 @@ int tscclock_init(void)
 {
        __u64 tsc_freq, rtc_boot;
 
-       /* Initialise i8254 timer channel 0 to mode 2 at 100 Hz */
+       /* Initialise i8254 timer channel 0 to mode 2 at CONFIG_HZ frequency */
        outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
-       outb(TIMER_CNTR, (TIMER_HZ / 100) & 0xff);
-       outb(TIMER_CNTR, (TIMER_HZ / 100) >> 8);
+       outb(TIMER_CNTR, (TIMER_HZ / CONFIG_HZ) & 0xff);
+       outb(TIMER_CNTR, (TIMER_HZ / CONFIG_HZ) >> 8);
 
        /*
         * Read RTC "time at boot". This must be done just before tsc_base is
@@ -238,9 +245,9 @@ int tscclock_init(void)
        /*
         * Calculate TSC scaling multiplier.
         *
-        * (0.32) tsc_mult = NSEC_PER_SEC (32.32) / tsc_freq (32.0)
+        * (0.32) tsc_mult = UKARCH_NSEC_PER_SEC (32.32) / tsc_freq (32.0)
         */
-       tsc_mult = (NSEC_PER_SEC << 32) / tsc_freq;
+       tsc_mult = (UKARCH_NSEC_PER_SEC << 32) / tsc_freq;
 
        /*
         * Monotonic time begins at tsc_base (first read of TSC before
index 2df881ec78efb0032a050f2cd33d8f845381f830..c1a875af0ff71f713e8394ddb847ad85093583a5 100644 (file)
 #ifndef __LINUXU_TIME_H__
 #define __LINUXU_TIME_H__
 
+#include <uk/plat/time.h>
 #include <linuxu/signal.h>
 
-#define TIMER_INTVAL_MSEC    10
+#define TIMER_INTVAL_NSEC    UKPLAT_TIME_TICK_NSEC
 #define TIMER_SIGNUM         SIGALRM
 
 
index ead07f59b872a8e94427d1a88784a9d8f98901ce..13439ad5cf9f23b00caf0e5bd3acd7346a36a73a 100644 (file)
@@ -40,8 +40,6 @@
 #include <linuxu/syscall.h>
 #include <linuxu/time.h>
 
-#define TIMER_INTVAL_NSEC    ukarch_time_msec_to_nsec(TIMER_INTVAL_MSEC)
-
 static k_timer_t timerid;
 
 
index 95d7b103d09acd6c257a2945e05f96a2ba898e90..a4b77b9342dc28091a26ae0d768a5143f79f7df6 100644 (file)
@@ -233,7 +233,7 @@ void time_block_until(__snsec until)
 static void timer_handler(evtchn_port_t ev __unused,
                struct __regs *regs __unused, void *ign __unused)
 {
-       __nsec until = ukplat_monotonic_clock() + ukarch_time_msec_to_nsec(1);
+       __nsec until = ukplat_monotonic_clock() + UKPLAT_TIME_TICK_NSEC;
 
        HYPERVISOR_set_timer_op(until);
 }