|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH 1/1] plat/common: UKTIME supported in the Raspberry Pi 3.
Hi Santiago,
It looks to me that this patch should be split into more patches (e.g.
add ukarch_{fls,flsl} for arm64, add timer support for new platform, etc).
Btw, isn't raspi a new platform actually? This would mean you should put
the platform-specific code under a new raspi/ subdir in plat/, along
with kvm/, xen/ and linuxu/.
Please see inline other comments.
On 10/18/19 3:17 PM, Santiago Pagani wrote:
> 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
Actually, we should check if CONFIG_HAVE_TIME is set (it's a new
addition). The thing is you might have some lib other than uktime
implementing the same thing, but this config flag (CONFIG_HAVE_TIME)
will always tell you that time-related functionality is enabled. You can
even create a patch only for this change.
> 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)
>
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |