[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 |