2 * QEMU generic PowerPC hardware System Emulator
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 //#define PPC_DEBUG_IRQ
28 //#define PPC_DEBUG_TB
33 static void cpu_ppc_tb_stop (CPUState *env);
34 static void cpu_ppc_tb_start (CPUState *env);
36 static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
39 env->pending_interrupts |= 1 << n_IRQ;
40 cpu_interrupt(env, CPU_INTERRUPT_HARD);
42 env->pending_interrupts &= ~(1 << n_IRQ);
43 if (env->pending_interrupts == 0)
44 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
46 #if defined(PPC_DEBUG_IRQ)
47 if (loglevel & CPU_LOG_INT) {
48 fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
49 __func__, env, n_IRQ, level,
50 env->pending_interrupts, env->interrupt_request);
55 /* PowerPC 6xx / 7xx internal IRQ controller */
56 static void ppc6xx_set_irq (void *opaque, int pin, int level)
58 CPUState *env = opaque;
61 #if defined(PPC_DEBUG_IRQ)
62 if (loglevel & CPU_LOG_INT) {
63 fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
67 cur_level = (env->irq_input_state >> pin) & 1;
68 /* Don't generate spurious events */
69 if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
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");
80 cpu_ppc_tb_start(env);
84 case PPC6xx_INPUT_INT:
85 /* Level sensitive - active high */
86 #if defined(PPC_DEBUG_IRQ)
87 if (loglevel & CPU_LOG_INT) {
88 fprintf(logfile, "%s: set the external IRQ state to %d\n",
92 ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
94 case PPC6xx_INPUT_SMI:
95 /* Level sensitive - active high */
96 #if defined(PPC_DEBUG_IRQ)
97 if (loglevel & CPU_LOG_INT) {
98 fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
102 ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
104 case PPC6xx_INPUT_MCP:
105 /* Negative edge sensitive */
106 /* XXX: TODO: actual reaction may depends on HID0 status
107 * 603/604/740/750: check HID0[EMCP]
109 if (cur_level == 1 && level == 0) {
110 #if defined(PPC_DEBUG_IRQ)
111 if (loglevel & CPU_LOG_INT) {
112 fprintf(logfile, "%s: raise machine check state\n",
116 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
119 case PPC6xx_INPUT_CKSTP_IN:
120 /* Level sensitive - active low */
121 /* XXX: TODO: relay the signal to CKSTP_OUT pin */
122 /* XXX: Note that the only way to restart the CPU is to reset it */
124 #if defined(PPC_DEBUG_IRQ)
125 if (loglevel & CPU_LOG_INT) {
126 fprintf(logfile, "%s: stop the CPU\n", __func__);
132 case PPC6xx_INPUT_HRESET:
133 /* Level sensitive - active low */
136 #if defined(PPC_DEBUG_IRQ)
137 if (loglevel & CPU_LOG_INT) {
138 fprintf(logfile, "%s: reset the CPU\n", __func__);
145 case PPC6xx_INPUT_SRESET:
146 #if defined(PPC_DEBUG_IRQ)
147 if (loglevel & CPU_LOG_INT) {
148 fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
152 ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
155 /* Unknown pin - do nothing */
156 #if defined(PPC_DEBUG_IRQ)
157 if (loglevel & CPU_LOG_INT) {
158 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
164 env->irq_input_state |= 1 << pin;
166 env->irq_input_state &= ~(1 << pin);
170 void ppc6xx_irq_init (CPUState *env)
172 env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
175 #if defined(TARGET_PPC64)
176 /* PowerPC 970 internal IRQ controller */
177 static void ppc970_set_irq (void *opaque, int pin, int level)
179 CPUState *env = opaque;
182 #if defined(PPC_DEBUG_IRQ)
183 if (loglevel & CPU_LOG_INT) {
184 fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
188 cur_level = (env->irq_input_state >> pin) & 1;
189 /* Don't generate spurious events */
190 if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
192 case PPC970_INPUT_INT:
193 /* Level sensitive - active high */
194 #if defined(PPC_DEBUG_IRQ)
195 if (loglevel & CPU_LOG_INT) {
196 fprintf(logfile, "%s: set the external IRQ state to %d\n",
200 ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
202 case PPC970_INPUT_THINT:
203 /* Level sensitive - active high */
204 #if defined(PPC_DEBUG_IRQ)
205 if (loglevel & CPU_LOG_INT) {
206 fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
210 ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
212 case PPC970_INPUT_MCP:
213 /* Negative edge sensitive */
214 /* XXX: TODO: actual reaction may depends on HID0 status
215 * 603/604/740/750: check HID0[EMCP]
217 if (cur_level == 1 && level == 0) {
218 #if defined(PPC_DEBUG_IRQ)
219 if (loglevel & CPU_LOG_INT) {
220 fprintf(logfile, "%s: raise machine check state\n",
224 ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
227 case PPC970_INPUT_CKSTP:
228 /* Level sensitive - active low */
229 /* XXX: TODO: relay the signal to CKSTP_OUT pin */
231 #if defined(PPC_DEBUG_IRQ)
232 if (loglevel & CPU_LOG_INT) {
233 fprintf(logfile, "%s: stop the CPU\n", __func__);
238 #if defined(PPC_DEBUG_IRQ)
239 if (loglevel & CPU_LOG_INT) {
240 fprintf(logfile, "%s: restart the CPU\n", __func__);
246 case PPC970_INPUT_HRESET:
247 /* Level sensitive - active low */
250 #if defined(PPC_DEBUG_IRQ)
251 if (loglevel & CPU_LOG_INT) {
252 fprintf(logfile, "%s: reset the CPU\n", __func__);
259 case PPC970_INPUT_SRESET:
260 #if defined(PPC_DEBUG_IRQ)
261 if (loglevel & CPU_LOG_INT) {
262 fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
266 ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
268 case PPC970_INPUT_TBEN:
269 #if defined(PPC_DEBUG_IRQ)
270 if (loglevel & CPU_LOG_INT) {
271 fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
278 /* Unknown pin - do nothing */
279 #if defined(PPC_DEBUG_IRQ)
280 if (loglevel & CPU_LOG_INT) {
281 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
287 env->irq_input_state |= 1 << pin;
289 env->irq_input_state &= ~(1 << pin);
293 void ppc970_irq_init (CPUState *env)
295 env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
297 #endif /* defined(TARGET_PPC64) */
299 /* PowerPC 40x internal IRQ controller */
300 static void ppc40x_set_irq (void *opaque, int pin, int level)
302 CPUState *env = opaque;
305 #if defined(PPC_DEBUG_IRQ)
306 if (loglevel & CPU_LOG_INT) {
307 fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
311 cur_level = (env->irq_input_state >> pin) & 1;
312 /* Don't generate spurious events */
313 if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
315 case PPC40x_INPUT_RESET_SYS:
317 #if defined(PPC_DEBUG_IRQ)
318 if (loglevel & CPU_LOG_INT) {
319 fprintf(logfile, "%s: reset the PowerPC system\n",
323 ppc40x_system_reset(env);
326 case PPC40x_INPUT_RESET_CHIP:
328 #if defined(PPC_DEBUG_IRQ)
329 if (loglevel & CPU_LOG_INT) {
330 fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
333 ppc40x_chip_reset(env);
336 case PPC40x_INPUT_RESET_CORE:
337 /* XXX: TODO: update DBSR[MRR] */
339 #if defined(PPC_DEBUG_IRQ)
340 if (loglevel & CPU_LOG_INT) {
341 fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
344 ppc40x_core_reset(env);
347 case PPC40x_INPUT_CINT:
348 /* Level sensitive - active high */
349 #if defined(PPC_DEBUG_IRQ)
350 if (loglevel & CPU_LOG_INT) {
351 fprintf(logfile, "%s: set the critical IRQ state to %d\n",
355 ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
357 case PPC40x_INPUT_INT:
358 /* Level sensitive - active high */
359 #if defined(PPC_DEBUG_IRQ)
360 if (loglevel & CPU_LOG_INT) {
361 fprintf(logfile, "%s: set the external IRQ state to %d\n",
365 ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
367 case PPC40x_INPUT_HALT:
368 /* Level sensitive - active low */
370 #if defined(PPC_DEBUG_IRQ)
371 if (loglevel & CPU_LOG_INT) {
372 fprintf(logfile, "%s: stop the CPU\n", __func__);
377 #if defined(PPC_DEBUG_IRQ)
378 if (loglevel & CPU_LOG_INT) {
379 fprintf(logfile, "%s: restart the CPU\n", __func__);
385 case PPC40x_INPUT_DEBUG:
386 /* Level sensitive - active high */
387 #if defined(PPC_DEBUG_IRQ)
388 if (loglevel & CPU_LOG_INT) {
389 fprintf(logfile, "%s: set the debug pin state to %d\n",
393 ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
396 /* Unknown pin - do nothing */
397 #if defined(PPC_DEBUG_IRQ)
398 if (loglevel & CPU_LOG_INT) {
399 fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
405 env->irq_input_state |= 1 << pin;
407 env->irq_input_state &= ~(1 << pin);
411 void ppc40x_irq_init (CPUState *env)
413 env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
414 env, PPC40x_INPUT_NB);
417 /*****************************************************************************/
418 /* PowerPC time base and decrementer emulation */
420 /* Time base management */
421 int64_t tb_offset; /* Compensation */
422 int64_t atb_offset; /* Compensation */
423 uint32_t tb_freq; /* TB frequency */
424 /* Decrementer management */
425 uint64_t decr_next; /* Tick for next decr interrupt */
426 uint32_t decr_freq; /* decrementer frequency */
427 struct QEMUTimer *decr_timer;
428 #if defined(TARGET_PPC64H)
429 /* Hypervisor decrementer management */
430 uint64_t hdecr_next; /* Tick for next hdecr interrupt */
431 struct QEMUTimer *hdecr_timer;
438 static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
441 /* TB time in tb periods */
442 return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
445 uint32_t cpu_ppc_load_tbl (CPUState *env)
447 ppc_tb_t *tb_env = env->tb_env;
450 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
451 #if defined(PPC_DEBUG_TB)
453 fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
457 return tb & 0xFFFFFFFF;
460 static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
462 ppc_tb_t *tb_env = env->tb_env;
465 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
466 #if defined(PPC_DEBUG_TB)
468 fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
475 uint32_t cpu_ppc_load_tbu (CPUState *env)
477 return _cpu_ppc_load_tbu(env);
480 static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
484 *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
487 fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
493 void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
495 ppc_tb_t *tb_env = env->tb_env;
498 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
499 tb &= 0xFFFFFFFF00000000ULL;
500 cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
501 &tb_env->tb_offset, tb | (uint64_t)value);
504 static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
506 ppc_tb_t *tb_env = env->tb_env;
509 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
510 tb &= 0x00000000FFFFFFFFULL;
511 cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
512 &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
515 void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
517 _cpu_ppc_store_tbu(env, value);
520 uint32_t cpu_ppc_load_atbl (CPUState *env)
522 ppc_tb_t *tb_env = env->tb_env;
525 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
526 #if defined(PPC_DEBUG_TB)
528 fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
532 return tb & 0xFFFFFFFF;
535 uint32_t cpu_ppc_load_atbu (CPUState *env)
537 ppc_tb_t *tb_env = env->tb_env;
540 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
541 #if defined(PPC_DEBUG_TB)
543 fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
550 void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
552 ppc_tb_t *tb_env = env->tb_env;
555 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
556 tb &= 0xFFFFFFFF00000000ULL;
557 cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
558 &tb_env->atb_offset, tb | (uint64_t)value);
561 void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
563 ppc_tb_t *tb_env = env->tb_env;
566 tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
567 tb &= 0x00000000FFFFFFFFULL;
568 cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
569 &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
572 static void cpu_ppc_tb_stop (CPUState *env)
574 ppc_tb_t *tb_env = env->tb_env;
575 uint64_t tb, atb, vmclk;
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 */
590 /* Now, the time bases are frozen to tb_offset / atb_offset value */
594 static void cpu_ppc_tb_start (CPUState *env)
596 ppc_tb_t *tb_env = env->tb_env;
597 uint64_t tb, atb, vmclk;
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);
615 static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
618 ppc_tb_t *tb_env = env->tb_env;
622 diff = tb_env->decr_next - qemu_get_clock(vm_clock);
624 decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
626 decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
627 #if defined(PPC_DEBUG_TB)
629 fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
636 uint32_t cpu_ppc_load_decr (CPUState *env)
638 ppc_tb_t *tb_env = env->tb_env;
640 return _cpu_ppc_load_decr(env, &tb_env->decr_next);
643 #if defined(TARGET_PPC64H)
644 uint32_t cpu_ppc_load_hdecr (CPUState *env)
646 ppc_tb_t *tb_env = env->tb_env;
648 return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
651 uint64_t cpu_ppc_load_purr (CPUState *env)
653 ppc_tb_t *tb_env = env->tb_env;
656 diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
658 return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
660 #endif /* defined(TARGET_PPC64H) */
662 /* When decrementer expires,
663 * all we need to do is generate or queue a CPU exception
665 static always_inline void cpu_ppc_decr_excp (CPUState *env)
670 fprintf(logfile, "raise decrementer exception\n");
673 ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
676 static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
681 fprintf(logfile, "raise decrementer exception\n");
684 ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
687 static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
688 struct QEMUTimer *timer,
689 void (*raise_excp)(CPUState *),
690 uint32_t decr, uint32_t value,
693 ppc_tb_t *tb_env = env->tb_env;
698 fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
701 now = qemu_get_clock(vm_clock);
702 next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
704 next += *nextp - now;
709 qemu_mod_timer(timer, next);
710 /* If we set a negative value and the decrementer was positive,
711 * raise an exception.
713 if ((value & 0x80000000) && !(decr & 0x80000000))
717 static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
718 uint32_t value, int is_excp)
720 ppc_tb_t *tb_env = env->tb_env;
722 __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
723 &cpu_ppc_decr_excp, decr, value, is_excp);
726 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
728 _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
731 static void cpu_ppc_decr_cb (void *opaque)
733 _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
736 #if defined(TARGET_PPC64H)
737 static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
738 uint32_t value, int is_excp)
740 ppc_tb_t *tb_env = env->tb_env;
742 __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
743 &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
746 void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
748 _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
751 static void cpu_ppc_hdecr_cb (void *opaque)
753 _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
756 void cpu_ppc_store_purr (CPUState *env, uint64_t value)
758 ppc_tb_t *tb_env = env->tb_env;
760 tb_env->purr_load = value;
761 tb_env->purr_start = qemu_get_clock(vm_clock);
763 #endif /* defined(TARGET_PPC64H) */
765 static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
767 CPUState *env = opaque;
768 ppc_tb_t *tb_env = env->tb_env;
770 tb_env->tb_freq = freq;
771 tb_env->decr_freq = freq;
772 /* There is a bug in Linux 2.4 kernels:
773 * if a decrementer exception is pending when it enables msr_ee at startup,
774 * it's not ready to handle it...
776 _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
777 #if defined(TARGET_PPC64H)
778 _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
779 cpu_ppc_store_purr(env, 0x0000000000000000ULL);
780 #endif /* defined(TARGET_PPC64H) */
783 /* Set up (once) timebase frequency (in Hz) */
784 clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
788 tb_env = qemu_mallocz(sizeof(ppc_tb_t));
791 env->tb_env = tb_env;
792 /* Create new timer */
793 tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
794 #if defined(TARGET_PPC64H)
795 tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
796 #endif /* defined(TARGET_PPC64H) */
797 cpu_ppc_set_tb_clk(env, freq);
799 return &cpu_ppc_set_tb_clk;
802 /* Specific helpers for POWER & PowerPC 601 RTC */
803 clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
805 return cpu_ppc_tb_init(env, 7812500);
808 void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
810 _cpu_ppc_store_tbu(env, value);
813 uint32_t cpu_ppc601_load_rtcu (CPUState *env)
815 return _cpu_ppc_load_tbu(env);
818 void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
820 cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
823 uint32_t cpu_ppc601_load_rtcl (CPUState *env)
825 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
828 /*****************************************************************************/
829 /* Embedded PowerPC timers */
832 typedef struct ppcemb_timer_t ppcemb_timer_t;
833 struct ppcemb_timer_t {
834 uint64_t pit_reload; /* PIT auto-reload value */
835 uint64_t fit_next; /* Tick for next FIT interrupt */
836 struct QEMUTimer *fit_timer;
837 uint64_t wdt_next; /* Tick for next WDT interrupt */
838 struct QEMUTimer *wdt_timer;
841 /* Fixed interval timer */
842 static void cpu_4xx_fit_cb (void *opaque)
846 ppcemb_timer_t *ppcemb_timer;
850 tb_env = env->tb_env;
851 ppcemb_timer = tb_env->opaque;
852 now = qemu_get_clock(vm_clock);
853 switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
867 /* Cannot occur, but makes gcc happy */
870 next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
873 qemu_mod_timer(ppcemb_timer->fit_timer, next);
874 env->spr[SPR_40x_TSR] |= 1 << 26;
875 if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
876 ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
879 fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
880 (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
881 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
886 /* Programmable interval timer */
887 static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
889 ppcemb_timer_t *ppcemb_timer;
892 ppcemb_timer = tb_env->opaque;
893 if (ppcemb_timer->pit_reload <= 1 ||
894 !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
895 (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
899 fprintf(logfile, "%s: stop PIT\n", __func__);
902 qemu_del_timer(tb_env->decr_timer);
906 fprintf(logfile, "%s: start PIT 0x" REGX "\n",
907 __func__, ppcemb_timer->pit_reload);
910 now = qemu_get_clock(vm_clock);
911 next = now + muldiv64(ppcemb_timer->pit_reload,
912 ticks_per_sec, tb_env->decr_freq);
914 next += tb_env->decr_next - now;
917 qemu_mod_timer(tb_env->decr_timer, next);
918 tb_env->decr_next = next;
922 static void cpu_4xx_pit_cb (void *opaque)
926 ppcemb_timer_t *ppcemb_timer;
929 tb_env = env->tb_env;
930 ppcemb_timer = tb_env->opaque;
931 env->spr[SPR_40x_TSR] |= 1 << 27;
932 if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
933 ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
934 start_stop_pit(env, tb_env, 1);
937 fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
938 "%016" PRIx64 "\n", __func__,
939 (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
940 (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
941 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
942 ppcemb_timer->pit_reload);
948 static void cpu_4xx_wdt_cb (void *opaque)
952 ppcemb_timer_t *ppcemb_timer;
956 tb_env = env->tb_env;
957 ppcemb_timer = tb_env->opaque;
958 now = qemu_get_clock(vm_clock);
959 switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
973 /* Cannot occur, but makes gcc happy */
976 next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
981 fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
982 env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
985 switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
988 qemu_mod_timer(ppcemb_timer->wdt_timer, next);
989 ppcemb_timer->wdt_next = next;
990 env->spr[SPR_40x_TSR] |= 1 << 31;
993 qemu_mod_timer(ppcemb_timer->wdt_timer, next);
994 ppcemb_timer->wdt_next = next;
995 env->spr[SPR_40x_TSR] |= 1 << 30;
996 if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
997 ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
1000 env->spr[SPR_40x_TSR] &= ~0x30000000;
1001 env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1002 switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1006 case 0x1: /* Core reset */
1007 ppc40x_core_reset(env);
1009 case 0x2: /* Chip reset */
1010 ppc40x_chip_reset(env);
1012 case 0x3: /* System reset */
1013 ppc40x_system_reset(env);
1019 void store_40x_pit (CPUState *env, target_ulong val)
1022 ppcemb_timer_t *ppcemb_timer;
1024 tb_env = env->tb_env;
1025 ppcemb_timer = tb_env->opaque;
1027 if (loglevel != 0) {
1028 fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
1031 ppcemb_timer->pit_reload = val;
1032 start_stop_pit(env, tb_env, 0);
1035 target_ulong load_40x_pit (CPUState *env)
1037 return cpu_ppc_load_decr(env);
1040 void store_booke_tsr (CPUState *env, target_ulong val)
1043 if (loglevel != 0) {
1044 fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1047 env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1048 if (val & 0x80000000)
1049 ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1052 void store_booke_tcr (CPUState *env, target_ulong val)
1056 tb_env = env->tb_env;
1058 if (loglevel != 0) {
1059 fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1062 env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1063 start_stop_pit(env, tb_env, 1);
1064 cpu_4xx_wdt_cb(env);
1067 static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1069 CPUState *env = opaque;
1070 ppc_tb_t *tb_env = env->tb_env;
1073 if (loglevel != 0) {
1074 fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1077 tb_env->tb_freq = freq;
1078 tb_env->decr_freq = freq;
1079 /* XXX: we should also update all timers */
1082 clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1085 ppcemb_timer_t *ppcemb_timer;
1087 tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1088 if (tb_env == NULL) {
1091 env->tb_env = tb_env;
1092 ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1093 tb_env->tb_freq = freq;
1094 tb_env->decr_freq = freq;
1095 tb_env->opaque = ppcemb_timer;
1097 if (loglevel != 0) {
1098 fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1099 &ppc_emb_set_tb_clk);
1102 if (ppcemb_timer != NULL) {
1103 /* We use decr timer for PIT */
1104 tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1105 ppcemb_timer->fit_timer =
1106 qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1107 ppcemb_timer->wdt_timer =
1108 qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1111 return &ppc_emb_set_tb_clk;
1114 /*****************************************************************************/
1115 /* Embedded PowerPC Device Control Registers */
1116 typedef struct ppc_dcrn_t ppc_dcrn_t;
1118 dcr_read_cb dcr_read;
1119 dcr_write_cb dcr_write;
1123 /* XXX: on 460, DCR addresses are 32 bits wide,
1124 * using DCRIPR to get the 22 upper bits of the DCR address
1126 #define DCRN_NB 1024
1128 ppc_dcrn_t dcrn[DCRN_NB];
1129 int (*read_error)(int dcrn);
1130 int (*write_error)(int dcrn);
1133 int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1137 if (dcrn < 0 || dcrn >= DCRN_NB)
1139 dcr = &dcr_env->dcrn[dcrn];
1140 if (dcr->dcr_read == NULL)
1142 *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1147 if (dcr_env->read_error != NULL)
1148 return (*dcr_env->read_error)(dcrn);
1153 int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1157 if (dcrn < 0 || dcrn >= DCRN_NB)
1159 dcr = &dcr_env->dcrn[dcrn];
1160 if (dcr->dcr_write == NULL)
1162 (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1167 if (dcr_env->write_error != NULL)
1168 return (*dcr_env->write_error)(dcrn);
1173 int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1174 dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1179 dcr_env = env->dcr_env;
1180 if (dcr_env == NULL)
1182 if (dcrn < 0 || dcrn >= DCRN_NB)
1184 dcr = &dcr_env->dcrn[dcrn];
1185 if (dcr->opaque != NULL ||
1186 dcr->dcr_read != NULL ||
1187 dcr->dcr_write != NULL)
1189 dcr->opaque = opaque;
1190 dcr->dcr_read = dcr_read;
1191 dcr->dcr_write = dcr_write;
1196 int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1197 int (*write_error)(int dcrn))
1201 dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1202 if (dcr_env == NULL)
1204 dcr_env->read_error = read_error;
1205 dcr_env->write_error = write_error;
1206 env->dcr_env = dcr_env;
1212 /*****************************************************************************/
1213 /* Handle system reset (for now, just stop emulation) */
1214 void cpu_ppc_reset (CPUState *env)
1216 printf("Reset asked... Stop emulation\n");
1221 /*****************************************************************************/
1223 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1235 printf("Set loglevel to %04x\n", val);
1236 cpu_set_log(val | 0x100);
1241 /*****************************************************************************/
1243 void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
1245 m48t59_write(nvram, addr, value);
1248 uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
1250 return m48t59_read(nvram, addr);
1253 void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
1255 m48t59_write(nvram, addr, value >> 8);
1256 m48t59_write(nvram, addr + 1, value & 0xFF);
1259 uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
1263 tmp = m48t59_read(nvram, addr) << 8;
1264 tmp |= m48t59_read(nvram, addr + 1);
1268 void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
1270 m48t59_write(nvram, addr, value >> 24);
1271 m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
1272 m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
1273 m48t59_write(nvram, addr + 3, value & 0xFF);
1276 uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
1280 tmp = m48t59_read(nvram, addr) << 24;
1281 tmp |= m48t59_read(nvram, addr + 1) << 16;
1282 tmp |= m48t59_read(nvram, addr + 2) << 8;
1283 tmp |= m48t59_read(nvram, addr + 3);
1288 void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
1289 const unsigned char *str, uint32_t max)
1293 for (i = 0; i < max && str[i] != '\0'; i++) {
1294 m48t59_write(nvram, addr + i, str[i]);
1296 m48t59_write(nvram, addr + max - 1, '\0');
1299 int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
1303 memset(dst, 0, max);
1304 for (i = 0; i < max; i++) {
1305 dst[i] = NVRAM_get_byte(nvram, addr + i);
1313 static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1316 uint16_t pd, pd1, pd2;
1321 pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1322 tmp ^= (pd1 << 3) | (pd1 << 8);
1323 tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1328 uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
1331 uint16_t crc = 0xFFFF;
1336 for (i = 0; i != count; i++) {
1337 crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1340 crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1346 #define CMDLINE_ADDR 0x017ff000
1348 int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
1349 const unsigned char *arch,
1350 uint32_t RAM_size, int boot_device,
1351 uint32_t kernel_image, uint32_t kernel_size,
1352 const char *cmdline,
1353 uint32_t initrd_image, uint32_t initrd_size,
1354 uint32_t NVRAM_image,
1355 int width, int height, int depth)
1359 /* Set parameters for Open Hack'Ware BIOS */
1360 NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1361 NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
1362 NVRAM_set_word(nvram, 0x14, NVRAM_size);
1363 NVRAM_set_string(nvram, 0x20, arch, 16);
1364 NVRAM_set_lword(nvram, 0x30, RAM_size);
1365 NVRAM_set_byte(nvram, 0x34, boot_device);
1366 NVRAM_set_lword(nvram, 0x38, kernel_image);
1367 NVRAM_set_lword(nvram, 0x3C, kernel_size);
1369 /* XXX: put the cmdline in NVRAM too ? */
1370 strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
1371 NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
1372 NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
1374 NVRAM_set_lword(nvram, 0x40, 0);
1375 NVRAM_set_lword(nvram, 0x44, 0);
1377 NVRAM_set_lword(nvram, 0x48, initrd_image);
1378 NVRAM_set_lword(nvram, 0x4C, initrd_size);
1379 NVRAM_set_lword(nvram, 0x50, NVRAM_image);
1381 NVRAM_set_word(nvram, 0x54, width);
1382 NVRAM_set_word(nvram, 0x56, height);
1383 NVRAM_set_word(nvram, 0x58, depth);
1384 crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1385 NVRAM_set_word(nvram, 0xFC, crc);