diff mbox series

[v4,2/3] synquacer: Add secure timer interrupt framework

Message ID 1542869577-32435-2-git-send-email-sumit.garg@linaro.org
State New
Headers show
Series [v4,1/3] libtomcrypt: Import SHA512/256 approved hash algorithm | expand

Commit Message

Sumit Garg Nov. 22, 2018, 6:52 a.m. UTC
Currently there is no means to perform background housekeeping in
secure world on Synquacer platforms. Provide an (optional) periodic
timer to allow any housekeeping to be performed.

Although it could be expanded, at present the code is fairly simple
because we expect only a single PTA to exploit the timer interrupt.
The secure timer interrupt is configured to fire every 2ms.

Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

---
 core/arch/arm/include/arm64.h                  |  4 ++
 core/arch/arm/plat-synquacer/main.c            | 30 ++++++++++--
 core/arch/arm/plat-synquacer/platform_config.h |  2 +
 core/arch/arm/plat-synquacer/sub.mk            |  1 +
 core/arch/arm/plat-synquacer/timer_fiq.c       | 67 ++++++++++++++++++++++++++
 core/arch/arm/plat-synquacer/timer_fiq.h       | 13 +++++
 6 files changed, 112 insertions(+), 5 deletions(-)
 create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.c
 create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.h

-- 
2.7.4

Comments

Sumit Garg Nov. 22, 2018, 7:12 a.m. UTC | #1
Hi Daniel,

On Thu, 22 Nov 2018 at 12:23, Sumit Garg <sumit.garg@linaro.org> wrote:
>

> Currently there is no means to perform background housekeeping in

> secure world on Synquacer platforms. Provide an (optional) periodic

> timer to allow any housekeeping to be performed.

>

> Although it could be expanded, at present the code is fairly simple

> because we expect only a single PTA to exploit the timer interrupt.

> The secure timer interrupt is configured to fire every 2ms.

>

> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

> ---

>  core/arch/arm/include/arm64.h                  |  4 ++

>  core/arch/arm/plat-synquacer/main.c            | 30 ++++++++++--

>  core/arch/arm/plat-synquacer/platform_config.h |  2 +

>  core/arch/arm/plat-synquacer/sub.mk            |  1 +

>  core/arch/arm/plat-synquacer/timer_fiq.c       | 67 ++++++++++++++++++++++++++

>  core/arch/arm/plat-synquacer/timer_fiq.h       | 13 +++++

>  6 files changed, 112 insertions(+), 5 deletions(-)

>  create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.c

>  create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.h

>

> diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h

> index 2c1fd8c..0cf14c0 100644

> --- a/core/arch/arm/include/arm64.h

> +++ b/core/arch/arm/include/arm64.h

> @@ -305,6 +305,10 @@ DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)

>  DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)

>  DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)

>  DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)

> +DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)

> +DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)

> +DEFINE_REG_READ_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)

> +DEFINE_REG_WRITE_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)

>

>  DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)

>

> diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c

> index c3aac4c..714becd 100644

> --- a/core/arch/arm/plat-synquacer/main.c

> +++ b/core/arch/arm/plat-synquacer/main.c

> @@ -18,6 +18,7 @@

>  #include <sm/optee_smc.h>

>  #include <tee/entry_fast.h>

>  #include <tee/entry_std.h>

> +#include <timer_fiq.h>

>

>  static void main_fiq(void);

>

> @@ -46,7 +47,7 @@ const struct thread_handlers *generic_boot_get_handlers(void)

>

>  static void main_fiq(void)

>  {

> -       panic();

> +       gic_it_handle(&gic_data);

>  }

>

>  void console_init(void)

> @@ -66,12 +67,31 @@ void main_init_gic(void)

>         if (!gicd_base)

>                 panic();

>

> -       /* Initialize GIC */

> -       gic_init(&gic_data, 0, gicd_base);

> +       /* On ARMv8-A, GIC configuration is initialized in TF-A */

> +       gic_init_base_addr(&gic_data, 0, gicd_base);

> +

>         itr_init(&gic_data.chip);

>  }

>

> -void main_secondary_init_gic(void)

> +static enum itr_return timer_itr_cb(struct itr_handler *h __unused)

> +{

> +       /* Reset timer for next FIQ */

> +       generic_timer_handler();

> +

> +       return ITRR_HANDLED;

> +}

> +

> +static struct itr_handler timer_itr = {

> +       .it = IT_SEC_TIMER,

> +       .flags = ITRF_TRIGGER_LEVEL,

> +       .handler = timer_itr_cb,

> +};

> +

> +static TEE_Result init_timer_itr(void)

>  {

> -       gic_cpu_init(&gic_data);

> +       itr_add(&timer_itr);

> +       itr_enable(IT_SEC_TIMER);

> +

> +       return TEE_SUCCESS;

>  }

> +driver_init(init_timer_itr);

> diff --git a/core/arch/arm/plat-synquacer/platform_config.h b/core/arch/arm/plat-synquacer/platform_config.h

> index 4d6d545..f9b1b40 100644

> --- a/core/arch/arm/plat-synquacer/platform_config.h

> +++ b/core/arch/arm/plat-synquacer/platform_config.h

> @@ -19,6 +19,8 @@

>  #define CONSOLE_UART_CLK_IN_HZ         62500000

>  #define CONSOLE_BAUDRATE               115200

>

> +#define IT_SEC_TIMER                   29

> +

>  #define DRAM0_BASE                     0x80000000

>

>  /* Platform specific defines */

> diff --git a/core/arch/arm/plat-synquacer/sub.mk b/core/arch/arm/plat-synquacer/sub.mk

> index 8ddc2fd..cfa1dc3 100644

> --- a/core/arch/arm/plat-synquacer/sub.mk

> +++ b/core/arch/arm/plat-synquacer/sub.mk

> @@ -1,2 +1,3 @@

>  global-incdirs-y += .

>  srcs-y += main.c

> +srcs-y += timer_fiq.c

> diff --git a/core/arch/arm/plat-synquacer/timer_fiq.c b/core/arch/arm/plat-synquacer/timer_fiq.c

> new file mode 100644

> index 0000000..c775bb9

> --- /dev/null

> +++ b/core/arch/arm/plat-synquacer/timer_fiq.c

> @@ -0,0 +1,67 @@

> +// SPDX-License-Identifier: BSD-2-Clause

> +/*

> + * Copyright (c) 2018, Linaro Limited

> + */

> +

> +#include <arm.h>

> +#include <console.h>

> +#include <drivers/gic.h>

> +#include <io.h>

> +#include <kernel/panic.h>

> +#include <kernel/misc.h>

> +#include <kernel/spinlock.h>

> +#include <timer_fiq.h>

> +

> +static unsigned int timer_lock = SPINLOCK_UNLOCK;

> +static bool timer_fiq_running;

> +

> +void generic_timer_start(void)

> +{

> +       uint64_t cval;

> +       uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);

> +

> +       cpu_spin_lock(&timer_lock);

> +

> +       if (timer_fiq_running == true)

> +               goto exit;

> +

> +       /* The timer will fire every 2 ms */

> +       cval = read_cntpct() + (read_cntfrq() / 500);

> +       write_cntps_cval(cval);

> +

> +       /* Enable the secure physical timer */

> +       write_cntps_ctl(1);

> +

> +       timer_fiq_running = true;

> +

> +exit:

> +       cpu_spin_unlock(&timer_lock);

> +       thread_set_exceptions(exceptions);

> +}

> +

> +void generic_timer_stop(void)

> +{

> +       uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);

> +

> +       cpu_spin_lock(&timer_lock);

> +

> +       /* Disable the timer */

> +       write_cntps_ctl(0);

> +

> +       timer_fiq_running = false;

> +

> +       cpu_spin_unlock(&timer_lock);

> +       thread_set_exceptions(exceptions);

> +}

> +

> +void generic_timer_handler(void)

> +{

> +       uint64_t cval;

> +

> +       /* Ensure that the timer did assert the interrupt */

> +       assert((read_cntps_ctl() >> 2));

> +

> +       /* Reconfigure timer to fire every 2 ms */

> +       cval = read_cntpct() + (read_cntfrq() / 500);


Here I have still used cntpct value to reconfigure cntps_cval as I
tried to use cntps_cval but it leads to following situation:

At a particular point of time cntpct value becomes greater than
(cntps_cval + 2ms) due to accumulating delay leading to timer
condition always true and thereby generating interrupts without any
delay.

-Sumit

> +       write_cntps_cval(cval);

> +}

> diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> new file mode 100644

> index 0000000..4f2091a

> --- /dev/null

> +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> @@ -0,0 +1,13 @@

> +/* SPDX-License-Identifier: BSD-2-Clause */

> +/*

> + * Copyright (C) 2018, Linaro Limited

> + */

> +

> +#ifndef __TIMER_FIQ_H

> +#define __TIMER_FIQ_H

> +

> +void generic_timer_start(void);

> +void generic_timer_stop(void);

> +void generic_timer_handler(void);

> +

> +#endif /* __TIMER_FIQ_H */

> --

> 2.7.4

>
Sumit Garg Nov. 22, 2018, 8:01 a.m. UTC | #2
On Thu, 22 Nov 2018 at 12:42, Sumit Garg <sumit.garg@linaro.org> wrote:
>

> Hi Daniel,

>

> On Thu, 22 Nov 2018 at 12:23, Sumit Garg <sumit.garg@linaro.org> wrote:

> >

> > Currently there is no means to perform background housekeeping in

> > secure world on Synquacer platforms. Provide an (optional) periodic

> > timer to allow any housekeeping to be performed.

> >

> > Although it could be expanded, at present the code is fairly simple

> > because we expect only a single PTA to exploit the timer interrupt.

> > The secure timer interrupt is configured to fire every 2ms.

> >

> > Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

> > ---

> >  core/arch/arm/include/arm64.h                  |  4 ++

> >  core/arch/arm/plat-synquacer/main.c            | 30 ++++++++++--

> >  core/arch/arm/plat-synquacer/platform_config.h |  2 +

> >  core/arch/arm/plat-synquacer/sub.mk            |  1 +

> >  core/arch/arm/plat-synquacer/timer_fiq.c       | 67 ++++++++++++++++++++++++++

> >  core/arch/arm/plat-synquacer/timer_fiq.h       | 13 +++++

> >  6 files changed, 112 insertions(+), 5 deletions(-)

> >  create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.c

> >  create mode 100644 core/arch/arm/plat-synquacer/timer_fiq.h

> >

> > diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h

> > index 2c1fd8c..0cf14c0 100644

> > --- a/core/arch/arm/include/arm64.h

> > +++ b/core/arch/arm/include/arm64.h

> > @@ -305,6 +305,10 @@ DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)

> >  DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)

> >  DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)

> >  DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)

> > +DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)

> > +DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)

> > +DEFINE_REG_READ_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)

> > +DEFINE_REG_WRITE_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)

> >

> >  DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)

> >

> > diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c

> > index c3aac4c..714becd 100644

> > --- a/core/arch/arm/plat-synquacer/main.c

> > +++ b/core/arch/arm/plat-synquacer/main.c

> > @@ -18,6 +18,7 @@

> >  #include <sm/optee_smc.h>

> >  #include <tee/entry_fast.h>

> >  #include <tee/entry_std.h>

> > +#include <timer_fiq.h>

> >

> >  static void main_fiq(void);

> >

> > @@ -46,7 +47,7 @@ const struct thread_handlers *generic_boot_get_handlers(void)

> >

> >  static void main_fiq(void)

> >  {

> > -       panic();

> > +       gic_it_handle(&gic_data);

> >  }

> >

> >  void console_init(void)

> > @@ -66,12 +67,31 @@ void main_init_gic(void)

> >         if (!gicd_base)

> >                 panic();

> >

> > -       /* Initialize GIC */

> > -       gic_init(&gic_data, 0, gicd_base);

> > +       /* On ARMv8-A, GIC configuration is initialized in TF-A */

> > +       gic_init_base_addr(&gic_data, 0, gicd_base);

> > +

> >         itr_init(&gic_data.chip);

> >  }

> >

> > -void main_secondary_init_gic(void)

> > +static enum itr_return timer_itr_cb(struct itr_handler *h __unused)

> > +{

> > +       /* Reset timer for next FIQ */

> > +       generic_timer_handler();

> > +

> > +       return ITRR_HANDLED;

> > +}

> > +

> > +static struct itr_handler timer_itr = {

> > +       .it = IT_SEC_TIMER,

> > +       .flags = ITRF_TRIGGER_LEVEL,

> > +       .handler = timer_itr_cb,

> > +};

> > +

> > +static TEE_Result init_timer_itr(void)

> >  {

> > -       gic_cpu_init(&gic_data);

> > +       itr_add(&timer_itr);

> > +       itr_enable(IT_SEC_TIMER);

> > +

> > +       return TEE_SUCCESS;

> >  }

> > +driver_init(init_timer_itr);

> > diff --git a/core/arch/arm/plat-synquacer/platform_config.h b/core/arch/arm/plat-synquacer/platform_config.h

> > index 4d6d545..f9b1b40 100644

> > --- a/core/arch/arm/plat-synquacer/platform_config.h

> > +++ b/core/arch/arm/plat-synquacer/platform_config.h

> > @@ -19,6 +19,8 @@

> >  #define CONSOLE_UART_CLK_IN_HZ         62500000

> >  #define CONSOLE_BAUDRATE               115200

> >

> > +#define IT_SEC_TIMER                   29

> > +

> >  #define DRAM0_BASE                     0x80000000

> >

> >  /* Platform specific defines */

> > diff --git a/core/arch/arm/plat-synquacer/sub.mk b/core/arch/arm/plat-synquacer/sub.mk

> > index 8ddc2fd..cfa1dc3 100644

> > --- a/core/arch/arm/plat-synquacer/sub.mk

> > +++ b/core/arch/arm/plat-synquacer/sub.mk

> > @@ -1,2 +1,3 @@

> >  global-incdirs-y += .

> >  srcs-y += main.c

> > +srcs-y += timer_fiq.c

> > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.c b/core/arch/arm/plat-synquacer/timer_fiq.c

> > new file mode 100644

> > index 0000000..c775bb9

> > --- /dev/null

> > +++ b/core/arch/arm/plat-synquacer/timer_fiq.c

> > @@ -0,0 +1,67 @@

> > +// SPDX-License-Identifier: BSD-2-Clause

> > +/*

> > + * Copyright (c) 2018, Linaro Limited

> > + */

> > +

> > +#include <arm.h>

> > +#include <console.h>

> > +#include <drivers/gic.h>

> > +#include <io.h>

> > +#include <kernel/panic.h>

> > +#include <kernel/misc.h>

> > +#include <kernel/spinlock.h>

> > +#include <timer_fiq.h>

> > +

> > +static unsigned int timer_lock = SPINLOCK_UNLOCK;

> > +static bool timer_fiq_running;

> > +

> > +void generic_timer_start(void)

> > +{

> > +       uint64_t cval;

> > +       uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);

> > +

> > +       cpu_spin_lock(&timer_lock);

> > +

> > +       if (timer_fiq_running == true)

> > +               goto exit;

> > +

> > +       /* The timer will fire every 2 ms */

> > +       cval = read_cntpct() + (read_cntfrq() / 500);

> > +       write_cntps_cval(cval);

> > +

> > +       /* Enable the secure physical timer */

> > +       write_cntps_ctl(1);

> > +

> > +       timer_fiq_running = true;

> > +

> > +exit:

> > +       cpu_spin_unlock(&timer_lock);

> > +       thread_set_exceptions(exceptions);

> > +}

> > +

> > +void generic_timer_stop(void)

> > +{

> > +       uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);

> > +

> > +       cpu_spin_lock(&timer_lock);

> > +

> > +       /* Disable the timer */

> > +       write_cntps_ctl(0);

> > +

> > +       timer_fiq_running = false;

> > +

> > +       cpu_spin_unlock(&timer_lock);

> > +       thread_set_exceptions(exceptions);

> > +}

> > +

> > +void generic_timer_handler(void)

> > +{

> > +       uint64_t cval;

> > +

> > +       /* Ensure that the timer did assert the interrupt */

> > +       assert((read_cntps_ctl() >> 2));

> > +

> > +       /* Reconfigure timer to fire every 2 ms */

> > +       cval = read_cntpct() + (read_cntfrq() / 500);

>

> Here I have still used cntpct value to reconfigure cntps_cval as I

> tried to use cntps_cval but it leads to following situation:

>

> At a particular point of time cntpct value becomes greater than

> (cntps_cval + 2ms) due to accumulating delay leading to timer

> condition always true and thereby generating interrupts without any

> delay.

>


I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8
reference manual), it seems that there is another TimerValue view that
looks more appropriate for our usage than CounterValue view used in
this patch.

So I have tried to use it as follows. It works as expected.

+void generic_timer_handler(void)
+{
+       /* Ensure that the timer did assert the interrupt */
+       assert((read_cntps_ctl() >> 2));
+
+       /* Disable the timer */
+       write_cntps_ctl(0);
+
+       /* Reconfigure timer to fire every 2 ms */
+       write_cntps_tval(read_cntfrq() / 500);
+
+       /* Enable the secure physical timer */
+       write_cntps_ctl(1);
+}

Here to reconfigure the timer value, we need to disable/enable timer
as per Section D7.5.13
CNTPS_TVAL_EL1, ARMv8 reference manual.

Please share your views regarding this.

-Sumit

> -Sumit

>

> > +       write_cntps_cval(cval);

> > +}

> > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > new file mode 100644

> > index 0000000..4f2091a

> > --- /dev/null

> > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > @@ -0,0 +1,13 @@

> > +/* SPDX-License-Identifier: BSD-2-Clause */

> > +/*

> > + * Copyright (C) 2018, Linaro Limited

> > + */

> > +

> > +#ifndef __TIMER_FIQ_H

> > +#define __TIMER_FIQ_H

> > +

> > +void generic_timer_start(void);

> > +void generic_timer_stop(void);

> > +void generic_timer_handler(void);

> > +

> > +#endif /* __TIMER_FIQ_H */

> > --

> > 2.7.4

> >
Daniel Thompson Nov. 22, 2018, 11:41 a.m. UTC | #3
On Thu, Nov 22, 2018 at 01:31:38PM +0530, Sumit Garg wrote:
> > > +void generic_timer_handler(void)

> > > +{

> > > +       uint64_t cval;

> > > +

> > > +       /* Ensure that the timer did assert the interrupt */

> > > +       assert((read_cntps_ctl() >> 2));

> > > +

> > > +       /* Reconfigure timer to fire every 2 ms */

> > > +       cval = read_cntpct() + (read_cntfrq() / 500);

> >

> > Here I have still used cntpct value to reconfigure cntps_cval as I

> > tried to use cntps_cval but it leads to following situation:

> >

> > At a particular point of time cntpct value becomes greater than

> > (cntps_cval + 2ms) due to accumulating delay leading to timer

> > condition always true and thereby generating interrupts without any

> > delay.


Comments are for things that are not clear from reading the code. In
other words in general for review comments that are not obviously stupid
it is often better to reply in comments on the suprising code than
in e-mail.

> >

> 

> I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8

> reference manual), it seems that there is another TimerValue view that

> looks more appropriate for our usage than CounterValue view used in

> this patch.

> 

> So I have tried to use it as follows. It works as expected.

> 

> +void generic_timer_handler(void)

> +{

> +       /* Ensure that the timer did assert the interrupt */

> +       assert((read_cntps_ctl() >> 2));

> +

> +       /* Disable the timer */

> +       write_cntps_ctl(0);

> +

> +       /* Reconfigure timer to fire every 2 ms */


As you mentioned above... timer does not fire every 2 ms. Here we
reconfigure the time to fire 2ms from now.

> +       write_cntps_tval(read_cntfrq() / 500);

> +

> +       /* Enable the secure physical timer */

> +       write_cntps_ctl(1);

> +}

> 

> Here to reconfigure the timer value, we need to disable/enable timer

> as per Section D7.5.13

> CNTPS_TVAL_EL1, ARMv8 reference manual.

> 

> Please share your views regarding this.


Looks like TVAL and CVAL are simply alternative views of the same
counter. Agree TVAL seems more suitable.

> 

> -Sumit

> 

> > -Sumit

> >

> > > +       write_cntps_cval(cval);

> > > +}

> > > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > new file mode 100644

> > > index 0000000..4f2091a

> > > --- /dev/null

> > > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > @@ -0,0 +1,13 @@

> > > +/* SPDX-License-Identifier: BSD-2-Clause */

> > > +/*

> > > + * Copyright (C) 2018, Linaro Limited

> > > + */

> > > +

> > > +#ifndef __TIMER_FIQ_H

> > > +#define __TIMER_FIQ_H

> > > +

> > > +void generic_timer_start(void);

> > > +void generic_timer_stop(void);

> > > +void generic_timer_handler(void);

> > > +

> > > +#endif /* __TIMER_FIQ_H */

> > > --

> > > 2.7.4

> > >
Sumit Garg Nov. 22, 2018, 12:12 p.m. UTC | #4
On Thu, 22 Nov 2018 at 17:12, Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>

> On Thu, Nov 22, 2018 at 01:31:38PM +0530, Sumit Garg wrote:

> > > > +void generic_timer_handler(void)

> > > > +{

> > > > +       uint64_t cval;

> > > > +

> > > > +       /* Ensure that the timer did assert the interrupt */

> > > > +       assert((read_cntps_ctl() >> 2));

> > > > +

> > > > +       /* Reconfigure timer to fire every 2 ms */

> > > > +       cval = read_cntpct() + (read_cntfrq() / 500);

> > >

> > > Here I have still used cntpct value to reconfigure cntps_cval as I

> > > tried to use cntps_cval but it leads to following situation:

> > >

> > > At a particular point of time cntpct value becomes greater than

> > > (cntps_cval + 2ms) due to accumulating delay leading to timer

> > > condition always true and thereby generating interrupts without any

> > > delay.

>

> Comments are for things that are not clear from reading the code. In

> other words in general for review comments that are not obviously stupid

> it is often better to reply in comments on the suprising code than

> in e-mail.

>


I am afraid, if I completely understand your comment here. But it
seems that you are looking for surprising code. Below is the diff that
causes the issue:

-       cval = read_cntpct() + (read_cntfrq() / 500);
+       cval = read_cntps_cval() + (read_cntfrq() / 500);

> > >

> >

> > I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8

> > reference manual), it seems that there is another TimerValue view that

> > looks more appropriate for our usage than CounterValue view used in

> > this patch.

> >

> > So I have tried to use it as follows. It works as expected.

> >

> > +void generic_timer_handler(void)

> > +{

> > +       /* Ensure that the timer did assert the interrupt */

> > +       assert((read_cntps_ctl() >> 2));

> > +

> > +       /* Disable the timer */

> > +       write_cntps_ctl(0);

> > +

> > +       /* Reconfigure timer to fire every 2 ms */

>

> As you mentioned above... timer does not fire every 2 ms. Here we

> reconfigure the time to fire 2ms from now.


So basically you want to avoid the delay between the moment timer
interrupt is asserted and interrupt handler, correct? If yes, then it
would be so minute (maybe < 1us) to worry about in our case.

>

> > +       write_cntps_tval(read_cntfrq() / 500);

> > +

> > +       /* Enable the secure physical timer */

> > +       write_cntps_ctl(1);

> > +}

> >

> > Here to reconfigure the timer value, we need to disable/enable timer

> > as per Section D7.5.13

> > CNTPS_TVAL_EL1, ARMv8 reference manual.

> >

> > Please share your views regarding this.

>

> Looks like TVAL and CVAL are simply alternative views of the same

> counter. Agree TVAL seems more suitable.

>


Ok, will use TVAL then.

> >

> > -Sumit

> >

> > > -Sumit

> > >

> > > > +       write_cntps_cval(cval);

> > > > +}

> > > > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > new file mode 100644

> > > > index 0000000..4f2091a

> > > > --- /dev/null

> > > > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > @@ -0,0 +1,13 @@

> > > > +/* SPDX-License-Identifier: BSD-2-Clause */

> > > > +/*

> > > > + * Copyright (C) 2018, Linaro Limited

> > > > + */

> > > > +

> > > > +#ifndef __TIMER_FIQ_H

> > > > +#define __TIMER_FIQ_H

> > > > +

> > > > +void generic_timer_start(void);

> > > > +void generic_timer_stop(void);

> > > > +void generic_timer_handler(void);

> > > > +

> > > > +#endif /* __TIMER_FIQ_H */

> > > > --

> > > > 2.7.4

> > > >
Daniel Thompson Nov. 22, 2018, 12:43 p.m. UTC | #5
On Thu, Nov 22, 2018 at 05:42:06PM +0530, Sumit Garg wrote:
> On Thu, 22 Nov 2018 at 17:12, Daniel Thompson

> <daniel.thompson@linaro.org> wrote:

> >

> > On Thu, Nov 22, 2018 at 01:31:38PM +0530, Sumit Garg wrote:

> > > > > +void generic_timer_handler(void)

> > > > > +{

> > > > > +       uint64_t cval;

> > > > > +

> > > > > +       /* Ensure that the timer did assert the interrupt */

> > > > > +       assert((read_cntps_ctl() >> 2));

> > > > > +

> > > > > +       /* Reconfigure timer to fire every 2 ms */

> > > > > +       cval = read_cntpct() + (read_cntfrq() / 500);

> > > >

> > > > Here I have still used cntpct value to reconfigure cntps_cval as I

> > > > tried to use cntps_cval but it leads to following situation:

> > > >

> > > > At a particular point of time cntpct value becomes greater than

> > > > (cntps_cval + 2ms) due to accumulating delay leading to timer

> > > > condition always true and thereby generating interrupts without any

> > > > delay.

> >

> > Comments are for things that are not clear from reading the code. In

> > other words in general for review comments that are not obviously stupid

> > it is often better to reply in comments on the suprising code than

> > in e-mail.

> >

> 

> I am afraid, if I completely understand your comment here. But it

> seems that you are looking for surprising code. Below is the diff that

> causes the issue:

> 

> -       cval = read_cntpct() + (read_cntfrq() / 500);

> +       cval = read_cntps_cval() + (read_cntfrq() / 500);


I'm saying don't tell *me* in private e-mail why you have decided to
read from read_cntpct(). Tell *everyone* by putting an appropriate comment
into the code.


> 

> > > >

> > >

> > > I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8

> > > reference manual), it seems that there is another TimerValue view that

> > > looks more appropriate for our usage than CounterValue view used in

> > > this patch.

> > >

> > > So I have tried to use it as follows. It works as expected.

> > >

> > > +void generic_timer_handler(void)

> > > +{

> > > +       /* Ensure that the timer did assert the interrupt */

> > > +       assert((read_cntps_ctl() >> 2));

> > > +

> > > +       /* Disable the timer */

> > > +       write_cntps_ctl(0);

> > > +

> > > +       /* Reconfigure timer to fire every 2 ms */

> >

> > As you mentioned above... timer does not fire every 2 ms. Here we

> > reconfigure the time to fire 2ms from now.

> 

> So basically you want to avoid the delay between the moment timer

> interrupt is asserted and interrupt handler, correct? If yes, then it

> would be so minute (maybe < 1us) to worry about in our case.


I am simply saying that the comment is wrong. The code the comment applies to
does *not* "Reconfigure timer to fire every 2 ms".

In any case, you said in previous e-mail that sometimes when we rearm
the timer is has taken more than 2ms between the timer firing and the
ISR running.  In such a situation then the difference is not minute.


> > > +       write_cntps_tval(read_cntfrq() / 500);

> > > +

> > > +       /* Enable the secure physical timer */

> > > +       write_cntps_ctl(1);

> > > +}

> > >

> > > Here to reconfigure the timer value, we need to disable/enable timer

> > > as per Section D7.5.13

> > > CNTPS_TVAL_EL1, ARMv8 reference manual.

> > >

> > > Please share your views regarding this.

> >

> > Looks like TVAL and CVAL are simply alternative views of the same

> > counter. Agree TVAL seems more suitable.

> >

> 

> Ok, will use TVAL then.

> 

> > >

> > > -Sumit

> > >

> > > > -Sumit

> > > >

> > > > > +       write_cntps_cval(cval);

> > > > > +}

> > > > > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > new file mode 100644

> > > > > index 0000000..4f2091a

> > > > > --- /dev/null

> > > > > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > @@ -0,0 +1,13 @@

> > > > > +/* SPDX-License-Identifier: BSD-2-Clause */

> > > > > +/*

> > > > > + * Copyright (C) 2018, Linaro Limited

> > > > > + */

> > > > > +

> > > > > +#ifndef __TIMER_FIQ_H

> > > > > +#define __TIMER_FIQ_H

> > > > > +

> > > > > +void generic_timer_start(void);

> > > > > +void generic_timer_stop(void);

> > > > > +void generic_timer_handler(void);

> > > > > +

> > > > > +#endif /* __TIMER_FIQ_H */

> > > > > --

> > > > > 2.7.4

> > > > >
Sumit Garg Nov. 22, 2018, 1:27 p.m. UTC | #6
On Thu, 22 Nov 2018 at 18:14, Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>

> On Thu, Nov 22, 2018 at 05:42:06PM +0530, Sumit Garg wrote:

> > On Thu, 22 Nov 2018 at 17:12, Daniel Thompson

> > <daniel.thompson@linaro.org> wrote:

> > >

> > > On Thu, Nov 22, 2018 at 01:31:38PM +0530, Sumit Garg wrote:

> > > > > > +void generic_timer_handler(void)

> > > > > > +{

> > > > > > +       uint64_t cval;

> > > > > > +

> > > > > > +       /* Ensure that the timer did assert the interrupt */

> > > > > > +       assert((read_cntps_ctl() >> 2));

> > > > > > +

> > > > > > +       /* Reconfigure timer to fire every 2 ms */

> > > > > > +       cval = read_cntpct() + (read_cntfrq() / 500);

> > > > >

> > > > > Here I have still used cntpct value to reconfigure cntps_cval as I

> > > > > tried to use cntps_cval but it leads to following situation:

> > > > >

> > > > > At a particular point of time cntpct value becomes greater than

> > > > > (cntps_cval + 2ms) due to accumulating delay leading to timer

> > > > > condition always true and thereby generating interrupts without any

> > > > > delay.

> > >

> > > Comments are for things that are not clear from reading the code. In

> > > other words in general for review comments that are not obviously stupid

> > > it is often better to reply in comments on the suprising code than

> > > in e-mail.

> > >

> >

> > I am afraid, if I completely understand your comment here. But it

> > seems that you are looking for surprising code. Below is the diff that

> > causes the issue:

> >

> > -       cval = read_cntpct() + (read_cntfrq() / 500);

> > +       cval = read_cntps_cval() + (read_cntfrq() / 500);

>

> I'm saying don't tell *me* in private e-mail why you have decided to

> read from read_cntpct(). Tell *everyone* by putting an appropriate comment

> into the code.

>

>

> >

> > > > >

> > > >

> > > > I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8

> > > > reference manual), it seems that there is another TimerValue view that

> > > > looks more appropriate for our usage than CounterValue view used in

> > > > this patch.

> > > >

> > > > So I have tried to use it as follows. It works as expected.

> > > >

> > > > +void generic_timer_handler(void)

> > > > +{

> > > > +       /* Ensure that the timer did assert the interrupt */

> > > > +       assert((read_cntps_ctl() >> 2));

> > > > +

> > > > +       /* Disable the timer */

> > > > +       write_cntps_ctl(0);

> > > > +

> > > > +       /* Reconfigure timer to fire every 2 ms */

> > >

> > > As you mentioned above... timer does not fire every 2 ms. Here we

> > > reconfigure the time to fire 2ms from now.

> >

> > So basically you want to avoid the delay between the moment timer

> > interrupt is asserted and interrupt handler, correct? If yes, then it

> > would be so minute (maybe < 1us) to worry about in our case.

>

> I am simply saying that the comment is wrong. The code the comment applies to

> does *not* "Reconfigure timer to fire every 2 ms".

>


Would "Reconfigure timer to fire 2 ms from now" be appropriate?

> In any case, you said in previous e-mail that sometimes when we rearm

> the timer is has taken more than 2ms between the timer firing and the

> ISR running.  In such a situation then the difference is not minute.

>


Its an interesting scenario to debug (as prints wont be suitable to
debug this timer problem). I am not sure what is actually causing the
delay. Its an observation that heath tests starts to fail continuously
when I use cntps_cval. Will try, if I can find the root cause.

-Sumit

>

> > > > +       write_cntps_tval(read_cntfrq() / 500);

> > > > +

> > > > +       /* Enable the secure physical timer */

> > > > +       write_cntps_ctl(1);

> > > > +}

> > > >

> > > > Here to reconfigure the timer value, we need to disable/enable timer

> > > > as per Section D7.5.13

> > > > CNTPS_TVAL_EL1, ARMv8 reference manual.

> > > >

> > > > Please share your views regarding this.

> > >

> > > Looks like TVAL and CVAL are simply alternative views of the same

> > > counter. Agree TVAL seems more suitable.

> > >

> >

> > Ok, will use TVAL then.

> >

> > > >

> > > > -Sumit

> > > >

> > > > > -Sumit

> > > > >

> > > > > > +       write_cntps_cval(cval);

> > > > > > +}

> > > > > > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > > new file mode 100644

> > > > > > index 0000000..4f2091a

> > > > > > --- /dev/null

> > > > > > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > > @@ -0,0 +1,13 @@

> > > > > > +/* SPDX-License-Identifier: BSD-2-Clause */

> > > > > > +/*

> > > > > > + * Copyright (C) 2018, Linaro Limited

> > > > > > + */

> > > > > > +

> > > > > > +#ifndef __TIMER_FIQ_H

> > > > > > +#define __TIMER_FIQ_H

> > > > > > +

> > > > > > +void generic_timer_start(void);

> > > > > > +void generic_timer_stop(void);

> > > > > > +void generic_timer_handler(void);

> > > > > > +

> > > > > > +#endif /* __TIMER_FIQ_H */

> > > > > > --

> > > > > > 2.7.4

> > > > > >
Daniel Thompson Nov. 22, 2018, 4:07 p.m. UTC | #7
On Thu, Nov 22, 2018 at 06:57:40PM +0530, Sumit Garg wrote:
> On Thu, 22 Nov 2018 at 18:14, Daniel Thompson

> <daniel.thompson@linaro.org> wrote:

> >

> > On Thu, Nov 22, 2018 at 05:42:06PM +0530, Sumit Garg wrote:

> > > On Thu, 22 Nov 2018 at 17:12, Daniel Thompson

> > > <daniel.thompson@linaro.org> wrote:

> > > >

> > > > On Thu, Nov 22, 2018 at 01:31:38PM +0530, Sumit Garg wrote:

> > > > > > > +void generic_timer_handler(void)

> > > > > > > +{

> > > > > > > +       uint64_t cval;

> > > > > > > +

> > > > > > > +       /* Ensure that the timer did assert the interrupt */

> > > > > > > +       assert((read_cntps_ctl() >> 2));

> > > > > > > +

> > > > > > > +       /* Reconfigure timer to fire every 2 ms */

> > > > > > > +       cval = read_cntpct() + (read_cntfrq() / 500);

> > > > > >

> > > > > > Here I have still used cntpct value to reconfigure cntps_cval as I

> > > > > > tried to use cntps_cval but it leads to following situation:

> > > > > >

> > > > > > At a particular point of time cntpct value becomes greater than

> > > > > > (cntps_cval + 2ms) due to accumulating delay leading to timer

> > > > > > condition always true and thereby generating interrupts without any

> > > > > > delay.

> > > >

> > > > Comments are for things that are not clear from reading the code. In

> > > > other words in general for review comments that are not obviously stupid

> > > > it is often better to reply in comments on the suprising code than

> > > > in e-mail.

> > > >

> > >

> > > I am afraid, if I completely understand your comment here. But it

> > > seems that you are looking for surprising code. Below is the diff that

> > > causes the issue:

> > >

> > > -       cval = read_cntpct() + (read_cntfrq() / 500);

> > > +       cval = read_cntps_cval() + (read_cntfrq() / 500);

> >

> > I'm saying don't tell *me* in private e-mail why you have decided to

> > read from read_cntpct(). Tell *everyone* by putting an appropriate comment

> > into the code.

> >

> >

> > >

> > > > > >

> > > > >

> > > > > I did explored more about ARM timers (Section D6.1.5 Timers, ARMv8

> > > > > reference manual), it seems that there is another TimerValue view that

> > > > > looks more appropriate for our usage than CounterValue view used in

> > > > > this patch.

> > > > >

> > > > > So I have tried to use it as follows. It works as expected.

> > > > >

> > > > > +void generic_timer_handler(void)

> > > > > +{

> > > > > +       /* Ensure that the timer did assert the interrupt */

> > > > > +       assert((read_cntps_ctl() >> 2));

> > > > > +

> > > > > +       /* Disable the timer */

> > > > > +       write_cntps_ctl(0);

> > > > > +

> > > > > +       /* Reconfigure timer to fire every 2 ms */

> > > >

> > > > As you mentioned above... timer does not fire every 2 ms. Here we

> > > > reconfigure the time to fire 2ms from now.

> > >

> > > So basically you want to avoid the delay between the moment timer

> > > interrupt is asserted and interrupt handler, correct? If yes, then it

> > > would be so minute (maybe < 1us) to worry about in our case.

> >

> > I am simply saying that the comment is wrong. The code the comment applies to

> > does *not* "Reconfigure timer to fire every 2 ms".

> >

> 

> Would "Reconfigure timer to fire 2 ms from now" be appropriate?



Yes.


> 

> > In any case, you said in previous e-mail that sometimes when we rearm

> > the timer is has taken more than 2ms between the timer firing and the

> > ISR running.  In such a situation then the difference is not minute.

> >

> 

> Its an interesting scenario to debug (as prints wont be suitable to

> debug this timer problem). I am not sure what is actually causing the

> delay. Its an observation that heath tests starts to fail continuously

> when I use cntps_cval. Will try, if I can find the root cause.

> 

> -Sumit

> 

> >

> > > > > +       write_cntps_tval(read_cntfrq() / 500);

> > > > > +

> > > > > +       /* Enable the secure physical timer */

> > > > > +       write_cntps_ctl(1);

> > > > > +}

> > > > >

> > > > > Here to reconfigure the timer value, we need to disable/enable timer

> > > > > as per Section D7.5.13

> > > > > CNTPS_TVAL_EL1, ARMv8 reference manual.

> > > > >

> > > > > Please share your views regarding this.

> > > >

> > > > Looks like TVAL and CVAL are simply alternative views of the same

> > > > counter. Agree TVAL seems more suitable.

> > > >

> > >

> > > Ok, will use TVAL then.

> > >

> > > > >

> > > > > -Sumit

> > > > >

> > > > > > -Sumit

> > > > > >

> > > > > > > +       write_cntps_cval(cval);

> > > > > > > +}

> > > > > > > diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > > > new file mode 100644

> > > > > > > index 0000000..4f2091a

> > > > > > > --- /dev/null

> > > > > > > +++ b/core/arch/arm/plat-synquacer/timer_fiq.h

> > > > > > > @@ -0,0 +1,13 @@

> > > > > > > +/* SPDX-License-Identifier: BSD-2-Clause */

> > > > > > > +/*

> > > > > > > + * Copyright (C) 2018, Linaro Limited

> > > > > > > + */

> > > > > > > +

> > > > > > > +#ifndef __TIMER_FIQ_H

> > > > > > > +#define __TIMER_FIQ_H

> > > > > > > +

> > > > > > > +void generic_timer_start(void);

> > > > > > > +void generic_timer_stop(void);

> > > > > > > +void generic_timer_handler(void);

> > > > > > > +

> > > > > > > +#endif /* __TIMER_FIQ_H */

> > > > > > > --

> > > > > > > 2.7.4

> > > > > > >
diff mbox series

Patch

diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h
index 2c1fd8c..0cf14c0 100644
--- a/core/arch/arm/include/arm64.h
+++ b/core/arch/arm/include/arm64.h
@@ -305,6 +305,10 @@  DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)
 DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)
 DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)
 DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)
+DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
+DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
+DEFINE_REG_READ_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)
+DEFINE_REG_WRITE_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)
 
 DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)
 
diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c
index c3aac4c..714becd 100644
--- a/core/arch/arm/plat-synquacer/main.c
+++ b/core/arch/arm/plat-synquacer/main.c
@@ -18,6 +18,7 @@ 
 #include <sm/optee_smc.h>
 #include <tee/entry_fast.h>
 #include <tee/entry_std.h>
+#include <timer_fiq.h>
 
 static void main_fiq(void);
 
@@ -46,7 +47,7 @@  const struct thread_handlers *generic_boot_get_handlers(void)
 
 static void main_fiq(void)
 {
-	panic();
+	gic_it_handle(&gic_data);
 }
 
 void console_init(void)
@@ -66,12 +67,31 @@  void main_init_gic(void)
 	if (!gicd_base)
 		panic();
 
-	/* Initialize GIC */
-	gic_init(&gic_data, 0, gicd_base);
+	/* On ARMv8-A, GIC configuration is initialized in TF-A */
+	gic_init_base_addr(&gic_data, 0, gicd_base);
+
 	itr_init(&gic_data.chip);
 }
 
-void main_secondary_init_gic(void)
+static enum itr_return timer_itr_cb(struct itr_handler *h __unused)
+{
+	/* Reset timer for next FIQ */
+	generic_timer_handler();
+
+	return ITRR_HANDLED;
+}
+
+static struct itr_handler timer_itr = {
+	.it = IT_SEC_TIMER,
+	.flags = ITRF_TRIGGER_LEVEL,
+	.handler = timer_itr_cb,
+};
+
+static TEE_Result init_timer_itr(void)
 {
-	gic_cpu_init(&gic_data);
+	itr_add(&timer_itr);
+	itr_enable(IT_SEC_TIMER);
+
+	return TEE_SUCCESS;
 }
+driver_init(init_timer_itr);
diff --git a/core/arch/arm/plat-synquacer/platform_config.h b/core/arch/arm/plat-synquacer/platform_config.h
index 4d6d545..f9b1b40 100644
--- a/core/arch/arm/plat-synquacer/platform_config.h
+++ b/core/arch/arm/plat-synquacer/platform_config.h
@@ -19,6 +19,8 @@ 
 #define CONSOLE_UART_CLK_IN_HZ		62500000
 #define CONSOLE_BAUDRATE		115200
 
+#define IT_SEC_TIMER			29
+
 #define DRAM0_BASE			0x80000000
 
 /* Platform specific defines */
diff --git a/core/arch/arm/plat-synquacer/sub.mk b/core/arch/arm/plat-synquacer/sub.mk
index 8ddc2fd..cfa1dc3 100644
--- a/core/arch/arm/plat-synquacer/sub.mk
+++ b/core/arch/arm/plat-synquacer/sub.mk
@@ -1,2 +1,3 @@ 
 global-incdirs-y += .
 srcs-y += main.c
+srcs-y += timer_fiq.c
diff --git a/core/arch/arm/plat-synquacer/timer_fiq.c b/core/arch/arm/plat-synquacer/timer_fiq.c
new file mode 100644
index 0000000..c775bb9
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/timer_fiq.c
@@ -0,0 +1,67 @@ 
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <arm.h>
+#include <console.h>
+#include <drivers/gic.h>
+#include <io.h>
+#include <kernel/panic.h>
+#include <kernel/misc.h>
+#include <kernel/spinlock.h>
+#include <timer_fiq.h>
+
+static unsigned int timer_lock = SPINLOCK_UNLOCK;
+static bool timer_fiq_running;
+
+void generic_timer_start(void)
+{
+	uint64_t cval;
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+
+	cpu_spin_lock(&timer_lock);
+
+	if (timer_fiq_running == true)
+		goto exit;
+
+	/* The timer will fire every 2 ms */
+	cval = read_cntpct() + (read_cntfrq() / 500);
+	write_cntps_cval(cval);
+
+	/* Enable the secure physical timer */
+	write_cntps_ctl(1);
+
+	timer_fiq_running = true;
+
+exit:
+	cpu_spin_unlock(&timer_lock);
+	thread_set_exceptions(exceptions);
+}
+
+void generic_timer_stop(void)
+{
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+
+	cpu_spin_lock(&timer_lock);
+
+	/* Disable the timer */
+	write_cntps_ctl(0);
+
+	timer_fiq_running = false;
+
+	cpu_spin_unlock(&timer_lock);
+	thread_set_exceptions(exceptions);
+}
+
+void generic_timer_handler(void)
+{
+	uint64_t cval;
+
+	/* Ensure that the timer did assert the interrupt */
+	assert((read_cntps_ctl() >> 2));
+
+	/* Reconfigure timer to fire every 2 ms */
+	cval = read_cntpct() + (read_cntfrq() / 500);
+	write_cntps_cval(cval);
+}
diff --git a/core/arch/arm/plat-synquacer/timer_fiq.h b/core/arch/arm/plat-synquacer/timer_fiq.h
new file mode 100644
index 0000000..4f2091a
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/timer_fiq.h
@@ -0,0 +1,13 @@ 
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2018, Linaro Limited
+ */
+
+#ifndef __TIMER_FIQ_H
+#define __TIMER_FIQ_H
+
+void generic_timer_start(void);
+void generic_timer_stop(void);
+void generic_timer_handler(void);
+
+#endif /* __TIMER_FIQ_H */