[PATCH v3 1/1] riscv: Add timer_get_us() for tracing

Heinrich Schuchardt xypron.glpk at gmx.de
Wed Nov 11 14:48:08 CET 2020


On 11/11/20 12:56 PM, Pragnesh Patel wrote:
> Hi Heinrich,
>
>> -----Original Message-----
>> From: Heinrich Schuchardt <xypron.glpk at gmx.de>
>> Sent: 11 November 2020 16:51
>> To: Pragnesh Patel <pragnesh.patel at openfive.com>; u-boot at lists.denx.de
>> Cc: atish.patra at wdc.com; palmerdabbelt at google.com; bmeng.cn at gmail.com;
>> Paul Walmsley ( Sifive) <paul.walmsley at sifive.com>; anup.patel at wdc.com;
>> Sagar Kadam <sagar.kadam at openfive.com>; rick at andestech.com; Sean
>> Anderson <seanga2 at gmail.com>; Simon Glass <sjg at chromium.org>
>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>> [External Email] Do not click links or attachments unless you recognize the
>> sender and know the content is safe
>>
>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>> Add timer_get_us() which is useful for tracing.
>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>>> and For M-mode U-Boot, mtime register will provide the same.
>>>
>>> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
>>
>> The default implementation of get_timer_us() in lib/time.c calls
>> get_ticks() which calls timer_get_count(). The get_count() operation is
>> implemented in drivers/timer/andes_plmt_timer.c,
>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>
>> Why do you need special timer_get_us() implementations?
>> Isn't it enough to supply the get_count() operation in the drivers?
>
> get_ticks() is depend on gd->timer and there are 2 cases
>
> 1) if gd->timer== NULL then dm_timer_init() gets called and it will call functions
> which are not marked with "notrace" so tracing got stuck.

Thanks for the background information.

Please, identify the existing functions that lack "notrace" and fix
them. This will give us a solution for all existing boards and not for a
small selection. Furthermore it will avoid code duplication.

In lib/trace.c consider replacing
"__attribute__((no_instrument_function))" by "notrace".

Best regards

Heinrich

>
> 2) if gd->timer is already initialized then still initr_dm() will make gd->timer = NULL;
>
> initr_dm()
> {
> #ifdef CONFIG_TIMER
>          gd->timer = NULL;
> #endif
> }
>
> So again dm_timer_init() gets called and tracing got stuck.
>
> So I thought better to implement timer_get_us().
>
>>
>> Best regards
>>
>> Heinrich
>>
>>> ---
>>>
>>> Changes in v3:
>>> - Added gd->arch.plmt in global data
>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>    and sifive_clint_get_count()
>>>
>>> Changes in v2:
>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>    and andes_plmt_timer.c.
>>>
>>>
>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/riscv/include/asm/global_data.h
>>> b/arch/riscv/include/asm/global_data.h
>>> index d3a0b1d221..4e22ceb83f 100644
>>> --- a/arch/riscv/include/asm/global_data.h
>>> +++ b/arch/riscv/include/asm/global_data.h
>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>>        void __iomem *plic;     /* plic base address */
>>>   #endif
>>> +#ifdef CONFIG_ANDES_PLMT
>>> +     void __iomem *plmt;     /* plmt base address */
>>> +#endif
>>>   #if CONFIG_IS_ENABLED(SMP)
>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
>>> index cec86718c7..7c50c46d9e 100644
>>> --- a/drivers/timer/andes_plmt_timer.c
>>> +++ b/drivers/timer/andes_plmt_timer.c
>>> @@ -13,11 +13,12 @@
>>>   #include <timer.h>
>>>   #include <asm/io.h>
>>>   #include <linux/err.h>
>>> +#include <div64.h>
>>>
>>>   /* mtime register */
>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>
>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>   {
>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -26,12
>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>        .get_count = andes_plmt_get_count,  };
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>> +     if (gd->arch.plmt) {
>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>> +     }
>>> +
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>        dev->priv = dev_read_addr_ptr(dev);
>>>        if (!dev->priv)
>>>                return -EINVAL;
>>>
>>> +     gd->arch.plmt = dev->priv;
>>>        return timer_timebase_fallback(dev);  }
>>>
>>> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
>>> index 21ae184057..7fa8773da3 100644
>>> --- a/drivers/timer/riscv_timer.c
>>> +++ b/drivers/timer/riscv_timer.c
>>> @@ -15,8 +15,9 @@
>>>   #include <errno.h>
>>>   #include <timer.h>
>>>   #include <asm/csr.h>
>>> +#include <div64.h>
>>>
>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>   {
>>>        __maybe_unused u32 hi, lo;
>>>
>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>>        return ((u64)hi << 32) | lo;
>>>   }
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     ticks = riscv_timer_get_count(NULL);
>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); diff
>>> --git a/drivers/timer/sifive_clint_timer.c
>>> b/drivers/timer/sifive_clint_timer.c
>>> index 00ce0f08d6..c341f7789b 100644
>>> --- a/drivers/timer/sifive_clint_timer.c
>>> +++ b/drivers/timer/sifive_clint_timer.c
>>> @@ -10,11 +10,12 @@
>>>   #include <timer.h>
>>>   #include <asm/io.h>
>>>   #include <linux/err.h>
>>> +#include <div64.h>
>>>
>>>   /* mtime register */
>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>
>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>   {
>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -23,12
>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>        .get_count = sifive_clint_get_count,  };
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>> +     if (gd->arch.clint) {
>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>> +     }
>>> +
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>        dev->priv = dev_read_addr_ptr(dev);
>>>        if (!dev->priv)
>>>                return -EINVAL;
>>>
>>> +     gd->arch.clint = dev->priv;
>>>        return timer_timebase_fallback(dev);  }
>>>
>>>
>



More information about the U-Boot mailing list