This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ARMv8-A Cortex-A72: Generic timer is backoff

We encounter an issue about ARM generic timer back-off.

Test sequence:

  1. A72 Core0 is reading the system counter from CNTPCT in real time, and assign the read value to a global variable “core0_ticks.
  2. A72 Core1/2/3 read the global variable “core0_ticks and assign to a temporary variable tmp_ticks, then they read the system counter from CNTPCT and assign to another temporary variable corex_ticks.
  3. Comparing “tmp_ticks and corex_ticks, and then, as shown below, we found in surprise, sometimes, corex_ticks < tmp_ticks, it only has some time gap of several ticks.

Pseudo-code:

Core0

Core1/2/3

While(1) {

    1. dsb

    2. core0_ticks = read timer counter(CNTPCT)

}

While (1) {

    1. dsb

    2. tmp_tcicks = core0_ticks

    3. dsb

    4. corex_ticks = read timer counterCNTPCT)

    5. if (corex_ticks < tmp_ticks), then return error
}

Error message:

core1_ticks[28b9d8f7] < core0_ticks[28b9d8f8]

core3_ticks[28b9dc58] < core0_ticks[28b9dc59]

core1_ticks[28bb6a38] < core0_ticks[28bb6a3b]

core3_ticks[28bcf400] < core0_ticks[28bcf401]

core1_ticks[28be89bd] < core0_ticks[28be89c0]

core3_ticks[28c01b51] < core0_ticks[28c01b54]

Questions:

Is this a common issue about ARM generic timer counter?

Or could you give some advice about the integration for ARM generic timer?

Or We have to do some additional configuration for ARM generic timer??

PS:

We also found that in Linux Kernel and U-boot, this issue existed in some other SoC, too. The following patch is from LS1043A form NXP and Hikey960 from Hisilicon.

/*

* FSL erratum A-008585 says that the ARM generic timer counter "has the

* potential to contain an erroneous value for a small number of core

* clock cycles every time the timer value changes".

* This sometimes leads to a consecutive counter read returning a lower

* value than the previous one, thus reporting the time to go backwards.

* The workaround is to read the counter twice and only return when the value

* was the same in both reads.

* Assumes that the CPU runs in much higher frequency than the timer.

*/

Erratum Hisilicon-161010101 says that the ARM generic timer counter "has

the potential to contain an erroneous value when the timer value

changes". Accesses to TVAL (both read and write) are also affected due

to the implicit counter read. Accesses to CVAL are not affected.

 

The workaround is to reread the system count registers until the value

of the second read is larger than the first one by less than 32, the

system counter can be guaranteed not to return wrong value twice by

back-to-back read and the error value is always larger than the correct

one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.

  • Based on your original description, you hope Core-0 to read core0_ticks first. After core0_ticks is read, Core-1/2/3 can start their operations.

    But it seems that your core-1/2/3 has no dependency for Core-0 core0_ticks result.  

    How about this test pseudo code ( if I understand your expectation correctly):

    flag =  -1

    Core-0:

    While(1) {

         if flag == 1

                  core0_ticks = read timer counter(CNTPCT)

                 flag = 0

                  dsb   // add this dsb

        else
              wait

    }

    While (1) {

         if flag == 0

                tmp_tcicks = core0_ticks

                flag = 1

                dsb

                corex_ticks = read timer counterCNTPCT)

                dsb

                if (corex_ticks < tmp_ticks), then return error

        else:

            wait
    }