Commit e1cb9502426a605e30aa4a43875161ee44a66bc2

Authored by blueswir1
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;
... ...