[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH v5] plat/*: Make timer interrupt frequency selectable



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@xxxxxxxxx>
Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx>
---
 include/uk/arch/time.h            |  6 ++++--
 include/uk/plat/time.h            |  4 ++++
 plat/Config.uk                    |  8 ++++++++
 plat/kvm/x86/tscclock.c           | 29 ++++++++++++++++++-----------
 plat/linuxu/include/linuxu/time.h |  3 ++-
 plat/linuxu/time.c                |  2 --
 plat/xen/x86/arch_time.c          |  2 +-
 7 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/include/uk/arch/time.h b/include/uk/arch/time.h
index 262fd3b1..ac207887 100644
--- a/include/uk/arch/time.h
+++ b/include/uk/arch/time.h
@@ -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)
 
diff --git a/include/uk/plat/time.h b/include/uk/plat/time.h
index 202e0f99..b402ec24 100644
--- a/include/uk/plat/time.h
+++ b/include/uk/plat/time.h
@@ -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
diff --git a/plat/Config.uk b/plat/Config.uk
index b776c451..8a878eb0 100644
--- a/plat/Config.uk
+++ b/plat/Config.uk
@@ -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.
diff --git a/plat/kvm/x86/tscclock.c b/plat/kvm/x86/tscclock.c
index f3fa55a2..86db814a 100644
--- a/plat/kvm/x86/tscclock.c
+++ b/plat/kvm/x86/tscclock.c
@@ -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
@@ -84,6 +82,15 @@
 #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
diff --git a/plat/linuxu/include/linuxu/time.h 
b/plat/linuxu/include/linuxu/time.h
index 2df881ec..c1a875af 100644
--- a/plat/linuxu/include/linuxu/time.h
+++ b/plat/linuxu/include/linuxu/time.h
@@ -35,9 +35,10 @@
 #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
 
 
diff --git a/plat/linuxu/time.c b/plat/linuxu/time.c
index ead07f59..13439ad5 100644
--- a/plat/linuxu/time.c
+++ b/plat/linuxu/time.c
@@ -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;
 
 
diff --git a/plat/xen/x86/arch_time.c b/plat/xen/x86/arch_time.c
index 95d7b103..a4b77b93 100644
--- a/plat/xen/x86/arch_time.c
+++ b/plat/xen/x86/arch_time.c
@@ -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);
 }
-- 
2.20.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.