Commit 61271e5c2d3eff4cc0c4845be291172c2015b6f1

Authored by bellard
1 parent aefce9af

more precise cuda timers


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1508 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 47 additions and 22 deletions
hw/cuda.c
@@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
23 */ 23 */
24 #include "vl.h" 24 #include "vl.h"
25 25
  26 +/* XXX: implement all timer modes */
  27 +
26 //#define DEBUG_CUDA 28 //#define DEBUG_CUDA
27 //#define DEBUG_CUDA_PACKET 29 //#define DEBUG_CUDA_PACKET
28 30
@@ -41,6 +43,7 @@ @@ -41,6 +43,7 @@
41 #define IER_CLR 0 /* clear bits in IER */ 43 #define IER_CLR 0 /* clear bits in IER */
42 #define SR_INT 0x04 /* Shift register full/empty */ 44 #define SR_INT 0x04 /* Shift register full/empty */
43 #define T1_INT 0x40 /* Timer 1 interrupt */ 45 #define T1_INT 0x40 /* Timer 1 interrupt */
  46 +#define T2_INT 0x20 /* Timer 2 interrupt */
44 47
45 /* Bits in ACR */ 48 /* Bits in ACR */
46 #define T1MODE 0xc0 /* Timer 1 mode */ 49 #define T1MODE 0xc0 /* Timer 1 mode */
@@ -91,7 +94,8 @@ @@ -91,7 +94,8 @@
91 #define RTC_OFFSET 2082844800 94 #define RTC_OFFSET 2082844800
92 95
93 typedef struct CUDATimer { 96 typedef struct CUDATimer {
94 - unsigned int latch; 97 + int index;
  98 + uint16_t latch;
95 uint16_t counter_value; /* counter value at load time */ 99 uint16_t counter_value; /* counter value at load time */
96 int64_t load_time; 100 int64_t load_time;
97 int64_t next_irq_time; 101 int64_t next_irq_time;
@@ -154,10 +158,16 @@ static unsigned int get_counter(CUDATimer *s) @@ -154,10 +158,16 @@ static unsigned int get_counter(CUDATimer *s)
154 158
155 d = muldiv64(qemu_get_clock(vm_clock) - s->load_time, 159 d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
156 CUDA_TIMER_FREQ, ticks_per_sec); 160 CUDA_TIMER_FREQ, ticks_per_sec);
157 - if (d <= s->counter_value) {  
158 - counter = d; 161 + if (s->index == 0) {
  162 + /* the timer goes down from latch to -1 (period of latch + 2) */
  163 + if (d <= (s->counter_value + 1)) {
  164 + counter = (s->counter_value - d) & 0xffff;
  165 + } else {
  166 + counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  167 + counter = (s->latch - counter) & 0xffff;
  168 + }
159 } else { 169 } else {
160 - counter = s->latch - 1 - ((d - s->counter_value) % s->latch); 170 + counter = (s->counter_value - d) & 0xffff;
161 } 171 }
162 return counter; 172 return counter;
163 } 173 }
@@ -175,17 +185,27 @@ static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) @@ -175,17 +185,27 @@ static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
175 185
176 static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) 186 static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
177 { 187 {
178 - int64_t d, next_time, base; 188 + int64_t d, next_time;
  189 + unsigned int counter;
  190 +
179 /* current counter value */ 191 /* current counter value */
180 d = muldiv64(current_time - s->load_time, 192 d = muldiv64(current_time - s->load_time,
181 CUDA_TIMER_FREQ, ticks_per_sec); 193 CUDA_TIMER_FREQ, ticks_per_sec);
182 - if (d < s->counter_value) {  
183 - next_time = s->counter_value + 1;  
184 - } else  
185 - {  
186 - base = ((d - s->counter_value + 1) / s->latch);  
187 - base = (base * s->latch) + s->counter_value;  
188 - next_time = base + s->latch; 194 + /* the timer goes down from latch to -1 (period of latch + 2) */
  195 + if (d <= (s->counter_value + 1)) {
  196 + counter = (s->counter_value - d) & 0xffff;
  197 + } else {
  198 + counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  199 + counter = (s->latch - counter) & 0xffff;
  200 + }
  201 +
  202 + /* Note: we consider the irq is raised on 0 */
  203 + if (counter == 0xffff) {
  204 + next_time = d + s->latch + 1;
  205 + } else if (counter == 0) {
  206 + next_time = d + s->latch + 2;
  207 + } else {
  208 + next_time = d + counter;
189 } 209 }
190 #if 0 210 #if 0
191 #ifdef DEBUG_CUDA 211 #ifdef DEBUG_CUDA
@@ -249,17 +269,18 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) @@ -249,17 +269,18 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
249 break; 269 break;
250 case 5: 270 case 5:
251 val = get_counter(&s->timers[0]) >> 8; 271 val = get_counter(&s->timers[0]) >> 8;
252 - s->ifr &= ~T1_INT;  
253 cuda_update_irq(s); 272 cuda_update_irq(s);
254 break; 273 break;
255 case 6: 274 case 6:
256 val = s->timers[0].latch & 0xff; 275 val = s->timers[0].latch & 0xff;
257 break; 276 break;
258 case 7: 277 case 7:
  278 + /* XXX: check this */
259 val = (s->timers[0].latch >> 8) & 0xff; 279 val = (s->timers[0].latch >> 8) & 0xff;
260 break; 280 break;
261 case 8: 281 case 8:
262 val = get_counter(&s->timers[1]) & 0xff; 282 val = get_counter(&s->timers[1]) & 0xff;
  283 + s->ifr &= ~T2_INT;
263 break; 284 break;
264 case 9: 285 case 9:
265 val = get_counter(&s->timers[1]) >> 8; 286 val = get_counter(&s->timers[1]) >> 8;
@@ -317,12 +338,13 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -317,12 +338,13 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
317 s->dira = val; 338 s->dira = val;
318 break; 339 break;
319 case 4: 340 case 4:
320 - val = val | (get_counter(&s->timers[0]) & 0xff00);  
321 - set_counter(s, &s->timers[0], val); 341 + s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  342 + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
322 break; 343 break;
323 case 5: 344 case 5:
324 - val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);  
325 - set_counter(s, &s->timers[0], val); 345 + s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  346 + s->ifr &= ~T1_INT;
  347 + set_counter(s, &s->timers[0], s->timers[0].latch);
326 break; 348 break;
327 case 6: 349 case 6:
328 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; 350 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
@@ -330,15 +352,15 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -330,15 +352,15 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
330 break; 352 break;
331 case 7: 353 case 7:
332 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); 354 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  355 + s->ifr &= ~T1_INT;
333 cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); 356 cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
334 break; 357 break;
335 case 8: 358 case 8:
336 - val = val | (get_counter(&s->timers[1]) & 0xff00); 359 + s->timers[1].latch = val;
337 set_counter(s, &s->timers[1], val); 360 set_counter(s, &s->timers[1], val);
338 break; 361 break;
339 case 9: 362 case 9:
340 - val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);  
341 - set_counter(s, &s->timers[1], val); 363 + set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
342 break; 364 break;
343 case 10: 365 case 10:
344 s->sr = val; 366 s->sr = val;
@@ -620,10 +642,13 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq) @@ -620,10 +642,13 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
620 s->irq_opaque = irq_opaque; 642 s->irq_opaque = irq_opaque;
621 s->irq = irq; 643 s->irq = irq;
622 644
  645 + s->timers[0].index = 0;
623 s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); 646 s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
624 - s->timers[0].latch = 0x10000; 647 + s->timers[0].latch = 0xffff;
625 set_counter(s, &s->timers[0], 0xffff); 648 set_counter(s, &s->timers[0], 0xffff);
626 - s->timers[1].latch = 0x10000; 649 +
  650 + s->timers[1].index = 1;
  651 + s->timers[1].latch = 0;
627 // s->ier = T1_INT | SR_INT; 652 // s->ier = T1_INT | SR_INT;
628 s->ier = 0; 653 s->ier = 0;
629 set_counter(s, &s->timers[1], 0xffff); 654 set_counter(s, &s->timers[1], 0xffff);