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 | 122 | |
123 | 123 | slavio_timer_get_out(s); |
124 | 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 | 127 | qemu_irq_raise(s->irq); |
128 | - } | |
129 | 128 | } |
130 | 129 | |
131 | 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 | 140 | if (slavio_timer_is_user(s)) { |
142 | 141 | // read user timer MSW |
143 | 142 | slavio_timer_get_out(s); |
144 | - ret = s->counthigh; | |
143 | + ret = s->counthigh | s->reached; | |
145 | 144 | } else { |
146 | 145 | // read limit |
147 | 146 | // clear irq |
... | ... | @@ -155,7 +154,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) |
155 | 154 | // of counter (user mode) |
156 | 155 | slavio_timer_get_out(s); |
157 | 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 | 158 | else // read limit |
160 | 159 | ret = (s->count & TIMER_MAX_COUNT32) | s->reached; |
161 | 160 | break; |
... | ... | @@ -190,12 +189,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, |
190 | 189 | switch (saddr) { |
191 | 190 | case TIMER_LIMIT: |
192 | 191 | if (slavio_timer_is_user(s)) { |
192 | + uint64_t count; | |
193 | + | |
193 | 194 | // set user counter MSW, reset counter |
194 | 195 | qemu_irq_lower(s->irq); |
195 | 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 | 206 | } else { |
200 | 207 | // set limit, reset counter |
201 | 208 | qemu_irq_lower(s->irq); |
... | ... | @@ -210,12 +217,20 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, |
210 | 217 | break; |
211 | 218 | case TIMER_COUNTER: |
212 | 219 | if (slavio_timer_is_user(s)) { |
220 | + uint64_t count; | |
221 | + | |
213 | 222 | // set user counter LSW, reset counter |
214 | 223 | qemu_irq_lower(s->irq); |
215 | 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 | 234 | } else |
220 | 235 | DPRINTF("not user timer\n"); |
221 | 236 | break; | ... | ... |