Commit dbdd25065e90ba78c01b03d238785f25476c04a1
1 parent
d68f1306
Implement time-base start/stop helpers.
Implement PowerPC 6xx time-base enable input pin. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3394 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
92 additions
and
29 deletions
hw/ppc.c
| @@ -30,6 +30,9 @@ | @@ -30,6 +30,9 @@ | ||
| 30 | extern FILE *logfile; | 30 | extern FILE *logfile; |
| 31 | extern int loglevel; | 31 | extern int loglevel; |
| 32 | 32 | ||
| 33 | +static void cpu_ppc_tb_stop (CPUState *env); | ||
| 34 | +static void cpu_ppc_tb_start (CPUState *env); | ||
| 35 | + | ||
| 33 | static void ppc_set_irq (CPUState *env, int n_IRQ, int level) | 36 | static void ppc_set_irq (CPUState *env, int n_IRQ, int level) |
| 34 | { | 37 | { |
| 35 | if (level) { | 38 | if (level) { |
| @@ -65,6 +68,19 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) | @@ -65,6 +68,19 @@ static void ppc6xx_set_irq (void *opaque, int pin, int level) | ||
| 65 | /* Don't generate spurious events */ | 68 | /* Don't generate spurious events */ |
| 66 | if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { | 69 | if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { |
| 67 | switch (pin) { | 70 | switch (pin) { |
| 71 | + case PPC6xx_INPUT_TBEN: | ||
| 72 | + /* Level sensitive - active high */ | ||
| 73 | +#if defined(PPC_DEBUG_IRQ) | ||
| 74 | + if (loglevel & CPU_LOG_INT) { | ||
| 75 | + fprintf(logfile, "%s: %s the time base\n", | ||
| 76 | + __func__, level ? "start" : "stop"); | ||
| 77 | + } | ||
| 78 | +#endif | ||
| 79 | + if (level) { | ||
| 80 | + cpu_ppc_tb_start(env); | ||
| 81 | + } else { | ||
| 82 | + cpu_ppc_tb_stop(env); | ||
| 83 | + } | ||
| 68 | case PPC6xx_INPUT_INT: | 84 | case PPC6xx_INPUT_INT: |
| 69 | /* Level sensitive - active high */ | 85 | /* Level sensitive - active high */ |
| 70 | #if defined(PPC_DEBUG_IRQ) | 86 | #if defined(PPC_DEBUG_IRQ) |
| @@ -402,11 +418,12 @@ void ppc40x_irq_init (CPUState *env) | @@ -402,11 +418,12 @@ void ppc40x_irq_init (CPUState *env) | ||
| 402 | /* PowerPC time base and decrementer emulation */ | 418 | /* PowerPC time base and decrementer emulation */ |
| 403 | struct ppc_tb_t { | 419 | struct ppc_tb_t { |
| 404 | /* Time base management */ | 420 | /* Time base management */ |
| 405 | - int64_t tb_offset; /* Compensation */ | ||
| 406 | - int64_t atb_offset; /* Compensation */ | ||
| 407 | - uint32_t tb_freq; /* TB frequency */ | 421 | + int64_t tb_offset; /* Compensation */ |
| 422 | + int64_t atb_offset; /* Compensation */ | ||
| 423 | + uint32_t tb_freq; /* TB frequency */ | ||
| 408 | /* Decrementer management */ | 424 | /* Decrementer management */ |
| 409 | - uint64_t decr_next; /* Tick for next decr interrupt */ | 425 | + uint64_t decr_next; /* Tick for next decr interrupt */ |
| 426 | + uint32_t decr_freq; /* decrementer frequency */ | ||
| 410 | struct QEMUTimer *decr_timer; | 427 | struct QEMUTimer *decr_timer; |
| 411 | #if defined(TARGET_PPC64H) | 428 | #if defined(TARGET_PPC64H) |
| 412 | /* Hypervisor decrementer management */ | 429 | /* Hypervisor decrementer management */ |
| @@ -418,12 +435,11 @@ struct ppc_tb_t { | @@ -418,12 +435,11 @@ struct ppc_tb_t { | ||
| 418 | void *opaque; | 435 | void *opaque; |
| 419 | }; | 436 | }; |
| 420 | 437 | ||
| 421 | -static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, | 438 | +static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk, |
| 422 | int64_t tb_offset) | 439 | int64_t tb_offset) |
| 423 | { | 440 | { |
| 424 | /* TB time in tb periods */ | 441 | /* TB time in tb periods */ |
| 425 | - return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, | ||
| 426 | - tb_env->tb_freq, ticks_per_sec); | 442 | + return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset; |
| 427 | } | 443 | } |
| 428 | 444 | ||
| 429 | uint32_t cpu_ppc_load_tbl (CPUState *env) | 445 | uint32_t cpu_ppc_load_tbl (CPUState *env) |
| @@ -431,7 +447,7 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) | @@ -431,7 +447,7 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) | ||
| 431 | ppc_tb_t *tb_env = env->tb_env; | 447 | ppc_tb_t *tb_env = env->tb_env; |
| 432 | uint64_t tb; | 448 | uint64_t tb; |
| 433 | 449 | ||
| 434 | - tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | 450 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset); |
| 435 | #if defined(PPC_DEBUG_TB) | 451 | #if defined(PPC_DEBUG_TB) |
| 436 | if (loglevel != 0) { | 452 | if (loglevel != 0) { |
| 437 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | 453 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| @@ -446,7 +462,7 @@ static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env) | @@ -446,7 +462,7 @@ static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env) | ||
| 446 | ppc_tb_t *tb_env = env->tb_env; | 462 | ppc_tb_t *tb_env = env->tb_env; |
| 447 | uint64_t tb; | 463 | uint64_t tb; |
| 448 | 464 | ||
| 449 | - tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | 465 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset); |
| 450 | #if defined(PPC_DEBUG_TB) | 466 | #if defined(PPC_DEBUG_TB) |
| 451 | if (loglevel != 0) { | 467 | if (loglevel != 0) { |
| 452 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | 468 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| @@ -461,12 +477,11 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | @@ -461,12 +477,11 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | ||
| 461 | return _cpu_ppc_load_tbu(env); | 477 | return _cpu_ppc_load_tbu(env); |
| 462 | } | 478 | } |
| 463 | 479 | ||
| 464 | -static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, | 480 | +static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk, |
| 465 | int64_t *tb_offsetp, | 481 | int64_t *tb_offsetp, |
| 466 | uint64_t value) | 482 | uint64_t value) |
| 467 | { | 483 | { |
| 468 | - *tb_offsetp = muldiv64(value, ticks_per_sec, tb_env->tb_freq) | ||
| 469 | - - qemu_get_clock(vm_clock); | 484 | + *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec); |
| 470 | #ifdef PPC_DEBUG_TB | 485 | #ifdef PPC_DEBUG_TB |
| 471 | if (loglevel != 0) { | 486 | if (loglevel != 0) { |
| 472 | fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, | 487 | fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, |
| @@ -480,9 +495,10 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | @@ -480,9 +495,10 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | ||
| 480 | ppc_tb_t *tb_env = env->tb_env; | 495 | ppc_tb_t *tb_env = env->tb_env; |
| 481 | uint64_t tb; | 496 | uint64_t tb; |
| 482 | 497 | ||
| 483 | - tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | 498 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset); |
| 484 | tb &= 0xFFFFFFFF00000000ULL; | 499 | tb &= 0xFFFFFFFF00000000ULL; |
| 485 | - cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, tb | (uint64_t)value); | 500 | + cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock), |
| 501 | + &tb_env->tb_offset, tb | (uint64_t)value); | ||
| 486 | } | 502 | } |
| 487 | 503 | ||
| 488 | static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value) | 504 | static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value) |
| @@ -490,10 +506,10 @@ static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value) | @@ -490,10 +506,10 @@ static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value) | ||
| 490 | ppc_tb_t *tb_env = env->tb_env; | 506 | ppc_tb_t *tb_env = env->tb_env; |
| 491 | uint64_t tb; | 507 | uint64_t tb; |
| 492 | 508 | ||
| 493 | - tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | 509 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset); |
| 494 | tb &= 0x00000000FFFFFFFFULL; | 510 | tb &= 0x00000000FFFFFFFFULL; |
| 495 | - cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, | ||
| 496 | - ((uint64_t)value << 32) | tb); | 511 | + cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock), |
| 512 | + &tb_env->tb_offset, ((uint64_t)value << 32) | tb); | ||
| 497 | } | 513 | } |
| 498 | 514 | ||
| 499 | void cpu_ppc_store_tbu (CPUState *env, uint32_t value) | 515 | void cpu_ppc_store_tbu (CPUState *env, uint32_t value) |
| @@ -506,7 +522,7 @@ uint32_t cpu_ppc_load_atbl (CPUState *env) | @@ -506,7 +522,7 @@ uint32_t cpu_ppc_load_atbl (CPUState *env) | ||
| 506 | ppc_tb_t *tb_env = env->tb_env; | 522 | ppc_tb_t *tb_env = env->tb_env; |
| 507 | uint64_t tb; | 523 | uint64_t tb; |
| 508 | 524 | ||
| 509 | - tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | 525 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset); |
| 510 | #if defined(PPC_DEBUG_TB) | 526 | #if defined(PPC_DEBUG_TB) |
| 511 | if (loglevel != 0) { | 527 | if (loglevel != 0) { |
| 512 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | 528 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| @@ -521,7 +537,7 @@ uint32_t cpu_ppc_load_atbu (CPUState *env) | @@ -521,7 +537,7 @@ uint32_t cpu_ppc_load_atbu (CPUState *env) | ||
| 521 | ppc_tb_t *tb_env = env->tb_env; | 537 | ppc_tb_t *tb_env = env->tb_env; |
| 522 | uint64_t tb; | 538 | uint64_t tb; |
| 523 | 539 | ||
| 524 | - tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | 540 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset); |
| 525 | #if defined(PPC_DEBUG_TB) | 541 | #if defined(PPC_DEBUG_TB) |
| 526 | if (loglevel != 0) { | 542 | if (loglevel != 0) { |
| 527 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | 543 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| @@ -536,9 +552,10 @@ void cpu_ppc_store_atbl (CPUState *env, uint32_t value) | @@ -536,9 +552,10 @@ void cpu_ppc_store_atbl (CPUState *env, uint32_t value) | ||
| 536 | ppc_tb_t *tb_env = env->tb_env; | 552 | ppc_tb_t *tb_env = env->tb_env; |
| 537 | uint64_t tb; | 553 | uint64_t tb; |
| 538 | 554 | ||
| 539 | - tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | 555 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset); |
| 540 | tb &= 0xFFFFFFFF00000000ULL; | 556 | tb &= 0xFFFFFFFF00000000ULL; |
| 541 | - cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, tb | (uint64_t)value); | 557 | + cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock), |
| 558 | + &tb_env->atb_offset, tb | (uint64_t)value); | ||
| 542 | } | 559 | } |
| 543 | 560 | ||
| 544 | void cpu_ppc_store_atbu (CPUState *env, uint32_t value) | 561 | void cpu_ppc_store_atbu (CPUState *env, uint32_t value) |
| @@ -546,10 +563,53 @@ void cpu_ppc_store_atbu (CPUState *env, uint32_t value) | @@ -546,10 +563,53 @@ void cpu_ppc_store_atbu (CPUState *env, uint32_t value) | ||
| 546 | ppc_tb_t *tb_env = env->tb_env; | 563 | ppc_tb_t *tb_env = env->tb_env; |
| 547 | uint64_t tb; | 564 | uint64_t tb; |
| 548 | 565 | ||
| 549 | - tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | 566 | + tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset); |
| 550 | tb &= 0x00000000FFFFFFFFULL; | 567 | tb &= 0x00000000FFFFFFFFULL; |
| 551 | - cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, | ||
| 552 | - ((uint64_t)value << 32) | tb); | 568 | + cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock), |
| 569 | + &tb_env->atb_offset, ((uint64_t)value << 32) | tb); | ||
| 570 | +} | ||
| 571 | + | ||
| 572 | +static void cpu_ppc_tb_stop (CPUState *env) | ||
| 573 | +{ | ||
| 574 | + ppc_tb_t *tb_env = env->tb_env; | ||
| 575 | + uint64_t tb, atb, vmclk; | ||
| 576 | + | ||
| 577 | + /* If the time base is already frozen, do nothing */ | ||
| 578 | + if (tb_env->tb_freq != 0) { | ||
| 579 | + vmclk = qemu_get_clock(vm_clock); | ||
| 580 | + /* Get the time base */ | ||
| 581 | + tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset); | ||
| 582 | + /* Get the alternate time base */ | ||
| 583 | + atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset); | ||
| 584 | + /* Store the time base value (ie compute the current offset) */ | ||
| 585 | + cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb); | ||
| 586 | + /* Store the alternate time base value (compute the current offset) */ | ||
| 587 | + cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb); | ||
| 588 | + /* Set the time base frequency to zero */ | ||
| 589 | + tb_env->tb_freq = 0; | ||
| 590 | + /* Now, the time bases are frozen to tb_offset / atb_offset value */ | ||
| 591 | + } | ||
| 592 | +} | ||
| 593 | + | ||
| 594 | +static void cpu_ppc_tb_start (CPUState *env) | ||
| 595 | +{ | ||
| 596 | + ppc_tb_t *tb_env = env->tb_env; | ||
| 597 | + uint64_t tb, atb, vmclk; | ||
| 598 | + | ||
| 599 | + /* If the time base is not frozen, do nothing */ | ||
| 600 | + if (tb_env->tb_freq == 0) { | ||
| 601 | + vmclk = qemu_get_clock(vm_clock); | ||
| 602 | + /* Get the time base from tb_offset */ | ||
| 603 | + tb = tb_env->tb_offset; | ||
| 604 | + /* Get the alternate time base from atb_offset */ | ||
| 605 | + atb = tb_env->atb_offset; | ||
| 606 | + /* Restore the tb frequency from the decrementer frequency */ | ||
| 607 | + tb_env->tb_freq = tb_env->decr_freq; | ||
| 608 | + /* Store the time base value */ | ||
| 609 | + cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb); | ||
| 610 | + /* Store the alternate time base value */ | ||
| 611 | + cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb); | ||
| 612 | + } | ||
| 553 | } | 613 | } |
| 554 | 614 | ||
| 555 | static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env, | 615 | static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env, |
| @@ -561,9 +621,9 @@ static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env, | @@ -561,9 +621,9 @@ static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env, | ||
| 561 | 621 | ||
| 562 | diff = tb_env->decr_next - qemu_get_clock(vm_clock); | 622 | diff = tb_env->decr_next - qemu_get_clock(vm_clock); |
| 563 | if (diff >= 0) | 623 | if (diff >= 0) |
| 564 | - decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec); | 624 | + decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec); |
| 565 | else | 625 | else |
| 566 | - decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec); | 626 | + decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec); |
| 567 | #if defined(PPC_DEBUG_TB) | 627 | #if defined(PPC_DEBUG_TB) |
| 568 | if (loglevel != 0) { | 628 | if (loglevel != 0) { |
| 569 | fprintf(logfile, "%s: 0x%08x\n", __func__, decr); | 629 | fprintf(logfile, "%s: 0x%08x\n", __func__, decr); |
| @@ -639,7 +699,7 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp, | @@ -639,7 +699,7 @@ static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp, | ||
| 639 | } | 699 | } |
| 640 | #endif | 700 | #endif |
| 641 | now = qemu_get_clock(vm_clock); | 701 | now = qemu_get_clock(vm_clock); |
| 642 | - next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq); | 702 | + next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq); |
| 643 | if (is_excp) | 703 | if (is_excp) |
| 644 | next += *nextp - now; | 704 | next += *nextp - now; |
| 645 | if (next == now) | 705 | if (next == now) |
| @@ -708,6 +768,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) | @@ -708,6 +768,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) | ||
| 708 | ppc_tb_t *tb_env = env->tb_env; | 768 | ppc_tb_t *tb_env = env->tb_env; |
| 709 | 769 | ||
| 710 | tb_env->tb_freq = freq; | 770 | tb_env->tb_freq = freq; |
| 771 | + tb_env->decr_freq = freq; | ||
| 711 | /* There is a bug in Linux 2.4 kernels: | 772 | /* There is a bug in Linux 2.4 kernels: |
| 712 | * if a decrementer exception is pending when it enables msr_ee at startup, | 773 | * if a decrementer exception is pending when it enables msr_ee at startup, |
| 713 | * it's not ready to handle it... | 774 | * it's not ready to handle it... |
| @@ -848,7 +909,7 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp) | @@ -848,7 +909,7 @@ static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp) | ||
| 848 | #endif | 909 | #endif |
| 849 | now = qemu_get_clock(vm_clock); | 910 | now = qemu_get_clock(vm_clock); |
| 850 | next = now + muldiv64(ppcemb_timer->pit_reload, | 911 | next = now + muldiv64(ppcemb_timer->pit_reload, |
| 851 | - ticks_per_sec, tb_env->tb_freq); | 912 | + ticks_per_sec, tb_env->decr_freq); |
| 852 | if (is_excp) | 913 | if (is_excp) |
| 853 | next += tb_env->decr_next - now; | 914 | next += tb_env->decr_next - now; |
| 854 | if (next == now) | 915 | if (next == now) |
| @@ -912,7 +973,7 @@ static void cpu_4xx_wdt_cb (void *opaque) | @@ -912,7 +973,7 @@ static void cpu_4xx_wdt_cb (void *opaque) | ||
| 912 | /* Cannot occur, but makes gcc happy */ | 973 | /* Cannot occur, but makes gcc happy */ |
| 913 | return; | 974 | return; |
| 914 | } | 975 | } |
| 915 | - next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq); | 976 | + next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq); |
| 916 | if (next == now) | 977 | if (next == now) |
| 917 | next++; | 978 | next++; |
| 918 | #ifdef PPC_DEBUG_TB | 979 | #ifdef PPC_DEBUG_TB |
| @@ -1014,6 +1075,7 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq) | @@ -1014,6 +1075,7 @@ static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq) | ||
| 1014 | } | 1075 | } |
| 1015 | #endif | 1076 | #endif |
| 1016 | tb_env->tb_freq = freq; | 1077 | tb_env->tb_freq = freq; |
| 1078 | + tb_env->decr_freq = freq; | ||
| 1017 | /* XXX: we should also update all timers */ | 1079 | /* XXX: we should also update all timers */ |
| 1018 | } | 1080 | } |
| 1019 | 1081 | ||
| @@ -1029,6 +1091,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq) | @@ -1029,6 +1091,7 @@ clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq) | ||
| 1029 | env->tb_env = tb_env; | 1091 | env->tb_env = tb_env; |
| 1030 | ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t)); | 1092 | ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t)); |
| 1031 | tb_env->tb_freq = freq; | 1093 | tb_env->tb_freq = freq; |
| 1094 | + tb_env->decr_freq = freq; | ||
| 1032 | tb_env->opaque = ppcemb_timer; | 1095 | tb_env->opaque = ppcemb_timer; |
| 1033 | #ifdef PPC_DEBUG_TB | 1096 | #ifdef PPC_DEBUG_TB |
| 1034 | if (loglevel != 0) { | 1097 | if (loglevel != 0) { |