User timer limit fixes (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3931 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
40a2e657a5
commit
e1cb950242
|
@ -122,10 +122,9 @@ static void slavio_timer_irq(void *opaque)
|
||||||
|
|
||||||
slavio_timer_get_out(s);
|
slavio_timer_get_out(s);
|
||||||
DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
|
DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
|
||||||
if (!slavio_timer_is_user(s)) {
|
|
||||||
s->reached = TIMER_REACHED;
|
s->reached = TIMER_REACHED;
|
||||||
|
if (!slavio_timer_is_user(s))
|
||||||
qemu_irq_raise(s->irq);
|
qemu_irq_raise(s->irq);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
|
@ -141,7 +140,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
if (slavio_timer_is_user(s)) {
|
if (slavio_timer_is_user(s)) {
|
||||||
// read user timer MSW
|
// read user timer MSW
|
||||||
slavio_timer_get_out(s);
|
slavio_timer_get_out(s);
|
||||||
ret = s->counthigh;
|
ret = s->counthigh | s->reached;
|
||||||
} else {
|
} else {
|
||||||
// read limit
|
// read limit
|
||||||
// clear irq
|
// clear irq
|
||||||
|
@ -155,7 +154,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
// of counter (user mode)
|
// of counter (user mode)
|
||||||
slavio_timer_get_out(s);
|
slavio_timer_get_out(s);
|
||||||
if (slavio_timer_is_user(s)) // read user timer LSW
|
if (slavio_timer_is_user(s)) // read user timer LSW
|
||||||
ret = s->count & TIMER_COUNT_MASK32;
|
ret = s->count & TIMER_MAX_COUNT64;
|
||||||
else // read limit
|
else // read limit
|
||||||
ret = (s->count & TIMER_MAX_COUNT32) | s->reached;
|
ret = (s->count & TIMER_MAX_COUNT32) | s->reached;
|
||||||
break;
|
break;
|
||||||
|
@ -190,12 +189,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
case TIMER_LIMIT:
|
case TIMER_LIMIT:
|
||||||
if (slavio_timer_is_user(s)) {
|
if (slavio_timer_is_user(s)) {
|
||||||
|
uint64_t count;
|
||||||
|
|
||||||
// set user counter MSW, reset counter
|
// set user counter MSW, reset counter
|
||||||
qemu_irq_lower(s->irq);
|
qemu_irq_lower(s->irq);
|
||||||
s->limit = TIMER_MAX_COUNT64;
|
s->limit = TIMER_MAX_COUNT64;
|
||||||
DPRINTF("processor %d user timer reset\n", s->slave_index);
|
s->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
|
||||||
if (s->timer)
|
s->reached = 0;
|
||||||
ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
|
count = ((uint64_t)s->counthigh << 32) | s->count;
|
||||||
|
DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
|
||||||
|
count);
|
||||||
|
if (s->timer) {
|
||||||
|
ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
|
||||||
|
ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// set limit, reset counter
|
// set limit, reset counter
|
||||||
qemu_irq_lower(s->irq);
|
qemu_irq_lower(s->irq);
|
||||||
|
@ -210,12 +217,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
|
||||||
break;
|
break;
|
||||||
case TIMER_COUNTER:
|
case TIMER_COUNTER:
|
||||||
if (slavio_timer_is_user(s)) {
|
if (slavio_timer_is_user(s)) {
|
||||||
|
uint64_t count;
|
||||||
|
|
||||||
// set user counter LSW, reset counter
|
// set user counter LSW, reset counter
|
||||||
qemu_irq_lower(s->irq);
|
qemu_irq_lower(s->irq);
|
||||||
s->limit = TIMER_MAX_COUNT64;
|
s->limit = TIMER_MAX_COUNT64;
|
||||||
DPRINTF("processor %d user timer reset\n", s->slave_index);
|
s->count = val & TIMER_MAX_COUNT64;
|
||||||
if (s->timer)
|
s->reached = 0;
|
||||||
ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
|
count = ((uint64_t)s->counthigh) << 32 | s->count;
|
||||||
|
DPRINTF("processor %d user timer set to %016llx\n", s->slave_index,
|
||||||
|
count);
|
||||||
|
if (s->timer) {
|
||||||
|
ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count));
|
||||||
|
ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
DPRINTF("not user timer\n");
|
DPRINTF("not user timer\n");
|
||||||
break;
|
break;
|
||||||
|
|
Reference in New Issue