Revision 8f4efc55

b/hw/sun4u.c
40 40

  
41 41
//#define DEBUG_IRQ
42 42
//#define DEBUG_EBUS
43
//#define DEBUG_TIMER
43 44

  
44 45
#ifdef DEBUG_IRQ
45 46
#define CPUIRQ_DPRINTF(fmt, ...)                                \
......
55 56
#define EBUS_DPRINTF(fmt, ...)
56 57
#endif
57 58

  
59
#ifdef DEBUG_TIMER
60
#define TIMER_DPRINTF(fmt, ...)                                  \
61
    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
62
#else
63
#define TIMER_DPRINTF(fmt, ...)
64
#endif
65

  
58 66
#define KERNEL_LOAD_ADDR     0x00404000
59 67
#define CMDLINE_ADDR         0x003ff000
60 68
#define INITRD_LOAD_ADDR     0x00300000
......
282 290
    }
283 291
}
284 292

  
293
static void cpu_kick_irq(CPUState *env)
294
{
295
    env->halted = 0;
296
    cpu_check_irqs(env);
297
}
298

  
285 299
static void cpu_set_irq(void *opaque, int irq, int level)
286 300
{
287 301
    CPUState *env = opaque;
......
303 317
    uint64_t prom_addr;
304 318
} ResetData;
305 319

  
320
void cpu_put_timer(QEMUFile *f, CPUTimer *s)
321
{
322
    qemu_put_be32s(f, &s->frequency);
323
    qemu_put_be32s(f, &s->disabled);
324
    qemu_put_be64s(f, &s->disabled_mask);
325
    qemu_put_sbe64s(f, &s->clock_offset);
326

  
327
    qemu_put_timer(f, s->qtimer);
328
}
329

  
330
void cpu_get_timer(QEMUFile *f, CPUTimer *s)
331
{
332
    qemu_get_be32s(f, &s->frequency);
333
    qemu_get_be32s(f, &s->disabled);
334
    qemu_get_be64s(f, &s->disabled_mask);
335
    qemu_get_sbe64s(f, &s->clock_offset);
336

  
337
    qemu_get_timer(f, s->qtimer);
338
}
339

  
340
static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
341
                                  QEMUBHFunc *cb, uint32_t frequency,
342
                                  uint64_t disabled_mask)
343
{
344
    CPUTimer *timer = qemu_mallocz(sizeof (CPUTimer));
345

  
346
    timer->name = name;
347
    timer->frequency = frequency;
348
    timer->disabled_mask = disabled_mask;
349

  
350
    timer->disabled = 1;
351
    timer->clock_offset = qemu_get_clock(vm_clock);
352

  
353
    timer->qtimer = qemu_new_timer(vm_clock, cb, env);
354

  
355
    return timer;
356
}
357

  
358
static void cpu_timer_reset(CPUTimer *timer)
359
{
360
    timer->disabled = 1;
361
    timer->clock_offset = qemu_get_clock(vm_clock);
362

  
363
    qemu_del_timer(timer->qtimer);
364
}
365

  
306 366
static void main_cpu_reset(void *opaque)
307 367
{
308 368
    ResetData *s = (ResetData *)opaque;
......
310 370
    static unsigned int nr_resets;
311 371

  
312 372
    cpu_reset(env);
313
    env->tick_cmpr = TICK_INT_DIS | 0;
314
    ptimer_set_limit(env->tick, TICK_MAX, 1);
315
    ptimer_run(env->tick, 1);
316
    env->stick_cmpr = TICK_INT_DIS | 0;
317
    ptimer_set_limit(env->stick, TICK_MAX, 1);
318
    ptimer_run(env->stick, 1);
319
    env->hstick_cmpr = TICK_INT_DIS | 0;
320
    ptimer_set_limit(env->hstick, TICK_MAX, 1);
321
    ptimer_run(env->hstick, 1);
373

  
374
    cpu_timer_reset(env->tick);
375
    cpu_timer_reset(env->stick);
376
    cpu_timer_reset(env->hstick);
377

  
322 378
    env->gregs[1] = 0; // Memory start
323 379
    env->gregs[2] = ram_size; // Memory size
324 380
    env->gregs[3] = 0; // Machine description XXX
......
335 391
{
336 392
    CPUState *env = opaque;
337 393

  
338
    if (!(env->tick_cmpr & TICK_INT_DIS)) {
339
        env->softint |= SOFTINT_TIMER;
340
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
394
    CPUTimer* timer = env->tick;
395

  
396
    if (timer->disabled) {
397
        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
398
        return;
399
    } else {
400
        CPUIRQ_DPRINTF("tick: fire\n");
341 401
    }
402

  
403
    env->softint |= SOFTINT_TIMER;
404
    cpu_kick_irq(env);
342 405
}
343 406

  
344 407
static void stick_irq(void *opaque)
345 408
{
346 409
    CPUState *env = opaque;
347 410

  
348
    if (!(env->stick_cmpr & TICK_INT_DIS)) {
349
        env->softint |= SOFTINT_STIMER;
350
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
411
    CPUTimer* timer = env->stick;
412

  
413
    if (timer->disabled) {
414
        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
415
        return;
416
    } else {
417
        CPUIRQ_DPRINTF("stick: fire\n");
351 418
    }
419

  
420
    env->softint |= SOFTINT_STIMER;
421
    cpu_kick_irq(env);
352 422
}
353 423

  
354 424
static void hstick_irq(void *opaque)
355 425
{
356 426
    CPUState *env = opaque;
357 427

  
358
    if (!(env->hstick_cmpr & TICK_INT_DIS)) {
359
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
428
    CPUTimer* timer = env->hstick;
429

  
430
    if (timer->disabled) {
431
        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
432
        return;
433
    } else {
434
        CPUIRQ_DPRINTF("hstick: fire\n");
360 435
    }
436

  
437
    env->softint |= SOFTINT_STIMER;
438
    cpu_kick_irq(env);
439
}
440

  
441
static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
442
{
443
    return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
444
}
445

  
446
static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
447
{
448
    return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
361 449
}
362 450

  
363
void cpu_tick_set_count(void *opaque, uint64_t count)
451
void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
364 452
{
365
    ptimer_set_count(opaque, -count);
453
    uint64_t real_count = count & ~timer->disabled_mask;
454
    uint64_t disabled_bit = count & timer->disabled_mask;
455

  
456
    int64_t vm_clock_offset = qemu_get_clock(vm_clock) -
457
                    cpu_to_timer_ticks(real_count, timer->frequency);
458

  
459
    TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
460
                  timer->name, real_count,
461
                  timer->disabled?"disabled":"enabled", timer);
462

  
463
    timer->disabled = disabled_bit ? 1 : 0;
464
    timer->clock_offset = vm_clock_offset;
366 465
}
367 466

  
368
uint64_t cpu_tick_get_count(void *opaque)
467
uint64_t cpu_tick_get_count(CPUTimer *timer)
369 468
{
370
    return -ptimer_get_count(opaque);
469
    uint64_t real_count = timer_to_cpu_ticks(
470
                    qemu_get_clock(vm_clock) - timer->clock_offset,
471
                    timer->frequency);
472

  
473
    TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
474
           timer->name, real_count,
475
           timer->disabled?"disabled":"enabled", timer);
476

  
477
    if (timer->disabled)
478
        real_count |= timer->disabled_mask;
479

  
480
    return real_count;
371 481
}
372 482

  
373
void cpu_tick_set_limit(void *opaque, uint64_t limit)
483
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
374 484
{
375
    ptimer_set_limit(opaque, -limit, 0);
485
    int64_t now = qemu_get_clock(vm_clock);
486

  
487
    uint64_t real_limit = limit & ~timer->disabled_mask;
488
    timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
489

  
490
    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
491
                    timer->clock_offset;
492

  
493
    if (expires < now) {
494
        expires = now + 1;
495
    }
496

  
497
    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
498
                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
499
                  timer->name, real_limit,
500
                  timer->disabled?"disabled":"enabled",
501
                  timer, limit,
502
                  timer_to_cpu_ticks(now - timer->clock_offset,
503
                                     timer->frequency),
504
                  timer_to_cpu_ticks(expires - now, timer->frequency));
505

  
506
    if (!real_limit) {
507
        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
508
                timer->name);
509
        qemu_del_timer(timer->qtimer);
510
    } else if (timer->disabled) {
511
        qemu_del_timer(timer->qtimer);
512
    } else {
513
        qemu_mod_timer(timer->qtimer, expires);
514
    }
376 515
}
377 516

  
378 517
static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
......
559 698
static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
560 699
{
561 700
    CPUState *env;
562
    QEMUBH *bh;
563 701
    ResetData *reset_info;
564 702

  
703
    uint32_t   tick_frequency = 100*1000000;
704
    uint32_t  stick_frequency = 100*1000000;
705
    uint32_t hstick_frequency = 100*1000000;
706

  
565 707
    if (!cpu_model)
566 708
        cpu_model = hwdef->default_cpu_model;
567 709
    env = cpu_init(cpu_model);
......
569 711
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
570 712
        exit(1);
571 713
    }
572
    bh = qemu_bh_new(tick_irq, env);
573
    env->tick = ptimer_init(bh);
574
    ptimer_set_period(env->tick, 1ULL);
575 714

  
576
    bh = qemu_bh_new(stick_irq, env);
577
    env->stick = ptimer_init(bh);
578
    ptimer_set_period(env->stick, 1ULL);
715
    env->tick = cpu_timer_create("tick", env, tick_irq,
716
                                  tick_frequency, TICK_NPT_MASK);
717

  
718
    env->stick = cpu_timer_create("stick", env, stick_irq,
719
                                   stick_frequency, TICK_INT_DIS);
579 720

  
580
    bh = qemu_bh_new(hstick_irq, env);
581
    env->hstick = ptimer_init(bh);
582
    ptimer_set_period(env->hstick, 1ULL);
721
    env->hstick = cpu_timer_create("hstick", env, hstick_irq,
722
                                    hstick_frequency, TICK_INT_DIS);
583 723

  
584 724
    reset_info = qemu_mallocz(sizeof(ResetData));
585 725
    reset_info->env = env;
b/target-sparc/cpu.h
292 292
    uint64_t tte;
293 293
} SparcTLBEntry;
294 294

  
295
struct CPUTimer
296
{
297
    const char *name;
298
    uint32_t    frequency;
299
    uint32_t    disabled;
300
    uint64_t    disabled_mask;
301
    int64_t     clock_offset;
302
    struct QEMUTimer  *qtimer;
303
};
304

  
305
typedef struct CPUTimer CPUTimer;
306

  
307
struct QEMUFile;
308
void cpu_put_timer(struct QEMUFile *f, CPUTimer *s);
309
void cpu_get_timer(struct QEMUFile *f, CPUTimer *s);
310

  
295 311
typedef struct CPUSPARCState {
296 312
    target_ulong gregs[8]; /* general registers */
297 313
    target_ulong *regwptr; /* pointer to current register window */
......
393 409
    uint64_t mgregs[8]; /* mmu general registers */
394 410
    uint64_t fprs;
395 411
    uint64_t tick_cmpr, stick_cmpr;
396
    void *tick, *stick;
412
    CPUTimer *tick, *stick;
397 413
#define TICK_NPT_MASK        0x8000000000000000ULL
398 414
#define TICK_INT_DIS         0x8000000000000000ULL
399 415
    uint64_t gsr;
400 416
    uint32_t gl; // UA2005
401 417
    /* UA 2005 hyperprivileged registers */
402 418
    uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr;
403
    void *hstick; // UA 2005
419
    CPUTimer *hstick; // UA 2005
404 420
    uint32_t softint;
405 421
#define SOFTINT_TIMER   1
406 422
#define SOFTINT_STIMER  (1 << 16)
......
536 552
#define cpu_signal_handler cpu_sparc_signal_handler
537 553
#define cpu_list sparc_cpu_list
538 554

  
539
#define CPU_SAVE_VERSION 5
555
#define CPU_SAVE_VERSION 6
540 556

  
541 557
/* MMU modes definitions */
542 558
#define MMU_MODE0_SUFFIX _user
......
615 631

  
616 632
#ifdef TARGET_SPARC64
617 633
/* sun4u.c */
618
void cpu_tick_set_count(void *opaque, uint64_t count);
619
uint64_t cpu_tick_get_count(void *opaque);
620
void cpu_tick_set_limit(void *opaque, uint64_t limit);
634
void cpu_tick_set_count(CPUTimer *timer, uint64_t count);
635
uint64_t cpu_tick_get_count(CPUTimer *timer);
636
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
621 637
trap_state* cpu_tsptr(CPUState* env);
622 638
#endif
623 639

  
b/target-sparc/machine.c
84 84
    qemu_put_be64s(f, &env->fprs);
85 85
    qemu_put_be64s(f, &env->tick_cmpr);
86 86
    qemu_put_be64s(f, &env->stick_cmpr);
87
    qemu_put_ptimer(f, env->tick);
88
    qemu_put_ptimer(f, env->stick);
87
    cpu_put_timer(f, env->tick);
88
    cpu_put_timer(f, env->stick);
89 89
    qemu_put_be64s(f, &env->gsr);
90 90
    qemu_put_be32s(f, &env->gl);
91 91
    qemu_put_be64s(f, &env->hpstate);
......
96 96
    qemu_put_be64s(f, &env->hver);
97 97
    qemu_put_be64s(f, &env->hstick_cmpr);
98 98
    qemu_put_be64s(f, &env->ssr);
99
    qemu_put_ptimer(f, env->hstick);
99
    cpu_put_timer(f, env->hstick);
100 100
#endif
101 101
}
102 102

  
......
106 106
    int i;
107 107
    uint32_t tmp;
108 108

  
109
    if (version_id != 5)
109
    if (version_id < 6)
110 110
        return -EINVAL;
111 111
    for(i = 0; i < 8; i++)
112 112
        qemu_get_betls(f, &env->gregs[i]);
......
180 180
    qemu_get_be64s(f, &env->fprs);
181 181
    qemu_get_be64s(f, &env->tick_cmpr);
182 182
    qemu_get_be64s(f, &env->stick_cmpr);
183
    qemu_get_ptimer(f, env->tick);
184
    qemu_get_ptimer(f, env->stick);
183
    cpu_get_timer(f, env->tick);
184
    cpu_get_timer(f, env->stick);
185 185
    qemu_get_be64s(f, &env->gsr);
186 186
    qemu_get_be32s(f, &env->gl);
187 187
    qemu_get_be64s(f, &env->hpstate);
......
192 192
    qemu_get_be64s(f, &env->hver);
193 193
    qemu_get_be64s(f, &env->hstick_cmpr);
194 194
    qemu_get_be64s(f, &env->ssr);
195
    qemu_get_ptimer(f, env->hstick);
195
    cpu_get_timer(f, env->hstick);
196 196
#endif
197 197
    tlb_flush(env, 1);
198 198
    return 0;

Also available in: Unified diff