[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

 


Rackspace

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