Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RISC-V timer incorrectly written #10609

Closed
atthecodeface opened this issue Oct 15, 2018 · 3 comments
Closed

RISC-V timer incorrectly written #10609

atthecodeface opened this issue Oct 15, 2018 · 3 comments
Assignees
Labels
bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug

Comments

@atthecodeface
Copy link

I don't know if this is handled by Andy Ross' updates to the timer stuff, so rather than it getting dropped:
riscv_machine_timer_irq_handler in drivers/timer/riscv_machine_timer.c
is presumably the interrupt handler for the timer. Its process is to do its stuff then rearm the timer.

The RISC-V privileged spec does not guarantee spurious timer interrupts on timer rearming; there is a chance that a timer interrupt will occur after the timer is armed again, immediately as the loop delay from write-time-comparator to interrupt-disable is arbitrarily long (there was a mail thread on this on RISC-V ISA dev a couple of months back). Hence the code as is can continuously loop, and certainly have system clock ticks occur far more frequently than they should.

Also, the mechanism for writing the timer comparator does not match the spec: it writes val_low then val_high. The 'correct' approach is to set val_high to 0xffffffff, then write val_low, then write val_high; this is in figure 3.15 of the RISC-V privileged ISA specification (although I think there isa bug in that code too as the first write ought to be to timecmp+4, not timecmp, and this has also been noted on the mailing list)

Finally the spec does not actually indicate that a timer value should be low-then-hig, ii.e. matching the structure:

typedef struct {
u32_t val_low;
u32_t val_high;
} riscv_machine_timer_t;

The spec actually has no requirement of little or big endianness here. I regard it as a bug in the spec, not the code, though.

@nashif nashif added the bug The issue is a bug, or the PR is fixing a bug label Oct 16, 2018
@andyross
Copy link
Contributor

Cool, thanks. I was literally just this morning starting the rework on this driver, and indeed had copied that "low then high" mechanism (and even added a comment explaining it) verbatim. That kind of latching is a pretty common trick for multi-word counters, so it didn't look weird to me.

What is the correct reference for this device? The only docs I could find publicly were the SiFive manual for the SiFive E310. And I suppose I could check the qemu source...

As far as the spurious interrupt problem: that should be handled. The ISR (you can see similar logic in the HPET and -- though it's hairy there -- SysTick drivers) checks the current time vs. last and announces ticks for true expired time and not just a count of interrupts.

@nategraff-sifive
Copy link
Contributor

@andyross The Freedom E310-G000 Manual and the RISC-V Privileged Architecture Specification are the references I use for the machine timer. You can also check out the Freedom U540-C000 Manual which has its own implementation of the RISC-V machine timer.

I should also mention I've been working on getting your Xtensa SMP support ported to RISC-V, so as long as we're talking about the machine timer driver another change the driver needs is to be aware of which hart's timer it's rearming.

That has its own share of specification vagaries, though, because the hart IDs need not be contiguously assigned, but it really sucks to support if they're not. So far I've been working on the assumption that they are contiguous and that the hart ID can function as an index to an array of mtimecmp values, which has been enough to get things running on QEMU.

@nashif nashif added the priority: medium Medium impact/importance bug label Oct 18, 2018
@andyross
Copy link
Contributor

Driver that should address this up at #10556

andyross pushed a commit to andyross/zephyr that referenced this issue Nov 9, 2018
Rewritten driver along the lines of all the other new drivers,
implementing the new timer API.  Structurally, the machine timer is an
up-counter with comparator, so it works broadly the same way HPET and
NRF do.  The quirk here is that it's a 64 bit counter, which needs a
little more care.

Unlike the other timer reworks, this driver has grown by a few lines
as it used to be very simple.  But in exchange, we get full tickless
support on the platform.

Fixes zephyrproject-rtos#10609 in the process (the 64 bit timer registers are unlatched
for sub-word transfers, so you have to use careful ordering).

Signed-off-by: Andy Ross <[email protected]>
andyross pushed a commit to andyross/zephyr that referenced this issue Nov 13, 2018
Rewritten driver along the lines of all the other new drivers,
implementing the new timer API.  Structurally, the machine timer is an
up-counter with comparator, so it works broadly the same way HPET and
NRF do.  The quirk here is that it's a 64 bit counter, which needs a
little more care.

Unlike the other timer reworks, this driver has grown by a few lines
as it used to be very simple.  But in exchange, we get full tickless
support on the platform.

Fixes zephyrproject-rtos#10609 in the process (the 64 bit timer registers are unlatched
for sub-word transfers, so you have to use careful ordering).

Signed-off-by: Andy Ross <[email protected]>
@nashif nashif closed this as completed in f04f797 Nov 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug The issue is a bug, or the PR is fixing a bug priority: medium Medium impact/importance bug
Projects
None yet
Development

No branches or pull requests

4 participants