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,7 +3,7 @@
3 - Monitor multiplexing to several I/O channels (Jason Wessel) 3 - Monitor multiplexing to several I/O channels (Jason Wessel)
4 - ds1225y nvram support (Herve Poussineau) 4 - ds1225y nvram support (Herve Poussineau)
5 - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) 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 - MIPS 64-bit FPU support (Thiemo Seufer) 7 - MIPS 64-bit FPU support (Thiemo Seufer)
8 - Xscale PDA emulation (Andrzei Zaborowski) 8 - Xscale PDA emulation (Andrzei Zaborowski)
9 - ColdFire system emulation (Paul Brook) 9 - ColdFire system emulation (Paul Brook)
hw/slavio_timer.c
@@ -54,16 +54,24 @@ typedef struct SLAVIO_TIMERState { @@ -54,16 +54,24 @@ typedef struct SLAVIO_TIMERState {
54 ptimer_state *timer; 54 ptimer_state *timer;
55 uint32_t count, counthigh, reached; 55 uint32_t count, counthigh, reached;
56 uint64_t limit; 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 struct SLAVIO_TIMERState *slave[MAX_CPUS]; 62 struct SLAVIO_TIMERState *slave[MAX_CPUS];
60 uint32_t slave_mode; 63 uint32_t slave_mode;
61 } SLAVIO_TIMERState; 64 } SLAVIO_TIMERState;
62 65
63 #define TIMER_MAXADDR 0x1f 66 #define TIMER_MAXADDR 0x1f
64 -#define TIMER_SIZE (TIMER_MAXADDR + 1) 67 +#define SYS_TIMER_SIZE 0x14
65 #define CPU_TIMER_SIZE 0x10 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 // Update count, set irq, update expire_time 75 // Update count, set irq, update expire_time
68 // Convert from ptimer countdown units 76 // Convert from ptimer countdown units
69 static void slavio_timer_get_out(SLAVIO_TIMERState *s) 77 static void slavio_timer_get_out(SLAVIO_TIMERState *s)
@@ -84,9 +92,10 @@ static void slavio_timer_irq(void *opaque) @@ -84,9 +92,10 @@ static void slavio_timer_irq(void *opaque)
84 92
85 slavio_timer_get_out(s); 93 slavio_timer_get_out(s);
86 DPRINTF("callback: count %x%08x\n", s->counthigh, s->count); 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 qemu_irq_raise(s->irq); 97 qemu_irq_raise(s->irq);
  98 + }
90 } 99 }
91 100
92 static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) 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,35 +108,39 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
99 case 0: 108 case 0:
100 // read limit (system counter mode) or read most signifying 109 // read limit (system counter mode) or read most signifying
101 // part of counter (user mode) 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 // clear irq 117 // clear irq
104 qemu_irq_lower(s->irq); 118 qemu_irq_lower(s->irq);
105 s->reached = 0; 119 s->reached = 0;
106 ret = s->limit & 0x7fffffff; 120 ret = s->limit & 0x7fffffff;
107 } 121 }
108 - else {  
109 - slavio_timer_get_out(s);  
110 - ret = s->counthigh & 0x7fffffff;  
111 - }  
112 break; 122 break;
113 case 1: 123 case 1:
114 // read counter and reached bit (system mode) or read lsbits 124 // read counter and reached bit (system mode) or read lsbits
115 // of counter (user mode) 125 // of counter (user mode)
116 slavio_timer_get_out(s); 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 break; 131 break;
122 case 3: 132 case 3:
  133 + // only available in processor counter/timer
123 // read start/stop status 134 // read start/stop status
124 - ret = s->stopped; 135 + ret = s->running;
125 break; 136 break;
126 case 4: 137 case 4:
  138 + // only available in system counter
127 // read user/system mode 139 // read user/system mode
128 ret = s->slave_mode; 140 ret = s->slave_mode;
129 break; 141 break;
130 default: 142 default:
  143 + DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
131 ret = 0; 144 ret = 0;
132 break; 145 break;
133 } 146 }
@@ -146,20 +159,31 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3 @@ -146,20 +159,31 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3
146 saddr = (addr & TIMER_MAXADDR) >> 2; 159 saddr = (addr & TIMER_MAXADDR) >> 2;
147 switch (saddr) { 160 switch (saddr) {
148 case 0: 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 qemu_irq_lower(s->irq); 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 if (!s->limit) 172 if (!s->limit)
155 - s->limit = 0x7ffffffffffffe00ULL; 173 + s->limit = 0x7ffffe00ULL;
156 ptimer_set_limit(s->timer, s->limit >> 9, 1); 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 case 2: 187 case 2:
164 // set limit without resetting counter 188 // set limit without resetting counter
165 s->limit = val & 0x7ffffe00ULL; 189 s->limit = val & 0x7ffffe00ULL;
@@ -167,52 +191,42 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3 @@ -167,52 +191,42 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint3
167 s->limit = 0x7ffffe00ULL; 191 s->limit = 0x7ffffe00ULL;
168 ptimer_set_limit(s->timer, s->limit >> 9, reload); 192 ptimer_set_limit(s->timer, s->limit >> 9, reload);
169 break; 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 case 3: 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 ptimer_run(s->timer, 0); 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 break; 207 break;
194 case 4: 208 case 4:
195 - // bit 0: user (1) or system (0) counter mode  
196 - { 209 + if (s->master == NULL) {
197 unsigned int i; 210 unsigned int i;
198 211
199 for (i = 0; i < MAX_CPUS; i++) { 212 for (i = 0; i < MAX_CPUS; i++) {
200 if (val & (1 << i)) { 213 if (val & (1 << i)) {
201 qemu_irq_lower(s->slave[i]->irq); 214 qemu_irq_lower(s->slave[i]->irq);
202 s->slave[i]->limit = -1ULL; 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 s->slave_mode = val & ((1 << MAX_CPUS) - 1); 224 s->slave_mode = val & ((1 << MAX_CPUS) - 1);
213 - } 225 + } else
  226 + DPRINTF("not system timer\n");
214 break; 227 break;
215 default: 228 default:
  229 + DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
216 break; 230 break;
217 } 231 }
218 } 232 }
@@ -238,8 +252,8 @@ static void slavio_timer_save(QEMUFile *f, void *opaque) @@ -238,8 +252,8 @@ static void slavio_timer_save(QEMUFile *f, void *opaque)
238 qemu_put_be32s(f, &s->counthigh); 252 qemu_put_be32s(f, &s->counthigh);
239 qemu_put_be32(f, 0); // Was irq 253 qemu_put_be32(f, 0); // Was irq
240 qemu_put_be32s(f, &s->reached); 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 qemu_put_ptimer(f, s->timer); 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,8 +270,8 @@ static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
256 qemu_get_be32s(f, &s->counthigh); 270 qemu_get_be32s(f, &s->counthigh);
257 qemu_get_be32s(f, &tmp); // Was irq 271 qemu_get_be32s(f, &tmp); // Was irq
258 qemu_get_be32s(f, &s->reached); 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 qemu_get_ptimer(f, s->timer); 275 qemu_get_ptimer(f, s->timer);
262 276
263 return 0; 277 return 0;
@@ -267,18 +281,22 @@ static void slavio_timer_reset(void *opaque) @@ -267,18 +281,22 @@ static void slavio_timer_reset(void *opaque)
267 { 281 {
268 SLAVIO_TIMERState *s = opaque; 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 s->count = 0; 288 s->count = 0;
272 s->reached = 0; 289 s->reached = 0;
273 - s->mode &= 2;  
274 ptimer_set_limit(s->timer, s->limit >> 9, 1); 290 ptimer_set_limit(s->timer, s->limit >> 9, 1);
275 ptimer_run(s->timer, 0); 291 ptimer_run(s->timer, 0);
276 - s->stopped = 1; 292 + s->running = 1;
277 qemu_irq_lower(s->irq); 293 qemu_irq_lower(s->irq);
278 } 294 }
279 295
280 static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, 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 int slavio_timer_io_memory; 301 int slavio_timer_io_memory;
284 SLAVIO_TIMERState *s; 302 SLAVIO_TIMERState *s;
@@ -288,18 +306,18 @@ static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, @@ -288,18 +306,18 @@ static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr,
288 if (!s) 306 if (!s)
289 return s; 307 return s;
290 s->irq = irq; 308 s->irq = irq;
291 - s->mode = mode; 309 + s->master = master;
  310 + s->slave_index = slave_index;
292 bh = qemu_bh_new(slavio_timer_irq, s); 311 bh = qemu_bh_new(slavio_timer_irq, s);
293 s->timer = ptimer_init(bh); 312 s->timer = ptimer_init(bh);
294 ptimer_set_period(s->timer, 500ULL); 313 ptimer_set_period(s->timer, 500ULL);
295 314
296 slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read, 315 slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
297 slavio_timer_mem_write, s); 316 slavio_timer_mem_write, s);
298 - if (mode < 2) 317 + if (master)
299 cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory); 318 cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory);
300 else 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 register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s); 321 register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s);
304 qemu_register_reset(slavio_timer_reset, s); 322 qemu_register_reset(slavio_timer_reset, s);
305 slavio_timer_reset(s); 323 slavio_timer_reset(s);
@@ -313,11 +331,11 @@ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, @@ -313,11 +331,11 @@ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
313 SLAVIO_TIMERState *master; 331 SLAVIO_TIMERState *master;
314 unsigned int i; 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 for (i = 0; i < MAX_CPUS; i++) { 336 for (i = 0; i < MAX_CPUS; i++) {
319 master->slave[i] = slavio_timer_init(base + (target_phys_addr_t) 337 master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
320 (i * TARGET_PAGE_SIZE), 338 (i * TARGET_PAGE_SIZE),
321 - cpu_irqs[i], 0); 339 + cpu_irqs[i], master, i);
322 } 340 }
323 } 341 }