xref: /qemu/hw/ppc/ppc.c (revision 42043e4f)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * QEMU generic PowerPC hardware System Emulator
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (c) 2003-2007 Jocelyn Mayer
553018216SPaolo Bonzini  *
653018216SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
753018216SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
853018216SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
953018216SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1053018216SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1153018216SPaolo Bonzini  * furnished to do so, subject to the following conditions:
1253018216SPaolo Bonzini  *
1353018216SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1453018216SPaolo Bonzini  * all copies or substantial portions of the Software.
1553018216SPaolo Bonzini  *
1653018216SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1753018216SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1853018216SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1953018216SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2053018216SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2153018216SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2253018216SPaolo Bonzini  * THE SOFTWARE.
2353018216SPaolo Bonzini  */
240d75590dSPeter Maydell #include "qemu/osdep.h"
254771d756SPaolo Bonzini #include "qemu-common.h"
264771d756SPaolo Bonzini #include "cpu.h"
2753018216SPaolo Bonzini #include "hw/hw.h"
280d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
292b927571SAndreas Färber #include "hw/ppc/ppc_e500.h"
3053018216SPaolo Bonzini #include "qemu/timer.h"
3153018216SPaolo Bonzini #include "sysemu/sysemu.h"
320ce470cdSAlexey Kardashevskiy #include "sysemu/cpus.h"
330d09e41aSPaolo Bonzini #include "hw/timer/m48t59.h"
3453018216SPaolo Bonzini #include "qemu/log.h"
3598a8b524SAlexey Kardashevskiy #include "qemu/error-report.h"
36e703d2f7SGreg Kurz #include "qapi/error.h"
3753018216SPaolo Bonzini #include "hw/loader.h"
3853018216SPaolo Bonzini #include "sysemu/kvm.h"
3953018216SPaolo Bonzini #include "kvm_ppc.h"
4098a8b524SAlexey Kardashevskiy #include "trace.h"
4153018216SPaolo Bonzini 
4253018216SPaolo Bonzini //#define PPC_DEBUG_IRQ
4353018216SPaolo Bonzini //#define PPC_DEBUG_TB
4453018216SPaolo Bonzini 
4553018216SPaolo Bonzini #ifdef PPC_DEBUG_IRQ
4653018216SPaolo Bonzini #  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
4753018216SPaolo Bonzini #else
4853018216SPaolo Bonzini #  define LOG_IRQ(...) do { } while (0)
4953018216SPaolo Bonzini #endif
5053018216SPaolo Bonzini 
5153018216SPaolo Bonzini 
5253018216SPaolo Bonzini #ifdef PPC_DEBUG_TB
5353018216SPaolo Bonzini #  define LOG_TB(...) qemu_log(__VA_ARGS__)
5453018216SPaolo Bonzini #else
5553018216SPaolo Bonzini #  define LOG_TB(...) do { } while (0)
5653018216SPaolo Bonzini #endif
5753018216SPaolo Bonzini 
5853018216SPaolo Bonzini static void cpu_ppc_tb_stop (CPUPPCState *env);
5953018216SPaolo Bonzini static void cpu_ppc_tb_start (CPUPPCState *env);
6053018216SPaolo Bonzini 
6153018216SPaolo Bonzini void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
6253018216SPaolo Bonzini {
63d8ed887bSAndreas Färber     CPUState *cs = CPU(cpu);
6453018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
6553018216SPaolo Bonzini     unsigned int old_pending = env->pending_interrupts;
6653018216SPaolo Bonzini 
6753018216SPaolo Bonzini     if (level) {
6853018216SPaolo Bonzini         env->pending_interrupts |= 1 << n_IRQ;
69c3affe56SAndreas Färber         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
7053018216SPaolo Bonzini     } else {
7153018216SPaolo Bonzini         env->pending_interrupts &= ~(1 << n_IRQ);
72d8ed887bSAndreas Färber         if (env->pending_interrupts == 0) {
73d8ed887bSAndreas Färber             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
74d8ed887bSAndreas Färber         }
7553018216SPaolo Bonzini     }
7653018216SPaolo Bonzini 
7753018216SPaolo Bonzini     if (old_pending != env->pending_interrupts) {
7853018216SPaolo Bonzini #ifdef CONFIG_KVM
7953018216SPaolo Bonzini         kvmppc_set_interrupt(cpu, n_IRQ, level);
8053018216SPaolo Bonzini #endif
8153018216SPaolo Bonzini     }
8253018216SPaolo Bonzini 
8353018216SPaolo Bonzini     LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
8453018216SPaolo Bonzini                 "req %08x\n", __func__, env, n_IRQ, level,
85259186a7SAndreas Färber                 env->pending_interrupts, CPU(cpu)->interrupt_request);
8653018216SPaolo Bonzini }
8753018216SPaolo Bonzini 
8853018216SPaolo Bonzini /* PowerPC 6xx / 7xx internal IRQ controller */
8953018216SPaolo Bonzini static void ppc6xx_set_irq(void *opaque, int pin, int level)
9053018216SPaolo Bonzini {
9153018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
9253018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
9353018216SPaolo Bonzini     int cur_level;
9453018216SPaolo Bonzini 
9553018216SPaolo Bonzini     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
9653018216SPaolo Bonzini                 env, pin, level);
9753018216SPaolo Bonzini     cur_level = (env->irq_input_state >> pin) & 1;
9853018216SPaolo Bonzini     /* Don't generate spurious events */
9953018216SPaolo Bonzini     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
100259186a7SAndreas Färber         CPUState *cs = CPU(cpu);
101259186a7SAndreas Färber 
10253018216SPaolo Bonzini         switch (pin) {
10353018216SPaolo Bonzini         case PPC6xx_INPUT_TBEN:
10453018216SPaolo Bonzini             /* Level sensitive - active high */
10553018216SPaolo Bonzini             LOG_IRQ("%s: %s the time base\n",
10653018216SPaolo Bonzini                         __func__, level ? "start" : "stop");
10753018216SPaolo Bonzini             if (level) {
10853018216SPaolo Bonzini                 cpu_ppc_tb_start(env);
10953018216SPaolo Bonzini             } else {
11053018216SPaolo Bonzini                 cpu_ppc_tb_stop(env);
11153018216SPaolo Bonzini             }
11253018216SPaolo Bonzini         case PPC6xx_INPUT_INT:
11353018216SPaolo Bonzini             /* Level sensitive - active high */
11453018216SPaolo Bonzini             LOG_IRQ("%s: set the external IRQ state to %d\n",
11553018216SPaolo Bonzini                         __func__, level);
11653018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
11753018216SPaolo Bonzini             break;
11853018216SPaolo Bonzini         case PPC6xx_INPUT_SMI:
11953018216SPaolo Bonzini             /* Level sensitive - active high */
12053018216SPaolo Bonzini             LOG_IRQ("%s: set the SMI IRQ state to %d\n",
12153018216SPaolo Bonzini                         __func__, level);
12253018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
12353018216SPaolo Bonzini             break;
12453018216SPaolo Bonzini         case PPC6xx_INPUT_MCP:
12553018216SPaolo Bonzini             /* Negative edge sensitive */
12653018216SPaolo Bonzini             /* XXX: TODO: actual reaction may depends on HID0 status
12753018216SPaolo Bonzini              *            603/604/740/750: check HID0[EMCP]
12853018216SPaolo Bonzini              */
12953018216SPaolo Bonzini             if (cur_level == 1 && level == 0) {
13053018216SPaolo Bonzini                 LOG_IRQ("%s: raise machine check state\n",
13153018216SPaolo Bonzini                             __func__);
13253018216SPaolo Bonzini                 ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
13353018216SPaolo Bonzini             }
13453018216SPaolo Bonzini             break;
13553018216SPaolo Bonzini         case PPC6xx_INPUT_CKSTP_IN:
13653018216SPaolo Bonzini             /* Level sensitive - active low */
13753018216SPaolo Bonzini             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
13853018216SPaolo Bonzini             /* XXX: Note that the only way to restart the CPU is to reset it */
13953018216SPaolo Bonzini             if (level) {
14053018216SPaolo Bonzini                 LOG_IRQ("%s: stop the CPU\n", __func__);
141259186a7SAndreas Färber                 cs->halted = 1;
14253018216SPaolo Bonzini             }
14353018216SPaolo Bonzini             break;
14453018216SPaolo Bonzini         case PPC6xx_INPUT_HRESET:
14553018216SPaolo Bonzini             /* Level sensitive - active low */
14653018216SPaolo Bonzini             if (level) {
14753018216SPaolo Bonzini                 LOG_IRQ("%s: reset the CPU\n", __func__);
148c3affe56SAndreas Färber                 cpu_interrupt(cs, CPU_INTERRUPT_RESET);
14953018216SPaolo Bonzini             }
15053018216SPaolo Bonzini             break;
15153018216SPaolo Bonzini         case PPC6xx_INPUT_SRESET:
15253018216SPaolo Bonzini             LOG_IRQ("%s: set the RESET IRQ state to %d\n",
15353018216SPaolo Bonzini                         __func__, level);
15453018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
15553018216SPaolo Bonzini             break;
15653018216SPaolo Bonzini         default:
15753018216SPaolo Bonzini             /* Unknown pin - do nothing */
15853018216SPaolo Bonzini             LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
15953018216SPaolo Bonzini             return;
16053018216SPaolo Bonzini         }
16153018216SPaolo Bonzini         if (level)
16253018216SPaolo Bonzini             env->irq_input_state |= 1 << pin;
16353018216SPaolo Bonzini         else
16453018216SPaolo Bonzini             env->irq_input_state &= ~(1 << pin);
16553018216SPaolo Bonzini     }
16653018216SPaolo Bonzini }
16753018216SPaolo Bonzini 
168aa5a9e24SPaolo Bonzini void ppc6xx_irq_init(PowerPCCPU *cpu)
16953018216SPaolo Bonzini {
170aa5a9e24SPaolo Bonzini     CPUPPCState *env = &cpu->env;
17153018216SPaolo Bonzini 
17253018216SPaolo Bonzini     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
17353018216SPaolo Bonzini                                                   PPC6xx_INPUT_NB);
17453018216SPaolo Bonzini }
17553018216SPaolo Bonzini 
17653018216SPaolo Bonzini #if defined(TARGET_PPC64)
17753018216SPaolo Bonzini /* PowerPC 970 internal IRQ controller */
17853018216SPaolo Bonzini static void ppc970_set_irq(void *opaque, int pin, int level)
17953018216SPaolo Bonzini {
18053018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
18153018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
18253018216SPaolo Bonzini     int cur_level;
18353018216SPaolo Bonzini 
18453018216SPaolo Bonzini     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
18553018216SPaolo Bonzini                 env, pin, level);
18653018216SPaolo Bonzini     cur_level = (env->irq_input_state >> pin) & 1;
18753018216SPaolo Bonzini     /* Don't generate spurious events */
18853018216SPaolo Bonzini     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
189259186a7SAndreas Färber         CPUState *cs = CPU(cpu);
190259186a7SAndreas Färber 
19153018216SPaolo Bonzini         switch (pin) {
19253018216SPaolo Bonzini         case PPC970_INPUT_INT:
19353018216SPaolo Bonzini             /* Level sensitive - active high */
19453018216SPaolo Bonzini             LOG_IRQ("%s: set the external IRQ state to %d\n",
19553018216SPaolo Bonzini                         __func__, level);
19653018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
19753018216SPaolo Bonzini             break;
19853018216SPaolo Bonzini         case PPC970_INPUT_THINT:
19953018216SPaolo Bonzini             /* Level sensitive - active high */
20053018216SPaolo Bonzini             LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
20153018216SPaolo Bonzini                         level);
20253018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
20353018216SPaolo Bonzini             break;
20453018216SPaolo Bonzini         case PPC970_INPUT_MCP:
20553018216SPaolo Bonzini             /* Negative edge sensitive */
20653018216SPaolo Bonzini             /* XXX: TODO: actual reaction may depends on HID0 status
20753018216SPaolo Bonzini              *            603/604/740/750: check HID0[EMCP]
20853018216SPaolo Bonzini              */
20953018216SPaolo Bonzini             if (cur_level == 1 && level == 0) {
21053018216SPaolo Bonzini                 LOG_IRQ("%s: raise machine check state\n",
21153018216SPaolo Bonzini                             __func__);
21253018216SPaolo Bonzini                 ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
21353018216SPaolo Bonzini             }
21453018216SPaolo Bonzini             break;
21553018216SPaolo Bonzini         case PPC970_INPUT_CKSTP:
21653018216SPaolo Bonzini             /* Level sensitive - active low */
21753018216SPaolo Bonzini             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
21853018216SPaolo Bonzini             if (level) {
21953018216SPaolo Bonzini                 LOG_IRQ("%s: stop the CPU\n", __func__);
220259186a7SAndreas Färber                 cs->halted = 1;
22153018216SPaolo Bonzini             } else {
22253018216SPaolo Bonzini                 LOG_IRQ("%s: restart the CPU\n", __func__);
223259186a7SAndreas Färber                 cs->halted = 0;
224259186a7SAndreas Färber                 qemu_cpu_kick(cs);
22553018216SPaolo Bonzini             }
22653018216SPaolo Bonzini             break;
22753018216SPaolo Bonzini         case PPC970_INPUT_HRESET:
22853018216SPaolo Bonzini             /* Level sensitive - active low */
22953018216SPaolo Bonzini             if (level) {
230c3affe56SAndreas Färber                 cpu_interrupt(cs, CPU_INTERRUPT_RESET);
23153018216SPaolo Bonzini             }
23253018216SPaolo Bonzini             break;
23353018216SPaolo Bonzini         case PPC970_INPUT_SRESET:
23453018216SPaolo Bonzini             LOG_IRQ("%s: set the RESET IRQ state to %d\n",
23553018216SPaolo Bonzini                         __func__, level);
23653018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
23753018216SPaolo Bonzini             break;
23853018216SPaolo Bonzini         case PPC970_INPUT_TBEN:
23953018216SPaolo Bonzini             LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
24053018216SPaolo Bonzini                         level);
24153018216SPaolo Bonzini             /* XXX: TODO */
24253018216SPaolo Bonzini             break;
24353018216SPaolo Bonzini         default:
24453018216SPaolo Bonzini             /* Unknown pin - do nothing */
24553018216SPaolo Bonzini             LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
24653018216SPaolo Bonzini             return;
24753018216SPaolo Bonzini         }
24853018216SPaolo Bonzini         if (level)
24953018216SPaolo Bonzini             env->irq_input_state |= 1 << pin;
25053018216SPaolo Bonzini         else
25153018216SPaolo Bonzini             env->irq_input_state &= ~(1 << pin);
25253018216SPaolo Bonzini     }
25353018216SPaolo Bonzini }
25453018216SPaolo Bonzini 
255aa5a9e24SPaolo Bonzini void ppc970_irq_init(PowerPCCPU *cpu)
25653018216SPaolo Bonzini {
257aa5a9e24SPaolo Bonzini     CPUPPCState *env = &cpu->env;
25853018216SPaolo Bonzini 
25953018216SPaolo Bonzini     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
26053018216SPaolo Bonzini                                                   PPC970_INPUT_NB);
26153018216SPaolo Bonzini }
26253018216SPaolo Bonzini 
26353018216SPaolo Bonzini /* POWER7 internal IRQ controller */
26453018216SPaolo Bonzini static void power7_set_irq(void *opaque, int pin, int level)
26553018216SPaolo Bonzini {
26653018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
26753018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
26853018216SPaolo Bonzini 
26953018216SPaolo Bonzini     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
27053018216SPaolo Bonzini                 env, pin, level);
27153018216SPaolo Bonzini 
27253018216SPaolo Bonzini     switch (pin) {
27353018216SPaolo Bonzini     case POWER7_INPUT_INT:
27453018216SPaolo Bonzini         /* Level sensitive - active high */
27553018216SPaolo Bonzini         LOG_IRQ("%s: set the external IRQ state to %d\n",
27653018216SPaolo Bonzini                 __func__, level);
27753018216SPaolo Bonzini         ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
27853018216SPaolo Bonzini         break;
27953018216SPaolo Bonzini     default:
28053018216SPaolo Bonzini         /* Unknown pin - do nothing */
28153018216SPaolo Bonzini         LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
28253018216SPaolo Bonzini         return;
28353018216SPaolo Bonzini     }
28453018216SPaolo Bonzini     if (level) {
28553018216SPaolo Bonzini         env->irq_input_state |= 1 << pin;
28653018216SPaolo Bonzini     } else {
28753018216SPaolo Bonzini         env->irq_input_state &= ~(1 << pin);
28853018216SPaolo Bonzini     }
28953018216SPaolo Bonzini }
29053018216SPaolo Bonzini 
291aa5a9e24SPaolo Bonzini void ppcPOWER7_irq_init(PowerPCCPU *cpu)
29253018216SPaolo Bonzini {
293aa5a9e24SPaolo Bonzini     CPUPPCState *env = &cpu->env;
29453018216SPaolo Bonzini 
29553018216SPaolo Bonzini     env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
29653018216SPaolo Bonzini                                                   POWER7_INPUT_NB);
29753018216SPaolo Bonzini }
29853018216SPaolo Bonzini #endif /* defined(TARGET_PPC64) */
29953018216SPaolo Bonzini 
30053018216SPaolo Bonzini /* PowerPC 40x internal IRQ controller */
30153018216SPaolo Bonzini static void ppc40x_set_irq(void *opaque, int pin, int level)
30253018216SPaolo Bonzini {
30353018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
30453018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
30553018216SPaolo Bonzini     int cur_level;
30653018216SPaolo Bonzini 
30753018216SPaolo Bonzini     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
30853018216SPaolo Bonzini                 env, pin, level);
30953018216SPaolo Bonzini     cur_level = (env->irq_input_state >> pin) & 1;
31053018216SPaolo Bonzini     /* Don't generate spurious events */
31153018216SPaolo Bonzini     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
312259186a7SAndreas Färber         CPUState *cs = CPU(cpu);
313259186a7SAndreas Färber 
31453018216SPaolo Bonzini         switch (pin) {
31553018216SPaolo Bonzini         case PPC40x_INPUT_RESET_SYS:
31653018216SPaolo Bonzini             if (level) {
31753018216SPaolo Bonzini                 LOG_IRQ("%s: reset the PowerPC system\n",
31853018216SPaolo Bonzini                             __func__);
31953018216SPaolo Bonzini                 ppc40x_system_reset(cpu);
32053018216SPaolo Bonzini             }
32153018216SPaolo Bonzini             break;
32253018216SPaolo Bonzini         case PPC40x_INPUT_RESET_CHIP:
32353018216SPaolo Bonzini             if (level) {
32453018216SPaolo Bonzini                 LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
32553018216SPaolo Bonzini                 ppc40x_chip_reset(cpu);
32653018216SPaolo Bonzini             }
32753018216SPaolo Bonzini             break;
32853018216SPaolo Bonzini         case PPC40x_INPUT_RESET_CORE:
32953018216SPaolo Bonzini             /* XXX: TODO: update DBSR[MRR] */
33053018216SPaolo Bonzini             if (level) {
33153018216SPaolo Bonzini                 LOG_IRQ("%s: reset the PowerPC core\n", __func__);
33253018216SPaolo Bonzini                 ppc40x_core_reset(cpu);
33353018216SPaolo Bonzini             }
33453018216SPaolo Bonzini             break;
33553018216SPaolo Bonzini         case PPC40x_INPUT_CINT:
33653018216SPaolo Bonzini             /* Level sensitive - active high */
33753018216SPaolo Bonzini             LOG_IRQ("%s: set the critical IRQ state to %d\n",
33853018216SPaolo Bonzini                         __func__, level);
33953018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
34053018216SPaolo Bonzini             break;
34153018216SPaolo Bonzini         case PPC40x_INPUT_INT:
34253018216SPaolo Bonzini             /* Level sensitive - active high */
34353018216SPaolo Bonzini             LOG_IRQ("%s: set the external IRQ state to %d\n",
34453018216SPaolo Bonzini                         __func__, level);
34553018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
34653018216SPaolo Bonzini             break;
34753018216SPaolo Bonzini         case PPC40x_INPUT_HALT:
34853018216SPaolo Bonzini             /* Level sensitive - active low */
34953018216SPaolo Bonzini             if (level) {
35053018216SPaolo Bonzini                 LOG_IRQ("%s: stop the CPU\n", __func__);
351259186a7SAndreas Färber                 cs->halted = 1;
35253018216SPaolo Bonzini             } else {
35353018216SPaolo Bonzini                 LOG_IRQ("%s: restart the CPU\n", __func__);
354259186a7SAndreas Färber                 cs->halted = 0;
355259186a7SAndreas Färber                 qemu_cpu_kick(cs);
35653018216SPaolo Bonzini             }
35753018216SPaolo Bonzini             break;
35853018216SPaolo Bonzini         case PPC40x_INPUT_DEBUG:
35953018216SPaolo Bonzini             /* Level sensitive - active high */
36053018216SPaolo Bonzini             LOG_IRQ("%s: set the debug pin state to %d\n",
36153018216SPaolo Bonzini                         __func__, level);
36253018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
36353018216SPaolo Bonzini             break;
36453018216SPaolo Bonzini         default:
36553018216SPaolo Bonzini             /* Unknown pin - do nothing */
36653018216SPaolo Bonzini             LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
36753018216SPaolo Bonzini             return;
36853018216SPaolo Bonzini         }
36953018216SPaolo Bonzini         if (level)
37053018216SPaolo Bonzini             env->irq_input_state |= 1 << pin;
37153018216SPaolo Bonzini         else
37253018216SPaolo Bonzini             env->irq_input_state &= ~(1 << pin);
37353018216SPaolo Bonzini     }
37453018216SPaolo Bonzini }
37553018216SPaolo Bonzini 
376aa5a9e24SPaolo Bonzini void ppc40x_irq_init(PowerPCCPU *cpu)
37753018216SPaolo Bonzini {
378aa5a9e24SPaolo Bonzini     CPUPPCState *env = &cpu->env;
37953018216SPaolo Bonzini 
38053018216SPaolo Bonzini     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
38153018216SPaolo Bonzini                                                   cpu, PPC40x_INPUT_NB);
38253018216SPaolo Bonzini }
38353018216SPaolo Bonzini 
38453018216SPaolo Bonzini /* PowerPC E500 internal IRQ controller */
38553018216SPaolo Bonzini static void ppce500_set_irq(void *opaque, int pin, int level)
38653018216SPaolo Bonzini {
38753018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
38853018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
38953018216SPaolo Bonzini     int cur_level;
39053018216SPaolo Bonzini 
39153018216SPaolo Bonzini     LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
39253018216SPaolo Bonzini                 env, pin, level);
39353018216SPaolo Bonzini     cur_level = (env->irq_input_state >> pin) & 1;
39453018216SPaolo Bonzini     /* Don't generate spurious events */
39553018216SPaolo Bonzini     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
39653018216SPaolo Bonzini         switch (pin) {
39753018216SPaolo Bonzini         case PPCE500_INPUT_MCK:
39853018216SPaolo Bonzini             if (level) {
39953018216SPaolo Bonzini                 LOG_IRQ("%s: reset the PowerPC system\n",
40053018216SPaolo Bonzini                             __func__);
40153018216SPaolo Bonzini                 qemu_system_reset_request();
40253018216SPaolo Bonzini             }
40353018216SPaolo Bonzini             break;
40453018216SPaolo Bonzini         case PPCE500_INPUT_RESET_CORE:
40553018216SPaolo Bonzini             if (level) {
40653018216SPaolo Bonzini                 LOG_IRQ("%s: reset the PowerPC core\n", __func__);
40753018216SPaolo Bonzini                 ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
40853018216SPaolo Bonzini             }
40953018216SPaolo Bonzini             break;
41053018216SPaolo Bonzini         case PPCE500_INPUT_CINT:
41153018216SPaolo Bonzini             /* Level sensitive - active high */
41253018216SPaolo Bonzini             LOG_IRQ("%s: set the critical IRQ state to %d\n",
41353018216SPaolo Bonzini                         __func__, level);
41453018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
41553018216SPaolo Bonzini             break;
41653018216SPaolo Bonzini         case PPCE500_INPUT_INT:
41753018216SPaolo Bonzini             /* Level sensitive - active high */
41853018216SPaolo Bonzini             LOG_IRQ("%s: set the core IRQ state to %d\n",
41953018216SPaolo Bonzini                         __func__, level);
42053018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
42153018216SPaolo Bonzini             break;
42253018216SPaolo Bonzini         case PPCE500_INPUT_DEBUG:
42353018216SPaolo Bonzini             /* Level sensitive - active high */
42453018216SPaolo Bonzini             LOG_IRQ("%s: set the debug pin state to %d\n",
42553018216SPaolo Bonzini                         __func__, level);
42653018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
42753018216SPaolo Bonzini             break;
42853018216SPaolo Bonzini         default:
42953018216SPaolo Bonzini             /* Unknown pin - do nothing */
43053018216SPaolo Bonzini             LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
43153018216SPaolo Bonzini             return;
43253018216SPaolo Bonzini         }
43353018216SPaolo Bonzini         if (level)
43453018216SPaolo Bonzini             env->irq_input_state |= 1 << pin;
43553018216SPaolo Bonzini         else
43653018216SPaolo Bonzini             env->irq_input_state &= ~(1 << pin);
43753018216SPaolo Bonzini     }
43853018216SPaolo Bonzini }
43953018216SPaolo Bonzini 
440aa5a9e24SPaolo Bonzini void ppce500_irq_init(PowerPCCPU *cpu)
44153018216SPaolo Bonzini {
442aa5a9e24SPaolo Bonzini     CPUPPCState *env = &cpu->env;
44353018216SPaolo Bonzini 
44453018216SPaolo Bonzini     env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
44553018216SPaolo Bonzini                                                   cpu, PPCE500_INPUT_NB);
44653018216SPaolo Bonzini }
44753018216SPaolo Bonzini 
44853018216SPaolo Bonzini /* Enable or Disable the E500 EPR capability */
44953018216SPaolo Bonzini void ppce500_set_mpic_proxy(bool enabled)
45053018216SPaolo Bonzini {
451182735efSAndreas Färber     CPUState *cs;
45253018216SPaolo Bonzini 
453bdc44640SAndreas Färber     CPU_FOREACH(cs) {
454182735efSAndreas Färber         PowerPCCPU *cpu = POWERPC_CPU(cs);
45553018216SPaolo Bonzini 
456182735efSAndreas Färber         cpu->env.mpic_proxy = enabled;
45753018216SPaolo Bonzini         if (kvm_enabled()) {
458182735efSAndreas Färber             kvmppc_set_mpic_proxy(cpu, enabled);
45953018216SPaolo Bonzini         }
46053018216SPaolo Bonzini     }
46153018216SPaolo Bonzini }
46253018216SPaolo Bonzini 
46353018216SPaolo Bonzini /*****************************************************************************/
46453018216SPaolo Bonzini /* PowerPC time base and decrementer emulation */
46553018216SPaolo Bonzini 
46653018216SPaolo Bonzini uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
46753018216SPaolo Bonzini {
46853018216SPaolo Bonzini     /* TB time in tb periods */
46973bcb24dSRutuja Shah     return muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND) + tb_offset;
47053018216SPaolo Bonzini }
47153018216SPaolo Bonzini 
47253018216SPaolo Bonzini uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
47353018216SPaolo Bonzini {
47453018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
47553018216SPaolo Bonzini     uint64_t tb;
47653018216SPaolo Bonzini 
47753018216SPaolo Bonzini     if (kvm_enabled()) {
47853018216SPaolo Bonzini         return env->spr[SPR_TBL];
47953018216SPaolo Bonzini     }
48053018216SPaolo Bonzini 
481bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
48253018216SPaolo Bonzini     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
48353018216SPaolo Bonzini 
48453018216SPaolo Bonzini     return tb;
48553018216SPaolo Bonzini }
48653018216SPaolo Bonzini 
48753018216SPaolo Bonzini static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
48853018216SPaolo Bonzini {
48953018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
49053018216SPaolo Bonzini     uint64_t tb;
49153018216SPaolo Bonzini 
492bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
49353018216SPaolo Bonzini     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
49453018216SPaolo Bonzini 
49553018216SPaolo Bonzini     return tb >> 32;
49653018216SPaolo Bonzini }
49753018216SPaolo Bonzini 
49853018216SPaolo Bonzini uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
49953018216SPaolo Bonzini {
50053018216SPaolo Bonzini     if (kvm_enabled()) {
50153018216SPaolo Bonzini         return env->spr[SPR_TBU];
50253018216SPaolo Bonzini     }
50353018216SPaolo Bonzini 
50453018216SPaolo Bonzini     return _cpu_ppc_load_tbu(env);
50553018216SPaolo Bonzini }
50653018216SPaolo Bonzini 
50753018216SPaolo Bonzini static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
50853018216SPaolo Bonzini                                     int64_t *tb_offsetp, uint64_t value)
50953018216SPaolo Bonzini {
51073bcb24dSRutuja Shah     *tb_offsetp = value -
51173bcb24dSRutuja Shah         muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
51273bcb24dSRutuja Shah 
51353018216SPaolo Bonzini     LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
51453018216SPaolo Bonzini                 __func__, value, *tb_offsetp);
51553018216SPaolo Bonzini }
51653018216SPaolo Bonzini 
51753018216SPaolo Bonzini void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
51853018216SPaolo Bonzini {
51953018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
52053018216SPaolo Bonzini     uint64_t tb;
52153018216SPaolo Bonzini 
522bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
52353018216SPaolo Bonzini     tb &= 0xFFFFFFFF00000000ULL;
524bc72ad67SAlex Bligh     cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
52553018216SPaolo Bonzini                      &tb_env->tb_offset, tb | (uint64_t)value);
52653018216SPaolo Bonzini }
52753018216SPaolo Bonzini 
52853018216SPaolo Bonzini static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
52953018216SPaolo Bonzini {
53053018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
53153018216SPaolo Bonzini     uint64_t tb;
53253018216SPaolo Bonzini 
533bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
53453018216SPaolo Bonzini     tb &= 0x00000000FFFFFFFFULL;
535bc72ad67SAlex Bligh     cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
53653018216SPaolo Bonzini                      &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
53753018216SPaolo Bonzini }
53853018216SPaolo Bonzini 
53953018216SPaolo Bonzini void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
54053018216SPaolo Bonzini {
54153018216SPaolo Bonzini     _cpu_ppc_store_tbu(env, value);
54253018216SPaolo Bonzini }
54353018216SPaolo Bonzini 
54453018216SPaolo Bonzini uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
54553018216SPaolo Bonzini {
54653018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
54753018216SPaolo Bonzini     uint64_t tb;
54853018216SPaolo Bonzini 
549bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
55053018216SPaolo Bonzini     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
55153018216SPaolo Bonzini 
55253018216SPaolo Bonzini     return tb;
55353018216SPaolo Bonzini }
55453018216SPaolo Bonzini 
55553018216SPaolo Bonzini uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
55653018216SPaolo Bonzini {
55753018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
55853018216SPaolo Bonzini     uint64_t tb;
55953018216SPaolo Bonzini 
560bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
56153018216SPaolo Bonzini     LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
56253018216SPaolo Bonzini 
56353018216SPaolo Bonzini     return tb >> 32;
56453018216SPaolo Bonzini }
56553018216SPaolo Bonzini 
56653018216SPaolo Bonzini void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
56753018216SPaolo Bonzini {
56853018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
56953018216SPaolo Bonzini     uint64_t tb;
57053018216SPaolo Bonzini 
571bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
57253018216SPaolo Bonzini     tb &= 0xFFFFFFFF00000000ULL;
573bc72ad67SAlex Bligh     cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
57453018216SPaolo Bonzini                      &tb_env->atb_offset, tb | (uint64_t)value);
57553018216SPaolo Bonzini }
57653018216SPaolo Bonzini 
57753018216SPaolo Bonzini void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
57853018216SPaolo Bonzini {
57953018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
58053018216SPaolo Bonzini     uint64_t tb;
58153018216SPaolo Bonzini 
582bc72ad67SAlex Bligh     tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
58353018216SPaolo Bonzini     tb &= 0x00000000FFFFFFFFULL;
584bc72ad67SAlex Bligh     cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
58553018216SPaolo Bonzini                      &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
58653018216SPaolo Bonzini }
58753018216SPaolo Bonzini 
58853018216SPaolo Bonzini static void cpu_ppc_tb_stop (CPUPPCState *env)
58953018216SPaolo Bonzini {
59053018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
59153018216SPaolo Bonzini     uint64_t tb, atb, vmclk;
59253018216SPaolo Bonzini 
59353018216SPaolo Bonzini     /* If the time base is already frozen, do nothing */
59453018216SPaolo Bonzini     if (tb_env->tb_freq != 0) {
595bc72ad67SAlex Bligh         vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
59653018216SPaolo Bonzini         /* Get the time base */
59753018216SPaolo Bonzini         tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
59853018216SPaolo Bonzini         /* Get the alternate time base */
59953018216SPaolo Bonzini         atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
60053018216SPaolo Bonzini         /* Store the time base value (ie compute the current offset) */
60153018216SPaolo Bonzini         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
60253018216SPaolo Bonzini         /* Store the alternate time base value (compute the current offset) */
60353018216SPaolo Bonzini         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
60453018216SPaolo Bonzini         /* Set the time base frequency to zero */
60553018216SPaolo Bonzini         tb_env->tb_freq = 0;
60653018216SPaolo Bonzini         /* Now, the time bases are frozen to tb_offset / atb_offset value */
60753018216SPaolo Bonzini     }
60853018216SPaolo Bonzini }
60953018216SPaolo Bonzini 
61053018216SPaolo Bonzini static void cpu_ppc_tb_start (CPUPPCState *env)
61153018216SPaolo Bonzini {
61253018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
61353018216SPaolo Bonzini     uint64_t tb, atb, vmclk;
61453018216SPaolo Bonzini 
61553018216SPaolo Bonzini     /* If the time base is not frozen, do nothing */
61653018216SPaolo Bonzini     if (tb_env->tb_freq == 0) {
617bc72ad67SAlex Bligh         vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
61853018216SPaolo Bonzini         /* Get the time base from tb_offset */
61953018216SPaolo Bonzini         tb = tb_env->tb_offset;
62053018216SPaolo Bonzini         /* Get the alternate time base from atb_offset */
62153018216SPaolo Bonzini         atb = tb_env->atb_offset;
62253018216SPaolo Bonzini         /* Restore the tb frequency from the decrementer frequency */
62353018216SPaolo Bonzini         tb_env->tb_freq = tb_env->decr_freq;
62453018216SPaolo Bonzini         /* Store the time base value */
62553018216SPaolo Bonzini         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
62653018216SPaolo Bonzini         /* Store the alternate time base value */
62753018216SPaolo Bonzini         cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
62853018216SPaolo Bonzini     }
62953018216SPaolo Bonzini }
63053018216SPaolo Bonzini 
631e81a982aSAlexander Graf bool ppc_decr_clear_on_delivery(CPUPPCState *env)
632e81a982aSAlexander Graf {
633e81a982aSAlexander Graf     ppc_tb_t *tb_env = env->tb_env;
634e81a982aSAlexander Graf     int flags = PPC_DECR_UNDERFLOW_TRIGGERED | PPC_DECR_UNDERFLOW_LEVEL;
635e81a982aSAlexander Graf     return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED);
636e81a982aSAlexander Graf }
637e81a982aSAlexander Graf 
63853018216SPaolo Bonzini static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
63953018216SPaolo Bonzini {
64053018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
64153018216SPaolo Bonzini     uint32_t decr;
64253018216SPaolo Bonzini     int64_t diff;
64353018216SPaolo Bonzini 
644bc72ad67SAlex Bligh     diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
64553018216SPaolo Bonzini     if (diff >= 0) {
64673bcb24dSRutuja Shah         decr = muldiv64(diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
64753018216SPaolo Bonzini     } else if (tb_env->flags & PPC_TIMER_BOOKE) {
64853018216SPaolo Bonzini         decr = 0;
64953018216SPaolo Bonzini     }  else {
65073bcb24dSRutuja Shah         decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND);
65153018216SPaolo Bonzini     }
65253018216SPaolo Bonzini     LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
65353018216SPaolo Bonzini 
65453018216SPaolo Bonzini     return decr;
65553018216SPaolo Bonzini }
65653018216SPaolo Bonzini 
65753018216SPaolo Bonzini uint32_t cpu_ppc_load_decr (CPUPPCState *env)
65853018216SPaolo Bonzini {
65953018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
66053018216SPaolo Bonzini 
66153018216SPaolo Bonzini     if (kvm_enabled()) {
66253018216SPaolo Bonzini         return env->spr[SPR_DECR];
66353018216SPaolo Bonzini     }
66453018216SPaolo Bonzini 
66553018216SPaolo Bonzini     return _cpu_ppc_load_decr(env, tb_env->decr_next);
66653018216SPaolo Bonzini }
66753018216SPaolo Bonzini 
66853018216SPaolo Bonzini uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
66953018216SPaolo Bonzini {
67053018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
67153018216SPaolo Bonzini 
67253018216SPaolo Bonzini     return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
67353018216SPaolo Bonzini }
67453018216SPaolo Bonzini 
67553018216SPaolo Bonzini uint64_t cpu_ppc_load_purr (CPUPPCState *env)
67653018216SPaolo Bonzini {
67753018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
67853018216SPaolo Bonzini     uint64_t diff;
67953018216SPaolo Bonzini 
680bc72ad67SAlex Bligh     diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env->purr_start;
68153018216SPaolo Bonzini 
68273bcb24dSRutuja Shah     return tb_env->purr_load +
68373bcb24dSRutuja Shah         muldiv64(diff, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
68453018216SPaolo Bonzini }
68553018216SPaolo Bonzini 
68653018216SPaolo Bonzini /* When decrementer expires,
68753018216SPaolo Bonzini  * all we need to do is generate or queue a CPU exception
68853018216SPaolo Bonzini  */
68953018216SPaolo Bonzini static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
69053018216SPaolo Bonzini {
69153018216SPaolo Bonzini     /* Raise it */
69253018216SPaolo Bonzini     LOG_TB("raise decrementer exception\n");
69353018216SPaolo Bonzini     ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
69453018216SPaolo Bonzini }
69553018216SPaolo Bonzini 
696e81a982aSAlexander Graf static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
697e81a982aSAlexander Graf {
698e81a982aSAlexander Graf     ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0);
699e81a982aSAlexander Graf }
700e81a982aSAlexander Graf 
70153018216SPaolo Bonzini static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
70253018216SPaolo Bonzini {
7034b236b62SBenjamin Herrenschmidt     CPUPPCState *env = &cpu->env;
7044b236b62SBenjamin Herrenschmidt 
70553018216SPaolo Bonzini     /* Raise it */
7064b236b62SBenjamin Herrenschmidt     LOG_TB("raise hv decrementer exception\n");
7074b236b62SBenjamin Herrenschmidt 
7084b236b62SBenjamin Herrenschmidt     /* The architecture specifies that we don't deliver HDEC
7094b236b62SBenjamin Herrenschmidt      * interrupts in a PM state. Not only they don't cause a
7104b236b62SBenjamin Herrenschmidt      * wakeup but they also get effectively discarded.
7114b236b62SBenjamin Herrenschmidt      */
7124b236b62SBenjamin Herrenschmidt     if (!env->in_pm_state) {
71353018216SPaolo Bonzini         ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
71453018216SPaolo Bonzini     }
7154b236b62SBenjamin Herrenschmidt }
71653018216SPaolo Bonzini 
717e81a982aSAlexander Graf static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
718e81a982aSAlexander Graf {
719e81a982aSAlexander Graf     ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
720e81a982aSAlexander Graf }
721e81a982aSAlexander Graf 
72253018216SPaolo Bonzini static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
7231246b259SStefan Weil                                  QEMUTimer *timer,
724e81a982aSAlexander Graf                                  void (*raise_excp)(void *),
725e81a982aSAlexander Graf                                  void (*lower_excp)(PowerPCCPU *),
726e81a982aSAlexander Graf                                  uint32_t decr, uint32_t value)
72753018216SPaolo Bonzini {
72853018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
72953018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
73053018216SPaolo Bonzini     uint64_t now, next;
73153018216SPaolo Bonzini 
73253018216SPaolo Bonzini     LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
73353018216SPaolo Bonzini                 decr, value);
73453018216SPaolo Bonzini 
73553018216SPaolo Bonzini     if (kvm_enabled()) {
73653018216SPaolo Bonzini         /* KVM handles decrementer exceptions, we don't need our own timer */
73753018216SPaolo Bonzini         return;
73853018216SPaolo Bonzini     }
73953018216SPaolo Bonzini 
740e81a982aSAlexander Graf     /*
741e81a982aSAlexander Graf      * Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC
742e81a982aSAlexander Graf      * interrupt.
743e81a982aSAlexander Graf      *
744e81a982aSAlexander Graf      * If we get a really small DEC value, we can assume that by the time we
745e81a982aSAlexander Graf      * handled it we should inject an interrupt already.
746e81a982aSAlexander Graf      *
747e81a982aSAlexander Graf      * On MSB level based DEC implementations the MSB always means the interrupt
748e81a982aSAlexander Graf      * is pending, so raise it on those.
749e81a982aSAlexander Graf      *
750e81a982aSAlexander Graf      * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers
751e81a982aSAlexander Graf      * an edge interrupt, so raise it here too.
752e81a982aSAlexander Graf      */
753e81a982aSAlexander Graf     if ((value < 3) ||
754e81a982aSAlexander Graf         ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) ||
755e81a982aSAlexander Graf         ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000)
756e81a982aSAlexander Graf           && !(decr & 0x80000000))) {
757e81a982aSAlexander Graf         (*raise_excp)(cpu);
758e81a982aSAlexander Graf         return;
759e81a982aSAlexander Graf     }
760e81a982aSAlexander Graf 
761e81a982aSAlexander Graf     /* On MSB level based systems a 0 for the MSB stops interrupt delivery */
762e81a982aSAlexander Graf     if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) {
763e81a982aSAlexander Graf         (*lower_excp)(cpu);
764e81a982aSAlexander Graf     }
765e81a982aSAlexander Graf 
766e81a982aSAlexander Graf     /* Calculate the next timer event */
767bc72ad67SAlex Bligh     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
76873bcb24dSRutuja Shah     next = now + muldiv64(value, NANOSECONDS_PER_SECOND, tb_env->decr_freq);
76953018216SPaolo Bonzini     *nextp = next;
770e81a982aSAlexander Graf 
77153018216SPaolo Bonzini     /* Adjust timer */
772bc72ad67SAlex Bligh     timer_mod(timer, next);
77353018216SPaolo Bonzini }
77453018216SPaolo Bonzini 
77553018216SPaolo Bonzini static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
776e81a982aSAlexander Graf                                        uint32_t value)
77753018216SPaolo Bonzini {
77853018216SPaolo Bonzini     ppc_tb_t *tb_env = cpu->env.tb_env;
77953018216SPaolo Bonzini 
78053018216SPaolo Bonzini     __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
781e81a982aSAlexander Graf                          tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr,
782e81a982aSAlexander Graf                          value);
78353018216SPaolo Bonzini }
78453018216SPaolo Bonzini 
78553018216SPaolo Bonzini void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
78653018216SPaolo Bonzini {
78753018216SPaolo Bonzini     PowerPCCPU *cpu = ppc_env_get_cpu(env);
78853018216SPaolo Bonzini 
789e81a982aSAlexander Graf     _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value);
79053018216SPaolo Bonzini }
79153018216SPaolo Bonzini 
79253018216SPaolo Bonzini static void cpu_ppc_decr_cb(void *opaque)
79353018216SPaolo Bonzini {
79453018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
79553018216SPaolo Bonzini 
796e81a982aSAlexander Graf     cpu_ppc_decr_excp(cpu);
79753018216SPaolo Bonzini }
79853018216SPaolo Bonzini 
79953018216SPaolo Bonzini static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
800e81a982aSAlexander Graf                                         uint32_t value)
80153018216SPaolo Bonzini {
80253018216SPaolo Bonzini     ppc_tb_t *tb_env = cpu->env.tb_env;
80353018216SPaolo Bonzini 
80453018216SPaolo Bonzini     if (tb_env->hdecr_timer != NULL) {
80553018216SPaolo Bonzini         __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
806e81a982aSAlexander Graf                              tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower,
807e81a982aSAlexander Graf                              hdecr, value);
80853018216SPaolo Bonzini     }
80953018216SPaolo Bonzini }
81053018216SPaolo Bonzini 
81153018216SPaolo Bonzini void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
81253018216SPaolo Bonzini {
81353018216SPaolo Bonzini     PowerPCCPU *cpu = ppc_env_get_cpu(env);
81453018216SPaolo Bonzini 
815e81a982aSAlexander Graf     _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value);
81653018216SPaolo Bonzini }
81753018216SPaolo Bonzini 
81853018216SPaolo Bonzini static void cpu_ppc_hdecr_cb(void *opaque)
81953018216SPaolo Bonzini {
82053018216SPaolo Bonzini     PowerPCCPU *cpu = opaque;
82153018216SPaolo Bonzini 
822e81a982aSAlexander Graf     cpu_ppc_hdecr_excp(cpu);
82353018216SPaolo Bonzini }
82453018216SPaolo Bonzini 
82553018216SPaolo Bonzini static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
82653018216SPaolo Bonzini {
82753018216SPaolo Bonzini     ppc_tb_t *tb_env = cpu->env.tb_env;
82853018216SPaolo Bonzini 
82953018216SPaolo Bonzini     tb_env->purr_load = value;
830bc72ad67SAlex Bligh     tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
83153018216SPaolo Bonzini }
83253018216SPaolo Bonzini 
83353018216SPaolo Bonzini static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
83453018216SPaolo Bonzini {
83553018216SPaolo Bonzini     CPUPPCState *env = opaque;
83653018216SPaolo Bonzini     PowerPCCPU *cpu = ppc_env_get_cpu(env);
83753018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
83853018216SPaolo Bonzini 
83953018216SPaolo Bonzini     tb_env->tb_freq = freq;
84053018216SPaolo Bonzini     tb_env->decr_freq = freq;
84153018216SPaolo Bonzini     /* There is a bug in Linux 2.4 kernels:
84253018216SPaolo Bonzini      * if a decrementer exception is pending when it enables msr_ee at startup,
84353018216SPaolo Bonzini      * it's not ready to handle it...
84453018216SPaolo Bonzini      */
845e81a982aSAlexander Graf     _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
846e81a982aSAlexander Graf     _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF);
84753018216SPaolo Bonzini     cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
84853018216SPaolo Bonzini }
84953018216SPaolo Bonzini 
850*42043e4fSLaurent Vivier static void timebase_save(PPCTimebase *tb)
85198a8b524SAlexey Kardashevskiy {
8524a7428c5SChristopher Covington     uint64_t ticks = cpu_get_host_ticks();
85398a8b524SAlexey Kardashevskiy     PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
85498a8b524SAlexey Kardashevskiy 
85598a8b524SAlexey Kardashevskiy     if (!first_ppc_cpu->env.tb_env) {
85698a8b524SAlexey Kardashevskiy         error_report("No timebase object");
85798a8b524SAlexey Kardashevskiy         return;
85898a8b524SAlexey Kardashevskiy     }
85998a8b524SAlexey Kardashevskiy 
860*42043e4fSLaurent Vivier     /* not used anymore, we keep it for compatibility */
86177bad151SPaolo Bonzini     tb->time_of_the_day_ns = qemu_clock_get_ns(QEMU_CLOCK_HOST);
86298a8b524SAlexey Kardashevskiy     /*
863*42043e4fSLaurent Vivier      * tb_offset is only expected to be changed by QEMU so
86498a8b524SAlexey Kardashevskiy      * there is no need to update it from KVM here
86598a8b524SAlexey Kardashevskiy      */
86698a8b524SAlexey Kardashevskiy     tb->guest_timebase = ticks + first_ppc_cpu->env.tb_env->tb_offset;
86798a8b524SAlexey Kardashevskiy }
86898a8b524SAlexey Kardashevskiy 
869*42043e4fSLaurent Vivier static void timebase_load(PPCTimebase *tb)
87098a8b524SAlexey Kardashevskiy {
87198a8b524SAlexey Kardashevskiy     CPUState *cpu;
87298a8b524SAlexey Kardashevskiy     PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
873*42043e4fSLaurent Vivier     int64_t tb_off_adj, tb_off;
87498a8b524SAlexey Kardashevskiy     unsigned long freq;
87598a8b524SAlexey Kardashevskiy 
87698a8b524SAlexey Kardashevskiy     if (!first_ppc_cpu->env.tb_env) {
87798a8b524SAlexey Kardashevskiy         error_report("No timebase object");
878*42043e4fSLaurent Vivier         return;
87998a8b524SAlexey Kardashevskiy     }
88098a8b524SAlexey Kardashevskiy 
88198a8b524SAlexey Kardashevskiy     freq = first_ppc_cpu->env.tb_env->tb_freq;
88298a8b524SAlexey Kardashevskiy 
883*42043e4fSLaurent Vivier     tb_off_adj = tb->guest_timebase - cpu_get_host_ticks();
88498a8b524SAlexey Kardashevskiy 
88598a8b524SAlexey Kardashevskiy     tb_off = first_ppc_cpu->env.tb_env->tb_offset;
88698a8b524SAlexey Kardashevskiy     trace_ppc_tb_adjust(tb_off, tb_off_adj, tb_off_adj - tb_off,
88798a8b524SAlexey Kardashevskiy                         (tb_off_adj - tb_off) / freq);
88898a8b524SAlexey Kardashevskiy 
88998a8b524SAlexey Kardashevskiy     /* Set new offset to all CPUs */
89098a8b524SAlexey Kardashevskiy     CPU_FOREACH(cpu) {
89198a8b524SAlexey Kardashevskiy         PowerPCCPU *pcpu = POWERPC_CPU(cpu);
89298a8b524SAlexey Kardashevskiy         pcpu->env.tb_env->tb_offset = tb_off_adj;
893*42043e4fSLaurent Vivier #if defined(CONFIG_KVM)
894*42043e4fSLaurent Vivier         kvm_set_one_reg(cpu, KVM_REG_PPC_TB_OFFSET,
895*42043e4fSLaurent Vivier                         &pcpu->env.tb_env->tb_offset);
896*42043e4fSLaurent Vivier #endif
897*42043e4fSLaurent Vivier     }
89898a8b524SAlexey Kardashevskiy }
89998a8b524SAlexey Kardashevskiy 
900*42043e4fSLaurent Vivier void cpu_ppc_clock_vm_state_change(void *opaque, int running,
901*42043e4fSLaurent Vivier                                    RunState state)
902*42043e4fSLaurent Vivier {
903*42043e4fSLaurent Vivier     PPCTimebase *tb = opaque;
904*42043e4fSLaurent Vivier 
905*42043e4fSLaurent Vivier     if (running) {
906*42043e4fSLaurent Vivier         timebase_load(tb);
907*42043e4fSLaurent Vivier     } else {
908*42043e4fSLaurent Vivier         timebase_save(tb);
909*42043e4fSLaurent Vivier     }
910*42043e4fSLaurent Vivier }
911*42043e4fSLaurent Vivier 
912*42043e4fSLaurent Vivier /*
913*42043e4fSLaurent Vivier  * When migrating, read the clock just before migration,
914*42043e4fSLaurent Vivier  * so that the guest clock counts during the events
915*42043e4fSLaurent Vivier  * between:
916*42043e4fSLaurent Vivier  *
917*42043e4fSLaurent Vivier  *  * vm_stop()
918*42043e4fSLaurent Vivier  *  *
919*42043e4fSLaurent Vivier  *  * pre_save()
920*42043e4fSLaurent Vivier  *
921*42043e4fSLaurent Vivier  *  This reduces clock difference on migration from 5s
922*42043e4fSLaurent Vivier  *  to 0.1s (when max_downtime == 5s), because sending the
923*42043e4fSLaurent Vivier  *  final pages of memory (which happens between vm_stop()
924*42043e4fSLaurent Vivier  *  and pre_save()) takes max_downtime.
925*42043e4fSLaurent Vivier  */
926*42043e4fSLaurent Vivier static void timebase_pre_save(void *opaque)
927*42043e4fSLaurent Vivier {
928*42043e4fSLaurent Vivier     PPCTimebase *tb = opaque;
929*42043e4fSLaurent Vivier 
930*42043e4fSLaurent Vivier     timebase_save(tb);
93198a8b524SAlexey Kardashevskiy }
93298a8b524SAlexey Kardashevskiy 
93398a8b524SAlexey Kardashevskiy const VMStateDescription vmstate_ppc_timebase = {
93498a8b524SAlexey Kardashevskiy     .name = "timebase",
93598a8b524SAlexey Kardashevskiy     .version_id = 1,
93698a8b524SAlexey Kardashevskiy     .minimum_version_id = 1,
93798a8b524SAlexey Kardashevskiy     .minimum_version_id_old = 1,
93898a8b524SAlexey Kardashevskiy     .pre_save = timebase_pre_save,
93998a8b524SAlexey Kardashevskiy     .fields      = (VMStateField []) {
94098a8b524SAlexey Kardashevskiy         VMSTATE_UINT64(guest_timebase, PPCTimebase),
94198a8b524SAlexey Kardashevskiy         VMSTATE_INT64(time_of_the_day_ns, PPCTimebase),
94298a8b524SAlexey Kardashevskiy         VMSTATE_END_OF_LIST()
94398a8b524SAlexey Kardashevskiy     },
94498a8b524SAlexey Kardashevskiy };
94598a8b524SAlexey Kardashevskiy 
94653018216SPaolo Bonzini /* Set up (once) timebase frequency (in Hz) */
94753018216SPaolo Bonzini clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
94853018216SPaolo Bonzini {
94953018216SPaolo Bonzini     PowerPCCPU *cpu = ppc_env_get_cpu(env);
95053018216SPaolo Bonzini     ppc_tb_t *tb_env;
95153018216SPaolo Bonzini 
95253018216SPaolo Bonzini     tb_env = g_malloc0(sizeof(ppc_tb_t));
95353018216SPaolo Bonzini     env->tb_env = tb_env;
95453018216SPaolo Bonzini     tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
955e81a982aSAlexander Graf     if (env->insns_flags & PPC_SEGMENT_64B) {
956e81a982aSAlexander Graf         /* All Book3S 64bit CPUs implement level based DEC logic */
957e81a982aSAlexander Graf         tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL;
958e81a982aSAlexander Graf     }
95953018216SPaolo Bonzini     /* Create new timer */
960bc72ad67SAlex Bligh     tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
9614b236b62SBenjamin Herrenschmidt     if (env->has_hv_mode) {
962bc72ad67SAlex Bligh         tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb,
96353018216SPaolo Bonzini                                                 cpu);
96453018216SPaolo Bonzini     } else {
96553018216SPaolo Bonzini         tb_env->hdecr_timer = NULL;
96653018216SPaolo Bonzini     }
96753018216SPaolo Bonzini     cpu_ppc_set_tb_clk(env, freq);
96853018216SPaolo Bonzini 
96953018216SPaolo Bonzini     return &cpu_ppc_set_tb_clk;
97053018216SPaolo Bonzini }
97153018216SPaolo Bonzini 
97253018216SPaolo Bonzini /* Specific helpers for POWER & PowerPC 601 RTC */
97353018216SPaolo Bonzini void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
97453018216SPaolo Bonzini {
97553018216SPaolo Bonzini     _cpu_ppc_store_tbu(env, value);
97653018216SPaolo Bonzini }
97753018216SPaolo Bonzini 
97853018216SPaolo Bonzini uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
97953018216SPaolo Bonzini {
98053018216SPaolo Bonzini     return _cpu_ppc_load_tbu(env);
98153018216SPaolo Bonzini }
98253018216SPaolo Bonzini 
98353018216SPaolo Bonzini void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
98453018216SPaolo Bonzini {
98553018216SPaolo Bonzini     cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
98653018216SPaolo Bonzini }
98753018216SPaolo Bonzini 
98853018216SPaolo Bonzini uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
98953018216SPaolo Bonzini {
99053018216SPaolo Bonzini     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
99153018216SPaolo Bonzini }
99253018216SPaolo Bonzini 
99353018216SPaolo Bonzini /*****************************************************************************/
99453018216SPaolo Bonzini /* PowerPC 40x timers */
99553018216SPaolo Bonzini 
99653018216SPaolo Bonzini /* PIT, FIT & WDT */
99753018216SPaolo Bonzini typedef struct ppc40x_timer_t ppc40x_timer_t;
99853018216SPaolo Bonzini struct ppc40x_timer_t {
99953018216SPaolo Bonzini     uint64_t pit_reload;  /* PIT auto-reload value        */
100053018216SPaolo Bonzini     uint64_t fit_next;    /* Tick for next FIT interrupt  */
10011246b259SStefan Weil     QEMUTimer *fit_timer;
100253018216SPaolo Bonzini     uint64_t wdt_next;    /* Tick for next WDT interrupt  */
10031246b259SStefan Weil     QEMUTimer *wdt_timer;
100453018216SPaolo Bonzini 
100553018216SPaolo Bonzini     /* 405 have the PIT, 440 have a DECR.  */
100653018216SPaolo Bonzini     unsigned int decr_excp;
100753018216SPaolo Bonzini };
100853018216SPaolo Bonzini 
100953018216SPaolo Bonzini /* Fixed interval timer */
101053018216SPaolo Bonzini static void cpu_4xx_fit_cb (void *opaque)
101153018216SPaolo Bonzini {
101253018216SPaolo Bonzini     PowerPCCPU *cpu;
101353018216SPaolo Bonzini     CPUPPCState *env;
101453018216SPaolo Bonzini     ppc_tb_t *tb_env;
101553018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
101653018216SPaolo Bonzini     uint64_t now, next;
101753018216SPaolo Bonzini 
101853018216SPaolo Bonzini     env = opaque;
101953018216SPaolo Bonzini     cpu = ppc_env_get_cpu(env);
102053018216SPaolo Bonzini     tb_env = env->tb_env;
102153018216SPaolo Bonzini     ppc40x_timer = tb_env->opaque;
1022bc72ad67SAlex Bligh     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
102353018216SPaolo Bonzini     switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
102453018216SPaolo Bonzini     case 0:
102553018216SPaolo Bonzini         next = 1 << 9;
102653018216SPaolo Bonzini         break;
102753018216SPaolo Bonzini     case 1:
102853018216SPaolo Bonzini         next = 1 << 13;
102953018216SPaolo Bonzini         break;
103053018216SPaolo Bonzini     case 2:
103153018216SPaolo Bonzini         next = 1 << 17;
103253018216SPaolo Bonzini         break;
103353018216SPaolo Bonzini     case 3:
103453018216SPaolo Bonzini         next = 1 << 21;
103553018216SPaolo Bonzini         break;
103653018216SPaolo Bonzini     default:
103753018216SPaolo Bonzini         /* Cannot occur, but makes gcc happy */
103853018216SPaolo Bonzini         return;
103953018216SPaolo Bonzini     }
104073bcb24dSRutuja Shah     next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->tb_freq);
104153018216SPaolo Bonzini     if (next == now)
104253018216SPaolo Bonzini         next++;
1043bc72ad67SAlex Bligh     timer_mod(ppc40x_timer->fit_timer, next);
104453018216SPaolo Bonzini     env->spr[SPR_40x_TSR] |= 1 << 26;
104553018216SPaolo Bonzini     if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
104653018216SPaolo Bonzini         ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
104753018216SPaolo Bonzini     }
104853018216SPaolo Bonzini     LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
104953018216SPaolo Bonzini            (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
105053018216SPaolo Bonzini            env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
105153018216SPaolo Bonzini }
105253018216SPaolo Bonzini 
105353018216SPaolo Bonzini /* Programmable interval timer */
105453018216SPaolo Bonzini static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
105553018216SPaolo Bonzini {
105653018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
105753018216SPaolo Bonzini     uint64_t now, next;
105853018216SPaolo Bonzini 
105953018216SPaolo Bonzini     ppc40x_timer = tb_env->opaque;
106053018216SPaolo Bonzini     if (ppc40x_timer->pit_reload <= 1 ||
106153018216SPaolo Bonzini         !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
106253018216SPaolo Bonzini         (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
106353018216SPaolo Bonzini         /* Stop PIT */
106453018216SPaolo Bonzini         LOG_TB("%s: stop PIT\n", __func__);
1065bc72ad67SAlex Bligh         timer_del(tb_env->decr_timer);
106653018216SPaolo Bonzini     } else {
106753018216SPaolo Bonzini         LOG_TB("%s: start PIT %016" PRIx64 "\n",
106853018216SPaolo Bonzini                     __func__, ppc40x_timer->pit_reload);
1069bc72ad67SAlex Bligh         now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
107053018216SPaolo Bonzini         next = now + muldiv64(ppc40x_timer->pit_reload,
107173bcb24dSRutuja Shah                               NANOSECONDS_PER_SECOND, tb_env->decr_freq);
107253018216SPaolo Bonzini         if (is_excp)
107353018216SPaolo Bonzini             next += tb_env->decr_next - now;
107453018216SPaolo Bonzini         if (next == now)
107553018216SPaolo Bonzini             next++;
1076bc72ad67SAlex Bligh         timer_mod(tb_env->decr_timer, next);
107753018216SPaolo Bonzini         tb_env->decr_next = next;
107853018216SPaolo Bonzini     }
107953018216SPaolo Bonzini }
108053018216SPaolo Bonzini 
108153018216SPaolo Bonzini static void cpu_4xx_pit_cb (void *opaque)
108253018216SPaolo Bonzini {
108353018216SPaolo Bonzini     PowerPCCPU *cpu;
108453018216SPaolo Bonzini     CPUPPCState *env;
108553018216SPaolo Bonzini     ppc_tb_t *tb_env;
108653018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
108753018216SPaolo Bonzini 
108853018216SPaolo Bonzini     env = opaque;
108953018216SPaolo Bonzini     cpu = ppc_env_get_cpu(env);
109053018216SPaolo Bonzini     tb_env = env->tb_env;
109153018216SPaolo Bonzini     ppc40x_timer = tb_env->opaque;
109253018216SPaolo Bonzini     env->spr[SPR_40x_TSR] |= 1 << 27;
109353018216SPaolo Bonzini     if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
109453018216SPaolo Bonzini         ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
109553018216SPaolo Bonzini     }
109653018216SPaolo Bonzini     start_stop_pit(env, tb_env, 1);
109753018216SPaolo Bonzini     LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
109853018216SPaolo Bonzini            "%016" PRIx64 "\n", __func__,
109953018216SPaolo Bonzini            (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
110053018216SPaolo Bonzini            (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
110153018216SPaolo Bonzini            env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
110253018216SPaolo Bonzini            ppc40x_timer->pit_reload);
110353018216SPaolo Bonzini }
110453018216SPaolo Bonzini 
110553018216SPaolo Bonzini /* Watchdog timer */
110653018216SPaolo Bonzini static void cpu_4xx_wdt_cb (void *opaque)
110753018216SPaolo Bonzini {
110853018216SPaolo Bonzini     PowerPCCPU *cpu;
110953018216SPaolo Bonzini     CPUPPCState *env;
111053018216SPaolo Bonzini     ppc_tb_t *tb_env;
111153018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
111253018216SPaolo Bonzini     uint64_t now, next;
111353018216SPaolo Bonzini 
111453018216SPaolo Bonzini     env = opaque;
111553018216SPaolo Bonzini     cpu = ppc_env_get_cpu(env);
111653018216SPaolo Bonzini     tb_env = env->tb_env;
111753018216SPaolo Bonzini     ppc40x_timer = tb_env->opaque;
1118bc72ad67SAlex Bligh     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
111953018216SPaolo Bonzini     switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
112053018216SPaolo Bonzini     case 0:
112153018216SPaolo Bonzini         next = 1 << 17;
112253018216SPaolo Bonzini         break;
112353018216SPaolo Bonzini     case 1:
112453018216SPaolo Bonzini         next = 1 << 21;
112553018216SPaolo Bonzini         break;
112653018216SPaolo Bonzini     case 2:
112753018216SPaolo Bonzini         next = 1 << 25;
112853018216SPaolo Bonzini         break;
112953018216SPaolo Bonzini     case 3:
113053018216SPaolo Bonzini         next = 1 << 29;
113153018216SPaolo Bonzini         break;
113253018216SPaolo Bonzini     default:
113353018216SPaolo Bonzini         /* Cannot occur, but makes gcc happy */
113453018216SPaolo Bonzini         return;
113553018216SPaolo Bonzini     }
113673bcb24dSRutuja Shah     next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->decr_freq);
113753018216SPaolo Bonzini     if (next == now)
113853018216SPaolo Bonzini         next++;
113953018216SPaolo Bonzini     LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
114053018216SPaolo Bonzini            env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
114153018216SPaolo Bonzini     switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
114253018216SPaolo Bonzini     case 0x0:
114353018216SPaolo Bonzini     case 0x1:
1144bc72ad67SAlex Bligh         timer_mod(ppc40x_timer->wdt_timer, next);
114553018216SPaolo Bonzini         ppc40x_timer->wdt_next = next;
1146a1f7f97bSPeter Maydell         env->spr[SPR_40x_TSR] |= 1U << 31;
114753018216SPaolo Bonzini         break;
114853018216SPaolo Bonzini     case 0x2:
1149bc72ad67SAlex Bligh         timer_mod(ppc40x_timer->wdt_timer, next);
115053018216SPaolo Bonzini         ppc40x_timer->wdt_next = next;
115153018216SPaolo Bonzini         env->spr[SPR_40x_TSR] |= 1 << 30;
115253018216SPaolo Bonzini         if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
115353018216SPaolo Bonzini             ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
115453018216SPaolo Bonzini         }
115553018216SPaolo Bonzini         break;
115653018216SPaolo Bonzini     case 0x3:
115753018216SPaolo Bonzini         env->spr[SPR_40x_TSR] &= ~0x30000000;
115853018216SPaolo Bonzini         env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
115953018216SPaolo Bonzini         switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
116053018216SPaolo Bonzini         case 0x0:
116153018216SPaolo Bonzini             /* No reset */
116253018216SPaolo Bonzini             break;
116353018216SPaolo Bonzini         case 0x1: /* Core reset */
116453018216SPaolo Bonzini             ppc40x_core_reset(cpu);
116553018216SPaolo Bonzini             break;
116653018216SPaolo Bonzini         case 0x2: /* Chip reset */
116753018216SPaolo Bonzini             ppc40x_chip_reset(cpu);
116853018216SPaolo Bonzini             break;
116953018216SPaolo Bonzini         case 0x3: /* System reset */
117053018216SPaolo Bonzini             ppc40x_system_reset(cpu);
117153018216SPaolo Bonzini             break;
117253018216SPaolo Bonzini         }
117353018216SPaolo Bonzini     }
117453018216SPaolo Bonzini }
117553018216SPaolo Bonzini 
117653018216SPaolo Bonzini void store_40x_pit (CPUPPCState *env, target_ulong val)
117753018216SPaolo Bonzini {
117853018216SPaolo Bonzini     ppc_tb_t *tb_env;
117953018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
118053018216SPaolo Bonzini 
118153018216SPaolo Bonzini     tb_env = env->tb_env;
118253018216SPaolo Bonzini     ppc40x_timer = tb_env->opaque;
118353018216SPaolo Bonzini     LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
118453018216SPaolo Bonzini     ppc40x_timer->pit_reload = val;
118553018216SPaolo Bonzini     start_stop_pit(env, tb_env, 0);
118653018216SPaolo Bonzini }
118753018216SPaolo Bonzini 
118853018216SPaolo Bonzini target_ulong load_40x_pit (CPUPPCState *env)
118953018216SPaolo Bonzini {
119053018216SPaolo Bonzini     return cpu_ppc_load_decr(env);
119153018216SPaolo Bonzini }
119253018216SPaolo Bonzini 
119353018216SPaolo Bonzini static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
119453018216SPaolo Bonzini {
119553018216SPaolo Bonzini     CPUPPCState *env = opaque;
119653018216SPaolo Bonzini     ppc_tb_t *tb_env = env->tb_env;
119753018216SPaolo Bonzini 
119853018216SPaolo Bonzini     LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
119953018216SPaolo Bonzini                 freq);
120053018216SPaolo Bonzini     tb_env->tb_freq = freq;
120153018216SPaolo Bonzini     tb_env->decr_freq = freq;
120253018216SPaolo Bonzini     /* XXX: we should also update all timers */
120353018216SPaolo Bonzini }
120453018216SPaolo Bonzini 
120553018216SPaolo Bonzini clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
120653018216SPaolo Bonzini                                   unsigned int decr_excp)
120753018216SPaolo Bonzini {
120853018216SPaolo Bonzini     ppc_tb_t *tb_env;
120953018216SPaolo Bonzini     ppc40x_timer_t *ppc40x_timer;
121053018216SPaolo Bonzini 
121153018216SPaolo Bonzini     tb_env = g_malloc0(sizeof(ppc_tb_t));
121253018216SPaolo Bonzini     env->tb_env = tb_env;
121353018216SPaolo Bonzini     tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
121453018216SPaolo Bonzini     ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
121553018216SPaolo Bonzini     tb_env->tb_freq = freq;
121653018216SPaolo Bonzini     tb_env->decr_freq = freq;
121753018216SPaolo Bonzini     tb_env->opaque = ppc40x_timer;
121853018216SPaolo Bonzini     LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
121953018216SPaolo Bonzini     if (ppc40x_timer != NULL) {
122053018216SPaolo Bonzini         /* We use decr timer for PIT */
1221bc72ad67SAlex Bligh         tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env);
122253018216SPaolo Bonzini         ppc40x_timer->fit_timer =
1223bc72ad67SAlex Bligh             timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env);
122453018216SPaolo Bonzini         ppc40x_timer->wdt_timer =
1225bc72ad67SAlex Bligh             timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env);
122653018216SPaolo Bonzini         ppc40x_timer->decr_excp = decr_excp;
122753018216SPaolo Bonzini     }
122853018216SPaolo Bonzini 
122953018216SPaolo Bonzini     return &ppc_40x_set_tb_clk;
123053018216SPaolo Bonzini }
123153018216SPaolo Bonzini 
123253018216SPaolo Bonzini /*****************************************************************************/
123353018216SPaolo Bonzini /* Embedded PowerPC Device Control Registers */
123453018216SPaolo Bonzini typedef struct ppc_dcrn_t ppc_dcrn_t;
123553018216SPaolo Bonzini struct ppc_dcrn_t {
123653018216SPaolo Bonzini     dcr_read_cb dcr_read;
123753018216SPaolo Bonzini     dcr_write_cb dcr_write;
123853018216SPaolo Bonzini     void *opaque;
123953018216SPaolo Bonzini };
124053018216SPaolo Bonzini 
124153018216SPaolo Bonzini /* XXX: on 460, DCR addresses are 32 bits wide,
124253018216SPaolo Bonzini  *      using DCRIPR to get the 22 upper bits of the DCR address
124353018216SPaolo Bonzini  */
124453018216SPaolo Bonzini #define DCRN_NB 1024
124553018216SPaolo Bonzini struct ppc_dcr_t {
124653018216SPaolo Bonzini     ppc_dcrn_t dcrn[DCRN_NB];
124753018216SPaolo Bonzini     int (*read_error)(int dcrn);
124853018216SPaolo Bonzini     int (*write_error)(int dcrn);
124953018216SPaolo Bonzini };
125053018216SPaolo Bonzini 
125153018216SPaolo Bonzini int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
125253018216SPaolo Bonzini {
125353018216SPaolo Bonzini     ppc_dcrn_t *dcr;
125453018216SPaolo Bonzini 
125553018216SPaolo Bonzini     if (dcrn < 0 || dcrn >= DCRN_NB)
125653018216SPaolo Bonzini         goto error;
125753018216SPaolo Bonzini     dcr = &dcr_env->dcrn[dcrn];
125853018216SPaolo Bonzini     if (dcr->dcr_read == NULL)
125953018216SPaolo Bonzini         goto error;
126053018216SPaolo Bonzini     *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
126153018216SPaolo Bonzini 
126253018216SPaolo Bonzini     return 0;
126353018216SPaolo Bonzini 
126453018216SPaolo Bonzini  error:
126553018216SPaolo Bonzini     if (dcr_env->read_error != NULL)
126653018216SPaolo Bonzini         return (*dcr_env->read_error)(dcrn);
126753018216SPaolo Bonzini 
126853018216SPaolo Bonzini     return -1;
126953018216SPaolo Bonzini }
127053018216SPaolo Bonzini 
127153018216SPaolo Bonzini int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
127253018216SPaolo Bonzini {
127353018216SPaolo Bonzini     ppc_dcrn_t *dcr;
127453018216SPaolo Bonzini 
127553018216SPaolo Bonzini     if (dcrn < 0 || dcrn >= DCRN_NB)
127653018216SPaolo Bonzini         goto error;
127753018216SPaolo Bonzini     dcr = &dcr_env->dcrn[dcrn];
127853018216SPaolo Bonzini     if (dcr->dcr_write == NULL)
127953018216SPaolo Bonzini         goto error;
128053018216SPaolo Bonzini     (*dcr->dcr_write)(dcr->opaque, dcrn, val);
128153018216SPaolo Bonzini 
128253018216SPaolo Bonzini     return 0;
128353018216SPaolo Bonzini 
128453018216SPaolo Bonzini  error:
128553018216SPaolo Bonzini     if (dcr_env->write_error != NULL)
128653018216SPaolo Bonzini         return (*dcr_env->write_error)(dcrn);
128753018216SPaolo Bonzini 
128853018216SPaolo Bonzini     return -1;
128953018216SPaolo Bonzini }
129053018216SPaolo Bonzini 
129153018216SPaolo Bonzini int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
129253018216SPaolo Bonzini                       dcr_read_cb dcr_read, dcr_write_cb dcr_write)
129353018216SPaolo Bonzini {
129453018216SPaolo Bonzini     ppc_dcr_t *dcr_env;
129553018216SPaolo Bonzini     ppc_dcrn_t *dcr;
129653018216SPaolo Bonzini 
129753018216SPaolo Bonzini     dcr_env = env->dcr_env;
129853018216SPaolo Bonzini     if (dcr_env == NULL)
129953018216SPaolo Bonzini         return -1;
130053018216SPaolo Bonzini     if (dcrn < 0 || dcrn >= DCRN_NB)
130153018216SPaolo Bonzini         return -1;
130253018216SPaolo Bonzini     dcr = &dcr_env->dcrn[dcrn];
130353018216SPaolo Bonzini     if (dcr->opaque != NULL ||
130453018216SPaolo Bonzini         dcr->dcr_read != NULL ||
130553018216SPaolo Bonzini         dcr->dcr_write != NULL)
130653018216SPaolo Bonzini         return -1;
130753018216SPaolo Bonzini     dcr->opaque = opaque;
130853018216SPaolo Bonzini     dcr->dcr_read = dcr_read;
130953018216SPaolo Bonzini     dcr->dcr_write = dcr_write;
131053018216SPaolo Bonzini 
131153018216SPaolo Bonzini     return 0;
131253018216SPaolo Bonzini }
131353018216SPaolo Bonzini 
131453018216SPaolo Bonzini int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
131553018216SPaolo Bonzini                   int (*write_error)(int dcrn))
131653018216SPaolo Bonzini {
131753018216SPaolo Bonzini     ppc_dcr_t *dcr_env;
131853018216SPaolo Bonzini 
131953018216SPaolo Bonzini     dcr_env = g_malloc0(sizeof(ppc_dcr_t));
132053018216SPaolo Bonzini     dcr_env->read_error = read_error;
132153018216SPaolo Bonzini     dcr_env->write_error = write_error;
132253018216SPaolo Bonzini     env->dcr_env = dcr_env;
132353018216SPaolo Bonzini 
132453018216SPaolo Bonzini     return 0;
132553018216SPaolo Bonzini }
132653018216SPaolo Bonzini 
132753018216SPaolo Bonzini /*****************************************************************************/
132853018216SPaolo Bonzini /* Debug port */
132953018216SPaolo Bonzini void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
133053018216SPaolo Bonzini {
133153018216SPaolo Bonzini     addr &= 0xF;
133253018216SPaolo Bonzini     switch (addr) {
133353018216SPaolo Bonzini     case 0:
133453018216SPaolo Bonzini         printf("%c", val);
133553018216SPaolo Bonzini         break;
133653018216SPaolo Bonzini     case 1:
133753018216SPaolo Bonzini         printf("\n");
133853018216SPaolo Bonzini         fflush(stdout);
133953018216SPaolo Bonzini         break;
134053018216SPaolo Bonzini     case 2:
134153018216SPaolo Bonzini         printf("Set loglevel to %04" PRIx32 "\n", val);
134253018216SPaolo Bonzini         qemu_set_log(val | 0x100);
134353018216SPaolo Bonzini         break;
134453018216SPaolo Bonzini     }
134553018216SPaolo Bonzini }
134653018216SPaolo Bonzini 
13470ce470cdSAlexey Kardashevskiy /* CPU device-tree ID helpers */
13480ce470cdSAlexey Kardashevskiy int ppc_get_vcpu_dt_id(PowerPCCPU *cpu)
13490ce470cdSAlexey Kardashevskiy {
13500ce470cdSAlexey Kardashevskiy     return cpu->cpu_dt_id;
13510ce470cdSAlexey Kardashevskiy }
13520ce470cdSAlexey Kardashevskiy 
13530ce470cdSAlexey Kardashevskiy PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id)
13540ce470cdSAlexey Kardashevskiy {
13550ce470cdSAlexey Kardashevskiy     CPUState *cs;
13560ce470cdSAlexey Kardashevskiy 
13570ce470cdSAlexey Kardashevskiy     CPU_FOREACH(cs) {
13580ce470cdSAlexey Kardashevskiy         PowerPCCPU *cpu = POWERPC_CPU(cs);
13590ce470cdSAlexey Kardashevskiy 
13600ce470cdSAlexey Kardashevskiy         if (cpu->cpu_dt_id == cpu_dt_id) {
13610ce470cdSAlexey Kardashevskiy             return cpu;
13620ce470cdSAlexey Kardashevskiy         }
13630ce470cdSAlexey Kardashevskiy     }
13640ce470cdSAlexey Kardashevskiy 
13650ce470cdSAlexey Kardashevskiy     return NULL;
13660ce470cdSAlexey Kardashevskiy }
1367e703d2f7SGreg Kurz 
1368e703d2f7SGreg Kurz void ppc_cpu_parse_features(const char *cpu_model)
1369e703d2f7SGreg Kurz {
1370e703d2f7SGreg Kurz     CPUClass *cc;
1371e703d2f7SGreg Kurz     ObjectClass *oc;
1372e703d2f7SGreg Kurz     const char *typename;
1373e703d2f7SGreg Kurz     gchar **model_pieces;
1374e703d2f7SGreg Kurz 
1375e703d2f7SGreg Kurz     model_pieces = g_strsplit(cpu_model, ",", 2);
1376e703d2f7SGreg Kurz     if (!model_pieces[0]) {
1377e703d2f7SGreg Kurz         error_report("Invalid/empty CPU model name");
1378e703d2f7SGreg Kurz         exit(1);
1379e703d2f7SGreg Kurz     }
1380e703d2f7SGreg Kurz 
1381e703d2f7SGreg Kurz     oc = cpu_class_by_name(TYPE_POWERPC_CPU, model_pieces[0]);
1382e703d2f7SGreg Kurz     if (oc == NULL) {
1383e703d2f7SGreg Kurz         error_report("Unable to find CPU definition: %s", model_pieces[0]);
1384e703d2f7SGreg Kurz         exit(1);
1385e703d2f7SGreg Kurz     }
1386e703d2f7SGreg Kurz 
1387e703d2f7SGreg Kurz     typename = object_class_get_name(oc);
1388e703d2f7SGreg Kurz     cc = CPU_CLASS(oc);
1389e703d2f7SGreg Kurz     cc->parse_features(typename, model_pieces[1], &error_fatal);
1390e703d2f7SGreg Kurz     g_strfreev(model_pieces);
1391e703d2f7SGreg Kurz }
1392