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

[Minios-devel] [UNIKRAFT PATCH 1/1] plat/common: UKTIME supported in the Raspberry Pi 3.



Added and guarded Raspberry Pi 3's SoC specific
things related to the ARM generic timer in order
to support UKTIME.

Signed-off-by: Santiago Pagani <santiago.pagani@xxxxxxxxx>
---
 arch/arm/arm64/include/uk/asm/atomic.h |  53 ++++++++++
 lib/nolibc/include/unistd.h            |   2 +
 plat/common/arm/time.c                 | 134 ++++++++++++++++---------
 3 files changed, 143 insertions(+), 46 deletions(-)

diff --git a/arch/arm/arm64/include/uk/asm/atomic.h 
b/arch/arm/arm64/include/uk/asm/atomic.h
index 7ee66677..98b5ed2b 100644
--- a/arch/arm/arm64/include/uk/asm/atomic.h
+++ b/arch/arm/arm64/include/uk/asm/atomic.h
@@ -6,6 +6,7 @@
  * Authors: Karim Allah Ahmed <karim.allah.ahmed@xxxxxxxxx>
  *          Thomas Leonard <talex5@xxxxxxxxx>
  *          Wei Chen <Wei.Chen@xxxxxxx>
+ *          Santiago Pagani <santiago.pagani@xxxxxxxxx
  *
  * Copyright (c) 2014 Karim Allah Ahmed
  * Copyright (c) 2014 Thomas Leonard
@@ -37,6 +38,32 @@
 #error Do not include this header directly
 #endif
 
+/**
+ * ukarch_fls - find last (highest) set bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned int ukarch_fls(unsigned int word)
+{
+       int clz;
+
+       /* 000001xxxx = word
+        *      4     = 63 - clz(word)
+        */
+
+       __asm__("clz %[clz], %[word]\n"
+               :
+               /* Outputs: */
+               [clz] "=r"(clz)
+               :
+               /* Inputs: */
+               [word] "r"(word)
+               );
+
+       return 63 - clz;
+}
+
 /**
  * ukarch_ffsl - find first (lowest) set bit in word.
  * @word: The word to search
@@ -68,3 +95,29 @@ static inline unsigned long ukarch_ffsl(unsigned long word)
 
        return 63 - clz;
 }
+
+/**
+ * ukarch_flsl - find last (highest) set bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long ukarch_flsl(unsigned long word)
+{
+       int clz;
+
+       /* 000001xxxx = word
+        *      4     = 63 - clz(word)
+        */
+
+       __asm__("clz %[clz], %[word]\n"
+               :
+               /* Outputs: */
+               [clz] "=r"(clz)
+               :
+               /* Inputs: */
+               [word] "r"(word)
+               );
+
+       return 63 - clz;
+}
diff --git a/lib/nolibc/include/unistd.h b/lib/nolibc/include/unistd.h
index a6986873..263a9f49 100644
--- a/lib/nolibc/include/unistd.h
+++ b/lib/nolibc/include/unistd.h
@@ -55,7 +55,9 @@ extern "C" {
 
 #include <nolibc-internal/shareddefs.h>
 
+#if CONFIG_LIBUKTIME
 unsigned int sleep(unsigned int seconds);
+#endif
 
 #if CONFIG_LIBVFSCORE
 int close(int fd);
diff --git a/plat/common/arm/time.c b/plat/common/arm/time.c
index 56d9d6e1..3ed33e8d 100644
--- a/plat/common/arm/time.c
+++ b/plat/common/arm/time.c
@@ -32,8 +32,10 @@
  * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
  */
 #include <stdlib.h>
-#include <libfdt.h>
-#include <ofw/fdt.h>
+#if !CONFIG_PLAT_RASPI
+       #include <libfdt.h>
+       #include <ofw/fdt.h>
+#endif
 #include <uk/assert.h>
 #include <uk/plat/time.h>
 #include <uk/plat/lcpu.h>
@@ -44,17 +46,25 @@
 #include <irq.h>
 #include <gic/gic-v2.h>
 #include <arm/time.h>
+#if CONFIG_PLAT_RASPI
+       #include <raspi/time.h>
+       #include <raspi/irq.h>
+#endif
 
 /* TODO: For now this file is KVM dependent. As soon as we have more
  * Arm platforms that are using this file, we need to introduce a
  * portable way to handover the DTB entry point to common platform code */
-#include <kvm/config.h>
+#if CONFIG_PLAT_KVM
+       #include <kvm/config.h>
+#endif
 
-static const char * const arch_timer_list[] = {
-       "arm,armv8-timer",
-       "arm,armv7-timer",
-       NULL
-};
+#if !CONFIG_PLAT_RASPI
+       static const char * const arch_timer_list[] = {
+               "arm,armv8-timer",
+               "arm,armv7-timer",
+               NULL
+       };
+#endif
 
 static uint64_t boot_ticks;
 static uint32_t counter_freq;
@@ -163,6 +173,9 @@ static inline void generic_timer_disable(void)
 static inline void generic_timer_mask_irq(void)
 {
        set_el0(cntv_ctl, get_el0(cntv_ctl) | GT_TIMER_MASK_IRQ);
+       #if CONFIG_PLAT_RASPI
+               *RASPI_ARM_C0_TIMER_IRQ_CTL = *RASPI_ARM_C0_TIMER_IRQ_CTL & ~(1 
<< 3);
+       #endif
 
        /* Ensure the write of sys register is visible */
        isb();
@@ -171,7 +184,18 @@ static inline void generic_timer_mask_irq(void)
 static inline void generic_timer_unmask_irq(void)
 {
        set_el0(cntv_ctl, get_el0(cntv_ctl) & ~GT_TIMER_MASK_IRQ);
+       #if CONFIG_PLAT_RASPI
+               *RASPI_ARM_C0_TIMER_IRQ_CTL = *RASPI_ARM_C0_TIMER_IRQ_CTL | (1 
<< 3);
+       #endif
+
+       /* Ensure the write of sys register is visible */
+       isb();
+}
 
+static inline void generic_timer_clear_irq(void)
+{
+       set_el0(cntv_ctl, get_el0(cntv_ctl) & ~GT_TIMER_IRQ_STATUS);
+       
        /* Ensure the write of sys register is visible */
        isb();
 }
@@ -209,27 +233,34 @@ static inline uint64_t generic_timer_get_ticks(void)
 }
 #endif
 
-static uint32_t generic_timer_get_frequency(int fdt_timer)
-{
-       int len;
-       const uint64_t *fdt_freq;
-
-       /*
-        * On a few platforms the frequency is not configured correctly
-        * by the firmware. A property in the DT (clock-frequency) has
-        * been introduced to workaround those firmware.
-        */
-       fdt_freq = fdt_getprop(_libkvmplat_cfg.dtb,
-                       fdt_timer, "clock-frequency", &len);
-       if (!fdt_freq || (len <= 0)) {
-               uk_pr_info("No clock-frequency found, reading from register 
directly.\n");
-
-               /* No workaround, get from register directly */
+#if CONFIG_PLAT_RASPI
+       static uint32_t generic_timer_get_frequency(int fdt_timer __unused)
+       {
                return get_el0(cntfrq);
        }
-
-       return fdt32_to_cpu(fdt_freq[0]);
-}
+#else
+       static uint32_t generic_timer_get_frequency(int fdt_timer)
+       {
+               int len;
+               const uint64_t *fdt_freq;
+
+               /*
+               * On a few platforms the frequency is not configured correctly
+               * by the firmware. A property in the DT (clock-frequency) has
+               * been introduced to workaround those firmware.
+               */
+               fdt_freq = fdt_getprop(_libkvmplat_cfg.dtb,
+                               fdt_timer, "clock-frequency", &len);
+               if (!fdt_freq || (len <= 0)) {
+                       uk_pr_info("No clock-frequency found, reading from 
register directly.\n");
+
+                       /* No workaround, get from register directly */
+                       return get_el0(cntfrq);
+               }
+
+               return fdt32_to_cpu(fdt_freq[0]);
+       }
+#endif
 
 /*
  * monotonic_clock(): returns # of nanoseconds passed since
@@ -263,8 +294,6 @@ static void generic_timer_cpu_block_until(uint64_t until_ns)
 {
        uint64_t now_ns, until_ticks;
 
-       UK_ASSERT(ukplat_lcpu_irqs_disabled());
-
        /* Record current ns and until_ticks for timer */
        now_ns = ukplat_monotonic_clock();
        until_ticks = generic_timer_get_ticks()
@@ -322,6 +351,7 @@ static int generic_timer_irq_handler(void *arg __unused)
         * generic_timer_cpu_block_until, and then unmask the IRQ.
         */
        generic_timer_mask_irq();
+       generic_timer_clear_irq();
 
        /* Yes, we handled the irq. */
        return 1;
@@ -333,8 +363,10 @@ void time_block_until(__snsec until)
 {
        while ((__snsec) ukplat_monotonic_clock() < until) {
                generic_timer_cpu_block_until(until);
-               if (__uk_test_and_clear_bit(0, &sched_have_pending_events))
-                       break;
+               #if !CONFIG_PLAT_RASPI
+                       if (__uk_test_and_clear_bit(0, 
&sched_have_pending_events))
+                               break;
+               #endif
        }
 }
 
@@ -354,8 +386,10 @@ __nsec ukplat_wall_clock(void)
 void ukplat_time_init(void)
 {
        int rc, irq, fdt_timer;
-       uint32_t irq_type, hwirq;
-       uint32_t trigger_type;
+       #if !CONFIG_PLAT_RASPI
+               uint32_t irq_type, hwirq;
+               uint32_t trigger_type;
+       #endif
 
        /*
         * Monotonic time begins at boot_ticks (first read of counter
@@ -364,24 +398,32 @@ void ukplat_time_init(void)
        boot_ticks = generic_timer_get_ticks();
 
        /* Currently, we only support 1 timer per system */
-       fdt_timer = fdt_node_offset_by_compatible_list(_libkvmplat_cfg.dtb,
-                               -1, arch_timer_list);
-       if (fdt_timer < 0)
-               UK_CRASH("Could not find arch timer!\n");
+       #if CONFIG_PLAT_RASPI
+               fdt_timer = 0;
+       #else
+               fdt_timer = 
fdt_node_offset_by_compatible_list(_libkvmplat_cfg.dtb,
+                                       -1, arch_timer_list);
+               if (fdt_timer < 0)
+                       UK_CRASH("Could not find arch timer!\n");
+       #endif
 
        rc = generic_timer_init(fdt_timer);
        if (rc < 0)
                UK_CRASH("Failed to initialize platform time\n");
 
-       rc = gic_get_irq_from_dtb(_libkvmplat_cfg.dtb, fdt_timer, 2,
-                       &irq_type, &hwirq, &trigger_type);
-       if (rc < 0)
-               UK_CRASH("Failed to find IRQ number from DTB\n");
-
-       irq = gic_irq_translate(irq_type, hwirq);
-       if (irq < 0 || irq >= __MAX_IRQ)
-               UK_CRASH("Failed to translate IRQ number, type=%u, hwirq=%u\n",
-                       irq_type, hwirq);
+       #if CONFIG_PLAT_RASPI
+               irq = IRQ_ID_ARM_GENERIC_TIMER;
+       #else
+               rc = gic_get_irq_from_dtb(_libkvmplat_cfg.dtb, fdt_timer, 2,
+                               &irq_type, &hwirq, &trigger_type);
+               if (rc < 0)
+                       UK_CRASH("Failed to find IRQ number from DTB\n");
+
+               irq = gic_irq_translate(irq_type, hwirq);
+               if (irq < 0 || irq >= __MAX_IRQ)
+                       UK_CRASH("Failed to translate IRQ number, type=%u, 
hwirq=%u\n",
+                               irq_type, hwirq);
+       #endif
 
        rc = ukplat_irq_register(irq, generic_timer_irq_handler, NULL);
        if (rc < 0)
-- 
2.17.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®.