Commit 115646b6480b4f3f0fd9f7a66f46c96f68604cc7

Authored by blueswir1
1 parent f930d07e

More user timer fixes (Robert Reif)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3339 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 87 additions and 69 deletions
Changelog
... ... @@ -3,7 +3,7 @@
3 3 - Monitor multiplexing to several I/O channels (Jason Wessel)
4 4 - ds1225y nvram support (Herve Poussineau)
5 5 - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
6   - - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
  6 + - Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
7 7 - MIPS 64-bit FPU support (Thiemo Seufer)
8 8 - Xscale PDA emulation (Andrzei Zaborowski)
9 9 - ColdFire system emulation (Paul Brook)
... ...
hw/slavio_timer.c
... ... @@ -54,16 +54,24 @@ typedef struct SLAVIO_TIMERState {
54 54 ptimer_state *timer;
55 55 uint32_t count, counthigh, reached;
56 56 uint64_t limit;
57   - int stopped;
58   - int mode; // 0 = processor, 1 = user, 2 = system
  57 + // processor only
  58 + int running;
  59 + struct SLAVIO_TIMERState *master;
  60 + int slave_index;
  61 + // system only
59 62 struct SLAVIO_TIMERState *slave[MAX_CPUS];
60 63 uint32_t slave_mode;
61 64 } SLAVIO_TIMERState;
62 65  
63 66 #define TIMER_MAXADDR 0x1f
64   -#define TIMER_SIZE (TIMER_MAXADDR + 1)
  67 +#define SYS_TIMER_SIZE 0x14
65 68 #define CPU_TIMER_SIZE 0x10
66 69  
  70 +static int slavio_timer_is_user(SLAVIO_TIMERState *s)
  71 +{
  72 + return s->master && (s->master->slave_mode & (1 << s->slave_index));
  73 +}
  74 +
67 75 // Update count, set irq, update expire_time
68 76 // Convert from ptimer countdown units
69 77 static void slavio_timer_get_out(SLAVIO_TIMERState *s)
... ... @@ -84,9 +92,10 @@ static void slavio_timer_irq(void *opaque)
84 92  
85 93 slavio_timer_get_out(s);
86 94 DPRINTF("callback: count %x%08x\n", s->counthigh, s->count);
87   - s->reached = 0x80000000;
88   - if (s->mode != 1)
  95 + if (!slavio_timer_is_user(s)) {
  96 + s->reached = 0x80000000;
89 97 qemu_irq_raise(s->irq);
  98 + }
90 99 }
91 100  
92 101 static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
... ... @@ -99,35 +108,39 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
99 108 case 0:
100 109 // read limit (system counter mode) or read most signifying
101 110 // part of counter (user mode)
102   - if (s->mode != 1) {
  111 + if (slavio_timer_is_user(s)) {
  112 + // read user timer MSW
  113 + slavio_timer_get_out(s);
  114 + ret = s->counthigh;
  115 + } else {
  116 + // read limit
103 117 // clear irq
104 118 qemu_irq_lower(s->irq);
105 119 s->reached = 0;
106 120 ret = s->limit & 0x7fffffff;
107 121 }
108   - else {
109   - slavio_timer_get_out(s);
110   - ret = s->counthigh & 0x7fffffff;
111   - }
112 122 break;
113 123 case 1:
114 124 // read counter and reached bit (system mode) or read lsbits
115 125 // of counter (user mode)
116 126 slavio_timer_get_out(s);
117   - if (s->mode != 1)
118   - ret = (s->count & 0x7fffffff) | s->reached;
119   - else
120   - ret = s->count;
  127 + if (slavio_timer_is_user(s)) // read user timer LSW
  128 + ret = s->count & 0xffffffe00;
  129 + else // read limit
  130 + ret = (s->count & 0x7ffffe00) | s->reached;
121 131 break;
122 132 case 3:
  133 + // only available in processor counter/timer
123 134 // read start/stop status
124   - ret = s->stopped;
  135 + ret = s->running;
125 136 break;
126 137 case 4:
  138 + // only available in system counter
127 139 // read user/system mode
128 140 ret = s->slave_mode;
129 141 break;
130 142 default:
  143 + DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
131 144 ret = 0;
132 145 break;
133 146 }
... ... @@ -146,20 +159,31 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3
146 159 saddr = (addr & TIMER_MAXADDR) >> 2;
147 160 switch (saddr) {
148 161 case 0:
149   - if (s->mode == 1) {
150   - // set user counter limit MSW, reset counter
  162 + if (slavio_timer_is_user(s)) {
  163 + // set user counter MSW, reset counter
151 164 qemu_irq_lower(s->irq);
152   - s->limit &= 0xfffffe00ULL;
153   - s->limit |= (uint64_t)val << 32;
  165 + s->limit = 0x7ffffffffffffe00ULL;
  166 + DPRINTF("processor %d user timer reset\n", s->slave_index);
  167 + ptimer_set_limit(s->timer, s->limit >> 9, 1);
  168 + } else {
  169 + // set limit, reset counter
  170 + qemu_irq_lower(s->irq);
  171 + s->limit = val & 0x7ffffe00ULL;
154 172 if (!s->limit)
155   - s->limit = 0x7ffffffffffffe00ULL;
  173 + s->limit = 0x7ffffe00ULL;
156 174 ptimer_set_limit(s->timer, s->limit >> 9, 1);
157   - break;
158 175 }
159   - // set limit, reset counter
160   - reload = 1;
161   - qemu_irq_lower(s->irq);
162   - // fall through
  176 + break;
  177 + case 1:
  178 + if (slavio_timer_is_user(s)) {
  179 + // set user counter LSW, reset counter
  180 + qemu_irq_lower(s->irq);
  181 + s->limit = 0x7ffffffffffffe00ULL;
  182 + DPRINTF("processor %d user timer reset\n", s->slave_index);
  183 + ptimer_set_limit(s->timer, s->limit >> 9, 1);
  184 + } else
  185 + DPRINTF("not user timer\n");
  186 + break;
163 187 case 2:
164 188 // set limit without resetting counter
165 189 s->limit = val & 0x7ffffe00ULL;
... ... @@ -167,52 +191,42 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3
167 191 s->limit = 0x7ffffe00ULL;
168 192 ptimer_set_limit(s->timer, s->limit >> 9, reload);
169 193 break;
170   - case 1:
171   - // set user counter limit LSW, reset counter
172   - if (s->mode == 1) {
173   - qemu_irq_lower(s->irq);
174   - s->limit &= 0x7fffffff00000000ULL;
175   - s->limit |= val & 0xfffffe00ULL;
176   - if (!s->limit)
177   - s->limit = 0x7ffffffffffffe00ULL;
178   - ptimer_set_limit(s->timer, s->limit >> 9, 1);
179   - }
180   - break;
181 194 case 3:
182   - // start/stop user counter
183   - if (s->mode == 1) {
184   - if (val & 1) {
185   - ptimer_stop(s->timer);
186   - s->stopped = 1;
187   - }
188   - else {
  195 + if (slavio_timer_is_user(s)) {
  196 + // start/stop user counter
  197 + if ((val & 1) && !s->running) {
  198 + DPRINTF("processor %d user timer started\n", s->slave_index);
189 199 ptimer_run(s->timer, 0);
190   - s->stopped = 0;
  200 + s->running = 1;
  201 + } else if (!(val & 1) && s->running) {
  202 + DPRINTF("processor %d user timer stopped\n", s->slave_index);
  203 + ptimer_stop(s->timer);
  204 + s->running = 0;
191 205 }
192 206 }
193 207 break;
194 208 case 4:
195   - // bit 0: user (1) or system (0) counter mode
196   - {
  209 + if (s->master == NULL) {
197 210 unsigned int i;
198 211  
199 212 for (i = 0; i < MAX_CPUS; i++) {
200 213 if (val & (1 << i)) {
201 214 qemu_irq_lower(s->slave[i]->irq);
202 215 s->slave[i]->limit = -1ULL;
203   - s->slave[i]->mode = 1;
204   - } else {
205   - s->slave[i]->mode = 0;
206 216 }
207   - ptimer_stop(s->slave[i]->timer);
208   - ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9,
209   - 1);
210   - ptimer_run(s->slave[i]->timer, 0);
  217 + if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
  218 + ptimer_stop(s->slave[i]->timer);
  219 + ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, 1);
  220 + DPRINTF("processor %d timer changed\n", s->slave[i]->slave_index);
  221 + ptimer_run(s->slave[i]->timer, 0);
  222 + }
211 223 }
212 224 s->slave_mode = val & ((1 << MAX_CPUS) - 1);
213   - }
  225 + } else
  226 + DPRINTF("not system timer\n");
214 227 break;
215 228 default:
  229 + DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
216 230 break;
217 231 }
218 232 }
... ... @@ -238,8 +252,8 @@ static void slavio_timer_save(QEMUFile *f, void *opaque)
238 252 qemu_put_be32s(f, &s->counthigh);
239 253 qemu_put_be32(f, 0); // Was irq
240 254 qemu_put_be32s(f, &s->reached);
241   - qemu_put_be32s(f, &s->stopped);
242   - qemu_put_be32s(f, &s->mode);
  255 + qemu_put_be32s(f, &s->running);
  256 + qemu_put_be32s(f, 0); // Was mode
243 257 qemu_put_ptimer(f, s->timer);
244 258 }
245 259  
... ... @@ -256,8 +270,8 @@ static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
256 270 qemu_get_be32s(f, &s->counthigh);
257 271 qemu_get_be32s(f, &tmp); // Was irq
258 272 qemu_get_be32s(f, &s->reached);
259   - qemu_get_be32s(f, &s->stopped);
260   - qemu_get_be32s(f, &s->mode);
  273 + qemu_get_be32s(f, &s->running);
  274 + qemu_get_be32s(f, &tmp); // Was mode
261 275 qemu_get_ptimer(f, s->timer);
262 276  
263 277 return 0;
... ... @@ -267,18 +281,22 @@ static void slavio_timer_reset(void *opaque)
267 281 {
268 282 SLAVIO_TIMERState *s = opaque;
269 283  
270   - s->limit = 0x7ffffe00ULL;
  284 + if (slavio_timer_is_user(s))
  285 + s->limit = 0x7ffffffffffffe00ULL;
  286 + else
  287 + s->limit = 0x7ffffe00ULL;
271 288 s->count = 0;
272 289 s->reached = 0;
273   - s->mode &= 2;
274 290 ptimer_set_limit(s->timer, s->limit >> 9, 1);
275 291 ptimer_run(s->timer, 0);
276   - s->stopped = 1;
  292 + s->running = 1;
277 293 qemu_irq_lower(s->irq);
278 294 }
279 295  
280 296 static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
281   - qemu_irq irq, int mode)
  297 + qemu_irq irq,
  298 + SLAVIO_TIMERState *master,
  299 + int slave_index)
282 300 {
283 301 int slavio_timer_io_memory;
284 302 SLAVIO_TIMERState *s;
... ... @@ -288,18 +306,18 @@ static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
288 306 if (!s)
289 307 return s;
290 308 s->irq = irq;
291   - s->mode = mode;
  309 + s->master = master;
  310 + s->slave_index = slave_index;
292 311 bh = qemu_bh_new(slavio_timer_irq, s);
293 312 s->timer = ptimer_init(bh);
294 313 ptimer_set_period(s->timer, 500ULL);
295 314  
296 315 slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
297 316 slavio_timer_mem_write, s);
298   - if (mode < 2)
  317 + if (master)
299 318 cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
300 319 else
301   - cpu_register_physical_memory(addr, TIMER_SIZE,
302   - slavio_timer_io_memory);
  320 + cpu_register_physical_memory(addr, SYS_TIMER_SIZE, slavio_timer_io_memory);
303 321 register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
304 322 qemu_register_reset(slavio_timer_reset, s);
305 323 slavio_timer_reset(s);
... ... @@ -313,11 +331,11 @@ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
313 331 SLAVIO_TIMERState *master;
314 332 unsigned int i;
315 333  
316   - master = slavio_timer_init(base + 0x10000ULL, master_irq, 2);
  334 + master = slavio_timer_init(base + 0x10000ULL, master_irq, NULL, 0);
317 335  
318 336 for (i = 0; i < MAX_CPUS; i++) {
319 337 master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
320 338 (i * TARGET_PAGE_SIZE),
321   - cpu_irqs[i], 0);
  339 + cpu_irqs[i], master, i);
322 340 }
323 341 }
... ...