Message ID | m2tf43fc5581004020918l989a9cbavc4cabd6234c6ff74@mail.gmail.com |
---|---|
State | New |
Headers | show |
2010/4/2 Blue Swirl <blauwirbel@gmail.com>: > On 4/1/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote: >> 2010/4/1 Blue Swirl <blauwirbel@gmail.com>: >> > Which list? >> >> This mailing list? >> >> >> > On 4/1/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote: >> >> and looks wrong or incomplete to me: >> >> >> >> >According to Sun4M System Architecture Manual chapter 5.3.2, a limit >> >> >of 0 will not generate interrupts. >> >> >> >> This is indeed correct, but the chapter 5.3.2 also explains why: >> >> >> >> "Setting the limit register to 0 allows the counter to free run. Since the >> >> timer always resets to a value of 500 nS after reaching maximum count, >> >> there is no match and no interrupts are generated." >> >> >> >> The part about 500 nS (0x00000200 in the counter register) and >> >> no match seems to be not addressed. >> > >> > The 500ns offset part could be addressed by making the timer period >> > shorter by 1 tick. I doubt such a change would have any visible >> > difference with QEMU, except that tick count of 0 should never appear >> > in the counter but it may now. >> >> >> as well as all the other values between 0 and 0x200. But it's less >> important I guess. >> >> >> > For the no match part, t->reached should not be set if t->limit == 0. > > I think this patch would do what is expected. Looks good and passes my tests, thanks. Redefining LIMIT_TO_PERIODS is a really nice solution.
From 7ef9679874d24f3062bf64525d9dd13d45dc2f27 Mon Sep 17 00:00:00 2001 From: Blue Swirl <blauwirbel@gmail.com> Date: Fri, 2 Apr 2010 15:54:26 +0000 Subject: [PATCH] sparc32: improve timer implementation Timer with zero period (free-run) will never match. Timer counting starts with tick value of 0x200, not from 0, so the period must calculated from one tick less than the limit. Signed-off-by: Blue Swirl <blauwirbel@gmail.com> --- hw/slavio_timer.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index ef36fe4..d787553 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -88,8 +88,8 @@ typedef struct TimerContext { #define TIMER_MAX_COUNT32 0x7ffffe00ULL #define TIMER_REACHED 0x80000000 #define TIMER_PERIOD 500ULL // 500ns -#define LIMIT_TO_PERIODS(l) ((l) >> 9) -#define PERIODS_TO_LIMIT(l) ((l) << 9) +#define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1) +#define PERIODS_TO_LIMIT(l) (((l) + 1) << 9) static int slavio_timer_is_user(TimerContext *tc) { @@ -127,7 +127,10 @@ static void slavio_timer_irq(void *opaque) slavio_timer_get_out(t); DPRINTF("callback: count %x%08x\n", t->counthigh, t->count); - t->reached = TIMER_REACHED; + /* if limit is 0 (free-run), there will be no match */ + if (t->limit != 0) { + t->reached = TIMER_REACHED; + } /* there is no interrupt if user timer or free-run */ if (!slavio_timer_is_user(tc) && t->limit != 0) { qemu_irq_raise(t->irq); -- 1.5.6.5