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

Heinrich Schuchardt xypron.glpk at gmx.de
Thu Nov 12 08:09:38 CET 2020


On 11/12/20 7:34 AM, Pragnesh Patel wrote:
> Hi Heinrich,
>
>> -----Original Message-----
>> From: Heinrich Schuchardt <xypron.glpk at gmx.de>
>> Sent: 11 November 2020 19:18
>> To: Pragnesh Patel <pragnesh.patel at openfive.com>
>> Cc: atish.patra at wdc.com; palmerdabbelt at google.com; u-boot at lists.denx.de;
>> 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 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.
>
> I tried but There are so many functions which need "notrace".

Let's start with the problem statement:

When tracing functions is enabled this adds calls to
__cyg_profile_func_enter() and __cyg_profile_func_exit() to the traced
functions.

__cyg_profile_func_exit() and __cyg_profile_func_exit() invoke
timer_get_us() to record the entry and exit time.

If timer_get_us() or any function used to implement does not carry
__attribute__((no_instrument_function)) this will lead to an indefinite
recursion.

We have to change __cyg_profile_func_enter() and
__cyg_profile_func_exit() such that during their execution no function
is traced. We can do so by temporarily setting trace_enabled to false.

Does this match your observation?

Best regards

Heinrich

>
> Why don’t we consider removing gd->timer=NULL in initr_dm()
> initr_dm()
> {
> #ifdef CONFIG_TIMER
>          gd->timer = NULL;
> #endif
> }
>
> Or I can use TIMER_EARLY and return ticks and rate  by adding timer_early_get_count()
> and timer_early_get_rate() repectively.
>
> Suggestions are welcome
>
>>
>> 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