|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |