Commit e1cb9502426a605e30aa4a43875161ee44a66bc2
1 parent
40a2e657
User timer limit fixes (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3931 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
26 additions
and
11 deletions
hw/slavio_timer.c
| @@ -122,10 +122,9 @@ static void slavio_timer_irq(void *opaque) | @@ -122,10 +122,9 @@ static void slavio_timer_irq(void *opaque) | ||
| 122 | 122 | ||
| 123 | slavio_timer_get_out(s); | 123 | slavio_timer_get_out(s); |
| 124 | DPRINTF("callback: count %x%08x\n", s->counthigh, s->count); | 124 | DPRINTF("callback: count %x%08x\n", s->counthigh, s->count); |
| 125 | - if (!slavio_timer_is_user(s)) { | ||
| 126 | - s->reached = TIMER_REACHED; | 125 | + s->reached = TIMER_REACHED; |
| 126 | + if (!slavio_timer_is_user(s)) | ||
| 127 | qemu_irq_raise(s->irq); | 127 | qemu_irq_raise(s->irq); |
| 128 | - } | ||
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) | 130 | 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) | @@ -141,7 +140,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 141 | if (slavio_timer_is_user(s)) { | 140 | if (slavio_timer_is_user(s)) { |
| 142 | // read user timer MSW | 141 | // read user timer MSW |
| 143 | slavio_timer_get_out(s); | 142 | slavio_timer_get_out(s); |
| 144 | - ret = s->counthigh; | 143 | + ret = s->counthigh | s->reached; |
| 145 | } else { | 144 | } else { |
| 146 | // read limit | 145 | // read limit |
| 147 | // clear irq | 146 | // clear irq |
| @@ -155,7 +154,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) | @@ -155,7 +154,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 155 | // of counter (user mode) | 154 | // of counter (user mode) |
| 156 | slavio_timer_get_out(s); | 155 | slavio_timer_get_out(s); |
| 157 | if (slavio_timer_is_user(s)) // read user timer LSW | 156 | if (slavio_timer_is_user(s)) // read user timer LSW |
| 158 | - ret = s->count & TIMER_COUNT_MASK32; | 157 | + ret = s->count & TIMER_MAX_COUNT64; |
| 159 | else // read limit | 158 | else // read limit |
| 160 | ret = (s->count & TIMER_MAX_COUNT32) | s->reached; | 159 | ret = (s->count & TIMER_MAX_COUNT32) | s->reached; |
| 161 | break; | 160 | break; |
| @@ -190,12 +189,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | @@ -190,12 +189,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | ||
| 190 | switch (saddr) { | 189 | switch (saddr) { |
| 191 | case TIMER_LIMIT: | 190 | case TIMER_LIMIT: |
| 192 | if (slavio_timer_is_user(s)) { | 191 | if (slavio_timer_is_user(s)) { |
| 192 | + uint64_t count; | ||
| 193 | + | ||
| 193 | // set user counter MSW, reset counter | 194 | // set user counter MSW, reset counter |
| 194 | qemu_irq_lower(s->irq); | 195 | qemu_irq_lower(s->irq); |
| 195 | s->limit = TIMER_MAX_COUNT64; | 196 | s->limit = TIMER_MAX_COUNT64; |
| 196 | - DPRINTF("processor %d user timer reset\n", s->slave_index); | ||
| 197 | - if (s->timer) | ||
| 198 | - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1); | 197 | + s->counthigh = val & (TIMER_MAX_COUNT64 >> 32); |
| 198 | + s->reached = 0; | ||
| 199 | + count = ((uint64_t)s->counthigh << 32) | s->count; | ||
| 200 | + DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, | ||
| 201 | + count); | ||
| 202 | + if (s->timer) { | ||
| 203 | + ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); | ||
| 204 | + ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); | ||
| 205 | + } | ||
| 199 | } else { | 206 | } else { |
| 200 | // set limit, reset counter | 207 | // set limit, reset counter |
| 201 | qemu_irq_lower(s->irq); | 208 | qemu_irq_lower(s->irq); |
| @@ -210,12 +217,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | @@ -210,12 +217,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | ||
| 210 | break; | 217 | break; |
| 211 | case TIMER_COUNTER: | 218 | case TIMER_COUNTER: |
| 212 | if (slavio_timer_is_user(s)) { | 219 | if (slavio_timer_is_user(s)) { |
| 220 | + uint64_t count; | ||
| 221 | + | ||
| 213 | // set user counter LSW, reset counter | 222 | // set user counter LSW, reset counter |
| 214 | qemu_irq_lower(s->irq); | 223 | qemu_irq_lower(s->irq); |
| 215 | s->limit = TIMER_MAX_COUNT64; | 224 | s->limit = TIMER_MAX_COUNT64; |
| 216 | - DPRINTF("processor %d user timer reset\n", s->slave_index); | ||
| 217 | - if (s->timer) | ||
| 218 | - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1); | 225 | + s->count = val & TIMER_MAX_COUNT64; |
| 226 | + s->reached = 0; | ||
| 227 | + count = ((uint64_t)s->counthigh) << 32 | s->count; | ||
| 228 | + DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, | ||
| 229 | + count); | ||
| 230 | + if (s->timer) { | ||
| 231 | + ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); | ||
| 232 | + ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); | ||
| 233 | + } | ||
| 219 | } else | 234 | } else |
| 220 | DPRINTF("not user timer\n"); | 235 | DPRINTF("not user timer\n"); |
| 221 | break; | 236 | break; |