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; 65*8d04fb55SJan Kiszka unsigned int old_pending; 66*8d04fb55SJan Kiszka bool locked = false; 67*8d04fb55SJan Kiszka 68*8d04fb55SJan Kiszka /* We may already have the BQL if coming from the reset path */ 69*8d04fb55SJan Kiszka if (!qemu_mutex_iothread_locked()) { 70*8d04fb55SJan Kiszka locked = true; 71*8d04fb55SJan Kiszka qemu_mutex_lock_iothread(); 72*8d04fb55SJan Kiszka } 73*8d04fb55SJan Kiszka 74*8d04fb55SJan Kiszka old_pending = env->pending_interrupts; 7553018216SPaolo Bonzini 7653018216SPaolo Bonzini if (level) { 7753018216SPaolo Bonzini env->pending_interrupts |= 1 << n_IRQ; 78c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_HARD); 7953018216SPaolo Bonzini } else { 8053018216SPaolo Bonzini env->pending_interrupts &= ~(1 << n_IRQ); 81d8ed887bSAndreas Färber if (env->pending_interrupts == 0) { 82d8ed887bSAndreas Färber cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 83d8ed887bSAndreas Färber } 8453018216SPaolo Bonzini } 8553018216SPaolo Bonzini 8653018216SPaolo Bonzini if (old_pending != env->pending_interrupts) { 8753018216SPaolo Bonzini #ifdef CONFIG_KVM 8853018216SPaolo Bonzini kvmppc_set_interrupt(cpu, n_IRQ, level); 8953018216SPaolo Bonzini #endif 9053018216SPaolo Bonzini } 9153018216SPaolo Bonzini 92*8d04fb55SJan Kiszka 9353018216SPaolo Bonzini LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32 9453018216SPaolo Bonzini "req %08x\n", __func__, env, n_IRQ, level, 95259186a7SAndreas Färber env->pending_interrupts, CPU(cpu)->interrupt_request); 96*8d04fb55SJan Kiszka 97*8d04fb55SJan Kiszka if (locked) { 98*8d04fb55SJan Kiszka qemu_mutex_unlock_iothread(); 99*8d04fb55SJan Kiszka } 10053018216SPaolo Bonzini } 10153018216SPaolo Bonzini 10253018216SPaolo Bonzini /* PowerPC 6xx / 7xx internal IRQ controller */ 10353018216SPaolo Bonzini static void ppc6xx_set_irq(void *opaque, int pin, int level) 10453018216SPaolo Bonzini { 10553018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 10653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 10753018216SPaolo Bonzini int cur_level; 10853018216SPaolo Bonzini 10953018216SPaolo Bonzini LOG_IRQ("%s: env %p pin %d level %d\n", __func__, 11053018216SPaolo Bonzini env, pin, level); 11153018216SPaolo Bonzini cur_level = (env->irq_input_state >> pin) & 1; 11253018216SPaolo Bonzini /* Don't generate spurious events */ 11353018216SPaolo Bonzini if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { 114259186a7SAndreas Färber CPUState *cs = CPU(cpu); 115259186a7SAndreas Färber 11653018216SPaolo Bonzini switch (pin) { 11753018216SPaolo Bonzini case PPC6xx_INPUT_TBEN: 11853018216SPaolo Bonzini /* Level sensitive - active high */ 11953018216SPaolo Bonzini LOG_IRQ("%s: %s the time base\n", 12053018216SPaolo Bonzini __func__, level ? "start" : "stop"); 12153018216SPaolo Bonzini if (level) { 12253018216SPaolo Bonzini cpu_ppc_tb_start(env); 12353018216SPaolo Bonzini } else { 12453018216SPaolo Bonzini cpu_ppc_tb_stop(env); 12553018216SPaolo Bonzini } 12653018216SPaolo Bonzini case PPC6xx_INPUT_INT: 12753018216SPaolo Bonzini /* Level sensitive - active high */ 12853018216SPaolo Bonzini LOG_IRQ("%s: set the external IRQ state to %d\n", 12953018216SPaolo Bonzini __func__, level); 13053018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); 13153018216SPaolo Bonzini break; 13253018216SPaolo Bonzini case PPC6xx_INPUT_SMI: 13353018216SPaolo Bonzini /* Level sensitive - active high */ 13453018216SPaolo Bonzini LOG_IRQ("%s: set the SMI IRQ state to %d\n", 13553018216SPaolo Bonzini __func__, level); 13653018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level); 13753018216SPaolo Bonzini break; 13853018216SPaolo Bonzini case PPC6xx_INPUT_MCP: 13953018216SPaolo Bonzini /* Negative edge sensitive */ 14053018216SPaolo Bonzini /* XXX: TODO: actual reaction may depends on HID0 status 14153018216SPaolo Bonzini * 603/604/740/750: check HID0[EMCP] 14253018216SPaolo Bonzini */ 14353018216SPaolo Bonzini if (cur_level == 1 && level == 0) { 14453018216SPaolo Bonzini LOG_IRQ("%s: raise machine check state\n", 14553018216SPaolo Bonzini __func__); 14653018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1); 14753018216SPaolo Bonzini } 14853018216SPaolo Bonzini break; 14953018216SPaolo Bonzini case PPC6xx_INPUT_CKSTP_IN: 15053018216SPaolo Bonzini /* Level sensitive - active low */ 15153018216SPaolo Bonzini /* XXX: TODO: relay the signal to CKSTP_OUT pin */ 15253018216SPaolo Bonzini /* XXX: Note that the only way to restart the CPU is to reset it */ 15353018216SPaolo Bonzini if (level) { 15453018216SPaolo Bonzini LOG_IRQ("%s: stop the CPU\n", __func__); 155259186a7SAndreas Färber cs->halted = 1; 15653018216SPaolo Bonzini } 15753018216SPaolo Bonzini break; 15853018216SPaolo Bonzini case PPC6xx_INPUT_HRESET: 15953018216SPaolo Bonzini /* Level sensitive - active low */ 16053018216SPaolo Bonzini if (level) { 16153018216SPaolo Bonzini LOG_IRQ("%s: reset the CPU\n", __func__); 162c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_RESET); 16353018216SPaolo Bonzini } 16453018216SPaolo Bonzini break; 16553018216SPaolo Bonzini case PPC6xx_INPUT_SRESET: 16653018216SPaolo Bonzini LOG_IRQ("%s: set the RESET IRQ state to %d\n", 16753018216SPaolo Bonzini __func__, level); 16853018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level); 16953018216SPaolo Bonzini break; 17053018216SPaolo Bonzini default: 17153018216SPaolo Bonzini /* Unknown pin - do nothing */ 17253018216SPaolo Bonzini LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); 17353018216SPaolo Bonzini return; 17453018216SPaolo Bonzini } 17553018216SPaolo Bonzini if (level) 17653018216SPaolo Bonzini env->irq_input_state |= 1 << pin; 17753018216SPaolo Bonzini else 17853018216SPaolo Bonzini env->irq_input_state &= ~(1 << pin); 17953018216SPaolo Bonzini } 18053018216SPaolo Bonzini } 18153018216SPaolo Bonzini 182aa5a9e24SPaolo Bonzini void ppc6xx_irq_init(PowerPCCPU *cpu) 18353018216SPaolo Bonzini { 184aa5a9e24SPaolo Bonzini CPUPPCState *env = &cpu->env; 18553018216SPaolo Bonzini 18653018216SPaolo Bonzini env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu, 18753018216SPaolo Bonzini PPC6xx_INPUT_NB); 18853018216SPaolo Bonzini } 18953018216SPaolo Bonzini 19053018216SPaolo Bonzini #if defined(TARGET_PPC64) 19153018216SPaolo Bonzini /* PowerPC 970 internal IRQ controller */ 19253018216SPaolo Bonzini static void ppc970_set_irq(void *opaque, int pin, int level) 19353018216SPaolo Bonzini { 19453018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 19553018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 19653018216SPaolo Bonzini int cur_level; 19753018216SPaolo Bonzini 19853018216SPaolo Bonzini LOG_IRQ("%s: env %p pin %d level %d\n", __func__, 19953018216SPaolo Bonzini env, pin, level); 20053018216SPaolo Bonzini cur_level = (env->irq_input_state >> pin) & 1; 20153018216SPaolo Bonzini /* Don't generate spurious events */ 20253018216SPaolo Bonzini if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { 203259186a7SAndreas Färber CPUState *cs = CPU(cpu); 204259186a7SAndreas Färber 20553018216SPaolo Bonzini switch (pin) { 20653018216SPaolo Bonzini case PPC970_INPUT_INT: 20753018216SPaolo Bonzini /* Level sensitive - active high */ 20853018216SPaolo Bonzini LOG_IRQ("%s: set the external IRQ state to %d\n", 20953018216SPaolo Bonzini __func__, level); 21053018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); 21153018216SPaolo Bonzini break; 21253018216SPaolo Bonzini case PPC970_INPUT_THINT: 21353018216SPaolo Bonzini /* Level sensitive - active high */ 21453018216SPaolo Bonzini LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__, 21553018216SPaolo Bonzini level); 21653018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level); 21753018216SPaolo Bonzini break; 21853018216SPaolo Bonzini case PPC970_INPUT_MCP: 21953018216SPaolo Bonzini /* Negative edge sensitive */ 22053018216SPaolo Bonzini /* XXX: TODO: actual reaction may depends on HID0 status 22153018216SPaolo Bonzini * 603/604/740/750: check HID0[EMCP] 22253018216SPaolo Bonzini */ 22353018216SPaolo Bonzini if (cur_level == 1 && level == 0) { 22453018216SPaolo Bonzini LOG_IRQ("%s: raise machine check state\n", 22553018216SPaolo Bonzini __func__); 22653018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1); 22753018216SPaolo Bonzini } 22853018216SPaolo Bonzini break; 22953018216SPaolo Bonzini case PPC970_INPUT_CKSTP: 23053018216SPaolo Bonzini /* Level sensitive - active low */ 23153018216SPaolo Bonzini /* XXX: TODO: relay the signal to CKSTP_OUT pin */ 23253018216SPaolo Bonzini if (level) { 23353018216SPaolo Bonzini LOG_IRQ("%s: stop the CPU\n", __func__); 234259186a7SAndreas Färber cs->halted = 1; 23553018216SPaolo Bonzini } else { 23653018216SPaolo Bonzini LOG_IRQ("%s: restart the CPU\n", __func__); 237259186a7SAndreas Färber cs->halted = 0; 238259186a7SAndreas Färber qemu_cpu_kick(cs); 23953018216SPaolo Bonzini } 24053018216SPaolo Bonzini break; 24153018216SPaolo Bonzini case PPC970_INPUT_HRESET: 24253018216SPaolo Bonzini /* Level sensitive - active low */ 24353018216SPaolo Bonzini if (level) { 244c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_RESET); 24553018216SPaolo Bonzini } 24653018216SPaolo Bonzini break; 24753018216SPaolo Bonzini case PPC970_INPUT_SRESET: 24853018216SPaolo Bonzini LOG_IRQ("%s: set the RESET IRQ state to %d\n", 24953018216SPaolo Bonzini __func__, level); 25053018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level); 25153018216SPaolo Bonzini break; 25253018216SPaolo Bonzini case PPC970_INPUT_TBEN: 25353018216SPaolo Bonzini LOG_IRQ("%s: set the TBEN state to %d\n", __func__, 25453018216SPaolo Bonzini level); 25553018216SPaolo Bonzini /* XXX: TODO */ 25653018216SPaolo Bonzini break; 25753018216SPaolo Bonzini default: 25853018216SPaolo Bonzini /* Unknown pin - do nothing */ 25953018216SPaolo Bonzini LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); 26053018216SPaolo Bonzini return; 26153018216SPaolo Bonzini } 26253018216SPaolo Bonzini if (level) 26353018216SPaolo Bonzini env->irq_input_state |= 1 << pin; 26453018216SPaolo Bonzini else 26553018216SPaolo Bonzini env->irq_input_state &= ~(1 << pin); 26653018216SPaolo Bonzini } 26753018216SPaolo Bonzini } 26853018216SPaolo Bonzini 269aa5a9e24SPaolo Bonzini void ppc970_irq_init(PowerPCCPU *cpu) 27053018216SPaolo Bonzini { 271aa5a9e24SPaolo Bonzini CPUPPCState *env = &cpu->env; 27253018216SPaolo Bonzini 27353018216SPaolo Bonzini env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu, 27453018216SPaolo Bonzini PPC970_INPUT_NB); 27553018216SPaolo Bonzini } 27653018216SPaolo Bonzini 27753018216SPaolo Bonzini /* POWER7 internal IRQ controller */ 27853018216SPaolo Bonzini static void power7_set_irq(void *opaque, int pin, int level) 27953018216SPaolo Bonzini { 28053018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 28153018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 28253018216SPaolo Bonzini 28353018216SPaolo Bonzini LOG_IRQ("%s: env %p pin %d level %d\n", __func__, 28453018216SPaolo Bonzini env, pin, level); 28553018216SPaolo Bonzini 28653018216SPaolo Bonzini switch (pin) { 28753018216SPaolo Bonzini case POWER7_INPUT_INT: 28853018216SPaolo Bonzini /* Level sensitive - active high */ 28953018216SPaolo Bonzini LOG_IRQ("%s: set the external IRQ state to %d\n", 29053018216SPaolo Bonzini __func__, level); 29153018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); 29253018216SPaolo Bonzini break; 29353018216SPaolo Bonzini default: 29453018216SPaolo Bonzini /* Unknown pin - do nothing */ 29553018216SPaolo Bonzini LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); 29653018216SPaolo Bonzini return; 29753018216SPaolo Bonzini } 29853018216SPaolo Bonzini if (level) { 29953018216SPaolo Bonzini env->irq_input_state |= 1 << pin; 30053018216SPaolo Bonzini } else { 30153018216SPaolo Bonzini env->irq_input_state &= ~(1 << pin); 30253018216SPaolo Bonzini } 30353018216SPaolo Bonzini } 30453018216SPaolo Bonzini 305aa5a9e24SPaolo Bonzini void ppcPOWER7_irq_init(PowerPCCPU *cpu) 30653018216SPaolo Bonzini { 307aa5a9e24SPaolo Bonzini CPUPPCState *env = &cpu->env; 30853018216SPaolo Bonzini 30953018216SPaolo Bonzini env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu, 31053018216SPaolo Bonzini POWER7_INPUT_NB); 31153018216SPaolo Bonzini } 31253018216SPaolo Bonzini #endif /* defined(TARGET_PPC64) */ 31353018216SPaolo Bonzini 31453018216SPaolo Bonzini /* PowerPC 40x internal IRQ controller */ 31553018216SPaolo Bonzini static void ppc40x_set_irq(void *opaque, int pin, int level) 31653018216SPaolo Bonzini { 31753018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 31853018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 31953018216SPaolo Bonzini int cur_level; 32053018216SPaolo Bonzini 32153018216SPaolo Bonzini LOG_IRQ("%s: env %p pin %d level %d\n", __func__, 32253018216SPaolo Bonzini env, pin, level); 32353018216SPaolo Bonzini cur_level = (env->irq_input_state >> pin) & 1; 32453018216SPaolo Bonzini /* Don't generate spurious events */ 32553018216SPaolo Bonzini if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { 326259186a7SAndreas Färber CPUState *cs = CPU(cpu); 327259186a7SAndreas Färber 32853018216SPaolo Bonzini switch (pin) { 32953018216SPaolo Bonzini case PPC40x_INPUT_RESET_SYS: 33053018216SPaolo Bonzini if (level) { 33153018216SPaolo Bonzini LOG_IRQ("%s: reset the PowerPC system\n", 33253018216SPaolo Bonzini __func__); 33353018216SPaolo Bonzini ppc40x_system_reset(cpu); 33453018216SPaolo Bonzini } 33553018216SPaolo Bonzini break; 33653018216SPaolo Bonzini case PPC40x_INPUT_RESET_CHIP: 33753018216SPaolo Bonzini if (level) { 33853018216SPaolo Bonzini LOG_IRQ("%s: reset the PowerPC chip\n", __func__); 33953018216SPaolo Bonzini ppc40x_chip_reset(cpu); 34053018216SPaolo Bonzini } 34153018216SPaolo Bonzini break; 34253018216SPaolo Bonzini case PPC40x_INPUT_RESET_CORE: 34353018216SPaolo Bonzini /* XXX: TODO: update DBSR[MRR] */ 34453018216SPaolo Bonzini if (level) { 34553018216SPaolo Bonzini LOG_IRQ("%s: reset the PowerPC core\n", __func__); 34653018216SPaolo Bonzini ppc40x_core_reset(cpu); 34753018216SPaolo Bonzini } 34853018216SPaolo Bonzini break; 34953018216SPaolo Bonzini case PPC40x_INPUT_CINT: 35053018216SPaolo Bonzini /* Level sensitive - active high */ 35153018216SPaolo Bonzini LOG_IRQ("%s: set the critical IRQ state to %d\n", 35253018216SPaolo Bonzini __func__, level); 35353018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level); 35453018216SPaolo Bonzini break; 35553018216SPaolo Bonzini case PPC40x_INPUT_INT: 35653018216SPaolo Bonzini /* Level sensitive - active high */ 35753018216SPaolo Bonzini LOG_IRQ("%s: set the external IRQ state to %d\n", 35853018216SPaolo Bonzini __func__, level); 35953018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); 36053018216SPaolo Bonzini break; 36153018216SPaolo Bonzini case PPC40x_INPUT_HALT: 36253018216SPaolo Bonzini /* Level sensitive - active low */ 36353018216SPaolo Bonzini if (level) { 36453018216SPaolo Bonzini LOG_IRQ("%s: stop the CPU\n", __func__); 365259186a7SAndreas Färber cs->halted = 1; 36653018216SPaolo Bonzini } else { 36753018216SPaolo Bonzini LOG_IRQ("%s: restart the CPU\n", __func__); 368259186a7SAndreas Färber cs->halted = 0; 369259186a7SAndreas Färber qemu_cpu_kick(cs); 37053018216SPaolo Bonzini } 37153018216SPaolo Bonzini break; 37253018216SPaolo Bonzini case PPC40x_INPUT_DEBUG: 37353018216SPaolo Bonzini /* Level sensitive - active high */ 37453018216SPaolo Bonzini LOG_IRQ("%s: set the debug pin state to %d\n", 37553018216SPaolo Bonzini __func__, level); 37653018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level); 37753018216SPaolo Bonzini break; 37853018216SPaolo Bonzini default: 37953018216SPaolo Bonzini /* Unknown pin - do nothing */ 38053018216SPaolo Bonzini LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); 38153018216SPaolo Bonzini return; 38253018216SPaolo Bonzini } 38353018216SPaolo Bonzini if (level) 38453018216SPaolo Bonzini env->irq_input_state |= 1 << pin; 38553018216SPaolo Bonzini else 38653018216SPaolo Bonzini env->irq_input_state &= ~(1 << pin); 38753018216SPaolo Bonzini } 38853018216SPaolo Bonzini } 38953018216SPaolo Bonzini 390aa5a9e24SPaolo Bonzini void ppc40x_irq_init(PowerPCCPU *cpu) 39153018216SPaolo Bonzini { 392aa5a9e24SPaolo Bonzini CPUPPCState *env = &cpu->env; 39353018216SPaolo Bonzini 39453018216SPaolo Bonzini env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq, 39553018216SPaolo Bonzini cpu, PPC40x_INPUT_NB); 39653018216SPaolo Bonzini } 39753018216SPaolo Bonzini 39853018216SPaolo Bonzini /* PowerPC E500 internal IRQ controller */ 39953018216SPaolo Bonzini static void ppce500_set_irq(void *opaque, int pin, int level) 40053018216SPaolo Bonzini { 40153018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 40253018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 40353018216SPaolo Bonzini int cur_level; 40453018216SPaolo Bonzini 40553018216SPaolo Bonzini LOG_IRQ("%s: env %p pin %d level %d\n", __func__, 40653018216SPaolo Bonzini env, pin, level); 40753018216SPaolo Bonzini cur_level = (env->irq_input_state >> pin) & 1; 40853018216SPaolo Bonzini /* Don't generate spurious events */ 40953018216SPaolo Bonzini if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) { 41053018216SPaolo Bonzini switch (pin) { 41153018216SPaolo Bonzini case PPCE500_INPUT_MCK: 41253018216SPaolo Bonzini if (level) { 41353018216SPaolo Bonzini LOG_IRQ("%s: reset the PowerPC system\n", 41453018216SPaolo Bonzini __func__); 41553018216SPaolo Bonzini qemu_system_reset_request(); 41653018216SPaolo Bonzini } 41753018216SPaolo Bonzini break; 41853018216SPaolo Bonzini case PPCE500_INPUT_RESET_CORE: 41953018216SPaolo Bonzini if (level) { 42053018216SPaolo Bonzini LOG_IRQ("%s: reset the PowerPC core\n", __func__); 42153018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level); 42253018216SPaolo Bonzini } 42353018216SPaolo Bonzini break; 42453018216SPaolo Bonzini case PPCE500_INPUT_CINT: 42553018216SPaolo Bonzini /* Level sensitive - active high */ 42653018216SPaolo Bonzini LOG_IRQ("%s: set the critical IRQ state to %d\n", 42753018216SPaolo Bonzini __func__, level); 42853018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level); 42953018216SPaolo Bonzini break; 43053018216SPaolo Bonzini case PPCE500_INPUT_INT: 43153018216SPaolo Bonzini /* Level sensitive - active high */ 43253018216SPaolo Bonzini LOG_IRQ("%s: set the core IRQ state to %d\n", 43353018216SPaolo Bonzini __func__, level); 43453018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level); 43553018216SPaolo Bonzini break; 43653018216SPaolo Bonzini case PPCE500_INPUT_DEBUG: 43753018216SPaolo Bonzini /* Level sensitive - active high */ 43853018216SPaolo Bonzini LOG_IRQ("%s: set the debug pin state to %d\n", 43953018216SPaolo Bonzini __func__, level); 44053018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level); 44153018216SPaolo Bonzini break; 44253018216SPaolo Bonzini default: 44353018216SPaolo Bonzini /* Unknown pin - do nothing */ 44453018216SPaolo Bonzini LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin); 44553018216SPaolo Bonzini return; 44653018216SPaolo Bonzini } 44753018216SPaolo Bonzini if (level) 44853018216SPaolo Bonzini env->irq_input_state |= 1 << pin; 44953018216SPaolo Bonzini else 45053018216SPaolo Bonzini env->irq_input_state &= ~(1 << pin); 45153018216SPaolo Bonzini } 45253018216SPaolo Bonzini } 45353018216SPaolo Bonzini 454aa5a9e24SPaolo Bonzini void ppce500_irq_init(PowerPCCPU *cpu) 45553018216SPaolo Bonzini { 456aa5a9e24SPaolo Bonzini CPUPPCState *env = &cpu->env; 45753018216SPaolo Bonzini 45853018216SPaolo Bonzini env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq, 45953018216SPaolo Bonzini cpu, PPCE500_INPUT_NB); 46053018216SPaolo Bonzini } 46153018216SPaolo Bonzini 46253018216SPaolo Bonzini /* Enable or Disable the E500 EPR capability */ 46353018216SPaolo Bonzini void ppce500_set_mpic_proxy(bool enabled) 46453018216SPaolo Bonzini { 465182735efSAndreas Färber CPUState *cs; 46653018216SPaolo Bonzini 467bdc44640SAndreas Färber CPU_FOREACH(cs) { 468182735efSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 46953018216SPaolo Bonzini 470182735efSAndreas Färber cpu->env.mpic_proxy = enabled; 47153018216SPaolo Bonzini if (kvm_enabled()) { 472182735efSAndreas Färber kvmppc_set_mpic_proxy(cpu, enabled); 47353018216SPaolo Bonzini } 47453018216SPaolo Bonzini } 47553018216SPaolo Bonzini } 47653018216SPaolo Bonzini 47753018216SPaolo Bonzini /*****************************************************************************/ 47853018216SPaolo Bonzini /* PowerPC time base and decrementer emulation */ 47953018216SPaolo Bonzini 48053018216SPaolo Bonzini uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset) 48153018216SPaolo Bonzini { 48253018216SPaolo Bonzini /* TB time in tb periods */ 48373bcb24dSRutuja Shah return muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND) + tb_offset; 48453018216SPaolo Bonzini } 48553018216SPaolo Bonzini 48653018216SPaolo Bonzini uint64_t cpu_ppc_load_tbl (CPUPPCState *env) 48753018216SPaolo Bonzini { 48853018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 48953018216SPaolo Bonzini uint64_t tb; 49053018216SPaolo Bonzini 49153018216SPaolo Bonzini if (kvm_enabled()) { 49253018216SPaolo Bonzini return env->spr[SPR_TBL]; 49353018216SPaolo Bonzini } 49453018216SPaolo Bonzini 495bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); 49653018216SPaolo Bonzini LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb); 49753018216SPaolo Bonzini 49853018216SPaolo Bonzini return tb; 49953018216SPaolo Bonzini } 50053018216SPaolo Bonzini 50153018216SPaolo Bonzini static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env) 50253018216SPaolo Bonzini { 50353018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 50453018216SPaolo Bonzini uint64_t tb; 50553018216SPaolo Bonzini 506bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); 50753018216SPaolo Bonzini LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb); 50853018216SPaolo Bonzini 50953018216SPaolo Bonzini return tb >> 32; 51053018216SPaolo Bonzini } 51153018216SPaolo Bonzini 51253018216SPaolo Bonzini uint32_t cpu_ppc_load_tbu (CPUPPCState *env) 51353018216SPaolo Bonzini { 51453018216SPaolo Bonzini if (kvm_enabled()) { 51553018216SPaolo Bonzini return env->spr[SPR_TBU]; 51653018216SPaolo Bonzini } 51753018216SPaolo Bonzini 51853018216SPaolo Bonzini return _cpu_ppc_load_tbu(env); 51953018216SPaolo Bonzini } 52053018216SPaolo Bonzini 52153018216SPaolo Bonzini static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk, 52253018216SPaolo Bonzini int64_t *tb_offsetp, uint64_t value) 52353018216SPaolo Bonzini { 52473bcb24dSRutuja Shah *tb_offsetp = value - 52573bcb24dSRutuja Shah muldiv64(vmclk, tb_env->tb_freq, NANOSECONDS_PER_SECOND); 52673bcb24dSRutuja Shah 52753018216SPaolo Bonzini LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n", 52853018216SPaolo Bonzini __func__, value, *tb_offsetp); 52953018216SPaolo Bonzini } 53053018216SPaolo Bonzini 53153018216SPaolo Bonzini void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value) 53253018216SPaolo Bonzini { 53353018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 53453018216SPaolo Bonzini uint64_t tb; 53553018216SPaolo Bonzini 536bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); 53753018216SPaolo Bonzini tb &= 0xFFFFFFFF00000000ULL; 538bc72ad67SAlex Bligh cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 53953018216SPaolo Bonzini &tb_env->tb_offset, tb | (uint64_t)value); 54053018216SPaolo Bonzini } 54153018216SPaolo Bonzini 54253018216SPaolo Bonzini static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value) 54353018216SPaolo Bonzini { 54453018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 54553018216SPaolo Bonzini uint64_t tb; 54653018216SPaolo Bonzini 547bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); 54853018216SPaolo Bonzini tb &= 0x00000000FFFFFFFFULL; 549bc72ad67SAlex Bligh cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 55053018216SPaolo Bonzini &tb_env->tb_offset, ((uint64_t)value << 32) | tb); 55153018216SPaolo Bonzini } 55253018216SPaolo Bonzini 55353018216SPaolo Bonzini void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value) 55453018216SPaolo Bonzini { 55553018216SPaolo Bonzini _cpu_ppc_store_tbu(env, value); 55653018216SPaolo Bonzini } 55753018216SPaolo Bonzini 55853018216SPaolo Bonzini uint64_t cpu_ppc_load_atbl (CPUPPCState *env) 55953018216SPaolo Bonzini { 56053018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 56153018216SPaolo Bonzini uint64_t tb; 56253018216SPaolo Bonzini 563bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); 56453018216SPaolo Bonzini LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb); 56553018216SPaolo Bonzini 56653018216SPaolo Bonzini return tb; 56753018216SPaolo Bonzini } 56853018216SPaolo Bonzini 56953018216SPaolo Bonzini uint32_t cpu_ppc_load_atbu (CPUPPCState *env) 57053018216SPaolo Bonzini { 57153018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 57253018216SPaolo Bonzini uint64_t tb; 57353018216SPaolo Bonzini 574bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); 57553018216SPaolo Bonzini LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb); 57653018216SPaolo Bonzini 57753018216SPaolo Bonzini return tb >> 32; 57853018216SPaolo Bonzini } 57953018216SPaolo Bonzini 58053018216SPaolo Bonzini void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value) 58153018216SPaolo Bonzini { 58253018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 58353018216SPaolo Bonzini uint64_t tb; 58453018216SPaolo Bonzini 585bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); 58653018216SPaolo Bonzini tb &= 0xFFFFFFFF00000000ULL; 587bc72ad67SAlex Bligh cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 58853018216SPaolo Bonzini &tb_env->atb_offset, tb | (uint64_t)value); 58953018216SPaolo Bonzini } 59053018216SPaolo Bonzini 59153018216SPaolo Bonzini void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value) 59253018216SPaolo Bonzini { 59353018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 59453018216SPaolo Bonzini uint64_t tb; 59553018216SPaolo Bonzini 596bc72ad67SAlex Bligh tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); 59753018216SPaolo Bonzini tb &= 0x00000000FFFFFFFFULL; 598bc72ad67SAlex Bligh cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 59953018216SPaolo Bonzini &tb_env->atb_offset, ((uint64_t)value << 32) | tb); 60053018216SPaolo Bonzini } 60153018216SPaolo Bonzini 60253018216SPaolo Bonzini static void cpu_ppc_tb_stop (CPUPPCState *env) 60353018216SPaolo Bonzini { 60453018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 60553018216SPaolo Bonzini uint64_t tb, atb, vmclk; 60653018216SPaolo Bonzini 60753018216SPaolo Bonzini /* If the time base is already frozen, do nothing */ 60853018216SPaolo Bonzini if (tb_env->tb_freq != 0) { 609bc72ad67SAlex Bligh vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 61053018216SPaolo Bonzini /* Get the time base */ 61153018216SPaolo Bonzini tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset); 61253018216SPaolo Bonzini /* Get the alternate time base */ 61353018216SPaolo Bonzini atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset); 61453018216SPaolo Bonzini /* Store the time base value (ie compute the current offset) */ 61553018216SPaolo Bonzini cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb); 61653018216SPaolo Bonzini /* Store the alternate time base value (compute the current offset) */ 61753018216SPaolo Bonzini cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb); 61853018216SPaolo Bonzini /* Set the time base frequency to zero */ 61953018216SPaolo Bonzini tb_env->tb_freq = 0; 62053018216SPaolo Bonzini /* Now, the time bases are frozen to tb_offset / atb_offset value */ 62153018216SPaolo Bonzini } 62253018216SPaolo Bonzini } 62353018216SPaolo Bonzini 62453018216SPaolo Bonzini static void cpu_ppc_tb_start (CPUPPCState *env) 62553018216SPaolo Bonzini { 62653018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 62753018216SPaolo Bonzini uint64_t tb, atb, vmclk; 62853018216SPaolo Bonzini 62953018216SPaolo Bonzini /* If the time base is not frozen, do nothing */ 63053018216SPaolo Bonzini if (tb_env->tb_freq == 0) { 631bc72ad67SAlex Bligh vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 63253018216SPaolo Bonzini /* Get the time base from tb_offset */ 63353018216SPaolo Bonzini tb = tb_env->tb_offset; 63453018216SPaolo Bonzini /* Get the alternate time base from atb_offset */ 63553018216SPaolo Bonzini atb = tb_env->atb_offset; 63653018216SPaolo Bonzini /* Restore the tb frequency from the decrementer frequency */ 63753018216SPaolo Bonzini tb_env->tb_freq = tb_env->decr_freq; 63853018216SPaolo Bonzini /* Store the time base value */ 63953018216SPaolo Bonzini cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb); 64053018216SPaolo Bonzini /* Store the alternate time base value */ 64153018216SPaolo Bonzini cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb); 64253018216SPaolo Bonzini } 64353018216SPaolo Bonzini } 64453018216SPaolo Bonzini 645e81a982aSAlexander Graf bool ppc_decr_clear_on_delivery(CPUPPCState *env) 646e81a982aSAlexander Graf { 647e81a982aSAlexander Graf ppc_tb_t *tb_env = env->tb_env; 648e81a982aSAlexander Graf int flags = PPC_DECR_UNDERFLOW_TRIGGERED | PPC_DECR_UNDERFLOW_LEVEL; 649e81a982aSAlexander Graf return ((tb_env->flags & flags) == PPC_DECR_UNDERFLOW_TRIGGERED); 650e81a982aSAlexander Graf } 651e81a982aSAlexander Graf 65253018216SPaolo Bonzini static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) 65353018216SPaolo Bonzini { 65453018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 65553018216SPaolo Bonzini uint32_t decr; 65653018216SPaolo Bonzini int64_t diff; 65753018216SPaolo Bonzini 658bc72ad67SAlex Bligh diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 65953018216SPaolo Bonzini if (diff >= 0) { 66073bcb24dSRutuja Shah decr = muldiv64(diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND); 66153018216SPaolo Bonzini } else if (tb_env->flags & PPC_TIMER_BOOKE) { 66253018216SPaolo Bonzini decr = 0; 66353018216SPaolo Bonzini } else { 66473bcb24dSRutuja Shah decr = -muldiv64(-diff, tb_env->decr_freq, NANOSECONDS_PER_SECOND); 66553018216SPaolo Bonzini } 66653018216SPaolo Bonzini LOG_TB("%s: %08" PRIx32 "\n", __func__, decr); 66753018216SPaolo Bonzini 66853018216SPaolo Bonzini return decr; 66953018216SPaolo Bonzini } 67053018216SPaolo Bonzini 67153018216SPaolo Bonzini uint32_t cpu_ppc_load_decr (CPUPPCState *env) 67253018216SPaolo Bonzini { 67353018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 67453018216SPaolo Bonzini 67553018216SPaolo Bonzini if (kvm_enabled()) { 67653018216SPaolo Bonzini return env->spr[SPR_DECR]; 67753018216SPaolo Bonzini } 67853018216SPaolo Bonzini 67953018216SPaolo Bonzini return _cpu_ppc_load_decr(env, tb_env->decr_next); 68053018216SPaolo Bonzini } 68153018216SPaolo Bonzini 68253018216SPaolo Bonzini uint32_t cpu_ppc_load_hdecr (CPUPPCState *env) 68353018216SPaolo Bonzini { 68453018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 68553018216SPaolo Bonzini 68653018216SPaolo Bonzini return _cpu_ppc_load_decr(env, tb_env->hdecr_next); 68753018216SPaolo Bonzini } 68853018216SPaolo Bonzini 68953018216SPaolo Bonzini uint64_t cpu_ppc_load_purr (CPUPPCState *env) 69053018216SPaolo Bonzini { 69153018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 69253018216SPaolo Bonzini uint64_t diff; 69353018216SPaolo Bonzini 694bc72ad67SAlex Bligh diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env->purr_start; 69553018216SPaolo Bonzini 69673bcb24dSRutuja Shah return tb_env->purr_load + 69773bcb24dSRutuja Shah muldiv64(diff, tb_env->tb_freq, NANOSECONDS_PER_SECOND); 69853018216SPaolo Bonzini } 69953018216SPaolo Bonzini 70053018216SPaolo Bonzini /* When decrementer expires, 70153018216SPaolo Bonzini * all we need to do is generate or queue a CPU exception 70253018216SPaolo Bonzini */ 70353018216SPaolo Bonzini static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu) 70453018216SPaolo Bonzini { 70553018216SPaolo Bonzini /* Raise it */ 70653018216SPaolo Bonzini LOG_TB("raise decrementer exception\n"); 70753018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1); 70853018216SPaolo Bonzini } 70953018216SPaolo Bonzini 710e81a982aSAlexander Graf static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu) 711e81a982aSAlexander Graf { 712e81a982aSAlexander Graf ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0); 713e81a982aSAlexander Graf } 714e81a982aSAlexander Graf 71553018216SPaolo Bonzini static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu) 71653018216SPaolo Bonzini { 7174b236b62SBenjamin Herrenschmidt CPUPPCState *env = &cpu->env; 7184b236b62SBenjamin Herrenschmidt 71953018216SPaolo Bonzini /* Raise it */ 7204b236b62SBenjamin Herrenschmidt LOG_TB("raise hv decrementer exception\n"); 7214b236b62SBenjamin Herrenschmidt 7224b236b62SBenjamin Herrenschmidt /* The architecture specifies that we don't deliver HDEC 7234b236b62SBenjamin Herrenschmidt * interrupts in a PM state. Not only they don't cause a 7244b236b62SBenjamin Herrenschmidt * wakeup but they also get effectively discarded. 7254b236b62SBenjamin Herrenschmidt */ 7264b236b62SBenjamin Herrenschmidt if (!env->in_pm_state) { 72753018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1); 72853018216SPaolo Bonzini } 7294b236b62SBenjamin Herrenschmidt } 73053018216SPaolo Bonzini 731e81a982aSAlexander Graf static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu) 732e81a982aSAlexander Graf { 733e81a982aSAlexander Graf ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0); 734e81a982aSAlexander Graf } 735e81a982aSAlexander Graf 73653018216SPaolo Bonzini static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, 7371246b259SStefan Weil QEMUTimer *timer, 738e81a982aSAlexander Graf void (*raise_excp)(void *), 739e81a982aSAlexander Graf void (*lower_excp)(PowerPCCPU *), 740e81a982aSAlexander Graf uint32_t decr, uint32_t value) 74153018216SPaolo Bonzini { 74253018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 74353018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 74453018216SPaolo Bonzini uint64_t now, next; 74553018216SPaolo Bonzini 74653018216SPaolo Bonzini LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__, 74753018216SPaolo Bonzini decr, value); 74853018216SPaolo Bonzini 74953018216SPaolo Bonzini if (kvm_enabled()) { 75053018216SPaolo Bonzini /* KVM handles decrementer exceptions, we don't need our own timer */ 75153018216SPaolo Bonzini return; 75253018216SPaolo Bonzini } 75353018216SPaolo Bonzini 754e81a982aSAlexander Graf /* 755e81a982aSAlexander Graf * Going from 2 -> 1, 1 -> 0 or 0 -> -1 is the event to generate a DEC 756e81a982aSAlexander Graf * interrupt. 757e81a982aSAlexander Graf * 758e81a982aSAlexander Graf * If we get a really small DEC value, we can assume that by the time we 759e81a982aSAlexander Graf * handled it we should inject an interrupt already. 760e81a982aSAlexander Graf * 761e81a982aSAlexander Graf * On MSB level based DEC implementations the MSB always means the interrupt 762e81a982aSAlexander Graf * is pending, so raise it on those. 763e81a982aSAlexander Graf * 764e81a982aSAlexander Graf * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers 765e81a982aSAlexander Graf * an edge interrupt, so raise it here too. 766e81a982aSAlexander Graf */ 767e81a982aSAlexander Graf if ((value < 3) || 768e81a982aSAlexander Graf ((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && (value & 0x80000000)) || 769e81a982aSAlexander Graf ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && (value & 0x80000000) 770e81a982aSAlexander Graf && !(decr & 0x80000000))) { 771e81a982aSAlexander Graf (*raise_excp)(cpu); 772e81a982aSAlexander Graf return; 773e81a982aSAlexander Graf } 774e81a982aSAlexander Graf 775e81a982aSAlexander Graf /* On MSB level based systems a 0 for the MSB stops interrupt delivery */ 776e81a982aSAlexander Graf if (!(value & 0x80000000) && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { 777e81a982aSAlexander Graf (*lower_excp)(cpu); 778e81a982aSAlexander Graf } 779e81a982aSAlexander Graf 780e81a982aSAlexander Graf /* Calculate the next timer event */ 781bc72ad67SAlex Bligh now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 78273bcb24dSRutuja Shah next = now + muldiv64(value, NANOSECONDS_PER_SECOND, tb_env->decr_freq); 78353018216SPaolo Bonzini *nextp = next; 784e81a982aSAlexander Graf 78553018216SPaolo Bonzini /* Adjust timer */ 786bc72ad67SAlex Bligh timer_mod(timer, next); 78753018216SPaolo Bonzini } 78853018216SPaolo Bonzini 78953018216SPaolo Bonzini static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr, 790e81a982aSAlexander Graf uint32_t value) 79153018216SPaolo Bonzini { 79253018216SPaolo Bonzini ppc_tb_t *tb_env = cpu->env.tb_env; 79353018216SPaolo Bonzini 79453018216SPaolo Bonzini __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, 795e81a982aSAlexander Graf tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr, 796e81a982aSAlexander Graf value); 79753018216SPaolo Bonzini } 79853018216SPaolo Bonzini 79953018216SPaolo Bonzini void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) 80053018216SPaolo Bonzini { 80153018216SPaolo Bonzini PowerPCCPU *cpu = ppc_env_get_cpu(env); 80253018216SPaolo Bonzini 803e81a982aSAlexander Graf _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value); 80453018216SPaolo Bonzini } 80553018216SPaolo Bonzini 80653018216SPaolo Bonzini static void cpu_ppc_decr_cb(void *opaque) 80753018216SPaolo Bonzini { 80853018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 80953018216SPaolo Bonzini 810e81a982aSAlexander Graf cpu_ppc_decr_excp(cpu); 81153018216SPaolo Bonzini } 81253018216SPaolo Bonzini 81353018216SPaolo Bonzini static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr, 814e81a982aSAlexander Graf uint32_t value) 81553018216SPaolo Bonzini { 81653018216SPaolo Bonzini ppc_tb_t *tb_env = cpu->env.tb_env; 81753018216SPaolo Bonzini 81853018216SPaolo Bonzini if (tb_env->hdecr_timer != NULL) { 81953018216SPaolo Bonzini __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, 820e81a982aSAlexander Graf tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower, 821e81a982aSAlexander Graf hdecr, value); 82253018216SPaolo Bonzini } 82353018216SPaolo Bonzini } 82453018216SPaolo Bonzini 82553018216SPaolo Bonzini void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) 82653018216SPaolo Bonzini { 82753018216SPaolo Bonzini PowerPCCPU *cpu = ppc_env_get_cpu(env); 82853018216SPaolo Bonzini 829e81a982aSAlexander Graf _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value); 83053018216SPaolo Bonzini } 83153018216SPaolo Bonzini 83253018216SPaolo Bonzini static void cpu_ppc_hdecr_cb(void *opaque) 83353018216SPaolo Bonzini { 83453018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 83553018216SPaolo Bonzini 836e81a982aSAlexander Graf cpu_ppc_hdecr_excp(cpu); 83753018216SPaolo Bonzini } 83853018216SPaolo Bonzini 83953018216SPaolo Bonzini static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value) 84053018216SPaolo Bonzini { 84153018216SPaolo Bonzini ppc_tb_t *tb_env = cpu->env.tb_env; 84253018216SPaolo Bonzini 84353018216SPaolo Bonzini tb_env->purr_load = value; 844bc72ad67SAlex Bligh tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 84553018216SPaolo Bonzini } 84653018216SPaolo Bonzini 84753018216SPaolo Bonzini static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) 84853018216SPaolo Bonzini { 84953018216SPaolo Bonzini CPUPPCState *env = opaque; 85053018216SPaolo Bonzini PowerPCCPU *cpu = ppc_env_get_cpu(env); 85153018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 85253018216SPaolo Bonzini 85353018216SPaolo Bonzini tb_env->tb_freq = freq; 85453018216SPaolo Bonzini tb_env->decr_freq = freq; 85553018216SPaolo Bonzini /* There is a bug in Linux 2.4 kernels: 85653018216SPaolo Bonzini * if a decrementer exception is pending when it enables msr_ee at startup, 85753018216SPaolo Bonzini * it's not ready to handle it... 85853018216SPaolo Bonzini */ 859e81a982aSAlexander Graf _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF); 860e81a982aSAlexander Graf _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF); 86153018216SPaolo Bonzini cpu_ppc_store_purr(cpu, 0x0000000000000000ULL); 86253018216SPaolo Bonzini } 86353018216SPaolo Bonzini 86442043e4fSLaurent Vivier static void timebase_save(PPCTimebase *tb) 86598a8b524SAlexey Kardashevskiy { 8664a7428c5SChristopher Covington uint64_t ticks = cpu_get_host_ticks(); 86798a8b524SAlexey Kardashevskiy PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 86898a8b524SAlexey Kardashevskiy 86998a8b524SAlexey Kardashevskiy if (!first_ppc_cpu->env.tb_env) { 87098a8b524SAlexey Kardashevskiy error_report("No timebase object"); 87198a8b524SAlexey Kardashevskiy return; 87298a8b524SAlexey Kardashevskiy } 87398a8b524SAlexey Kardashevskiy 87442043e4fSLaurent Vivier /* not used anymore, we keep it for compatibility */ 87577bad151SPaolo Bonzini tb->time_of_the_day_ns = qemu_clock_get_ns(QEMU_CLOCK_HOST); 87698a8b524SAlexey Kardashevskiy /* 87742043e4fSLaurent Vivier * tb_offset is only expected to be changed by QEMU so 87898a8b524SAlexey Kardashevskiy * there is no need to update it from KVM here 87998a8b524SAlexey Kardashevskiy */ 88098a8b524SAlexey Kardashevskiy tb->guest_timebase = ticks + first_ppc_cpu->env.tb_env->tb_offset; 88198a8b524SAlexey Kardashevskiy } 88298a8b524SAlexey Kardashevskiy 88342043e4fSLaurent Vivier static void timebase_load(PPCTimebase *tb) 88498a8b524SAlexey Kardashevskiy { 88598a8b524SAlexey Kardashevskiy CPUState *cpu; 88698a8b524SAlexey Kardashevskiy PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); 88742043e4fSLaurent Vivier int64_t tb_off_adj, tb_off; 88898a8b524SAlexey Kardashevskiy unsigned long freq; 88998a8b524SAlexey Kardashevskiy 89098a8b524SAlexey Kardashevskiy if (!first_ppc_cpu->env.tb_env) { 89198a8b524SAlexey Kardashevskiy error_report("No timebase object"); 89242043e4fSLaurent Vivier return; 89398a8b524SAlexey Kardashevskiy } 89498a8b524SAlexey Kardashevskiy 89598a8b524SAlexey Kardashevskiy freq = first_ppc_cpu->env.tb_env->tb_freq; 89698a8b524SAlexey Kardashevskiy 89742043e4fSLaurent Vivier tb_off_adj = tb->guest_timebase - cpu_get_host_ticks(); 89898a8b524SAlexey Kardashevskiy 89998a8b524SAlexey Kardashevskiy tb_off = first_ppc_cpu->env.tb_env->tb_offset; 90098a8b524SAlexey Kardashevskiy trace_ppc_tb_adjust(tb_off, tb_off_adj, tb_off_adj - tb_off, 90198a8b524SAlexey Kardashevskiy (tb_off_adj - tb_off) / freq); 90298a8b524SAlexey Kardashevskiy 90398a8b524SAlexey Kardashevskiy /* Set new offset to all CPUs */ 90498a8b524SAlexey Kardashevskiy CPU_FOREACH(cpu) { 90598a8b524SAlexey Kardashevskiy PowerPCCPU *pcpu = POWERPC_CPU(cpu); 90698a8b524SAlexey Kardashevskiy pcpu->env.tb_env->tb_offset = tb_off_adj; 90742043e4fSLaurent Vivier #if defined(CONFIG_KVM) 90842043e4fSLaurent Vivier kvm_set_one_reg(cpu, KVM_REG_PPC_TB_OFFSET, 90942043e4fSLaurent Vivier &pcpu->env.tb_env->tb_offset); 91042043e4fSLaurent Vivier #endif 91142043e4fSLaurent Vivier } 91298a8b524SAlexey Kardashevskiy } 91398a8b524SAlexey Kardashevskiy 91442043e4fSLaurent Vivier void cpu_ppc_clock_vm_state_change(void *opaque, int running, 91542043e4fSLaurent Vivier RunState state) 91642043e4fSLaurent Vivier { 91742043e4fSLaurent Vivier PPCTimebase *tb = opaque; 91842043e4fSLaurent Vivier 91942043e4fSLaurent Vivier if (running) { 92042043e4fSLaurent Vivier timebase_load(tb); 92142043e4fSLaurent Vivier } else { 92242043e4fSLaurent Vivier timebase_save(tb); 92342043e4fSLaurent Vivier } 92442043e4fSLaurent Vivier } 92542043e4fSLaurent Vivier 92642043e4fSLaurent Vivier /* 92742043e4fSLaurent Vivier * When migrating, read the clock just before migration, 92842043e4fSLaurent Vivier * so that the guest clock counts during the events 92942043e4fSLaurent Vivier * between: 93042043e4fSLaurent Vivier * 93142043e4fSLaurent Vivier * * vm_stop() 93242043e4fSLaurent Vivier * * 93342043e4fSLaurent Vivier * * pre_save() 93442043e4fSLaurent Vivier * 93542043e4fSLaurent Vivier * This reduces clock difference on migration from 5s 93642043e4fSLaurent Vivier * to 0.1s (when max_downtime == 5s), because sending the 93742043e4fSLaurent Vivier * final pages of memory (which happens between vm_stop() 93842043e4fSLaurent Vivier * and pre_save()) takes max_downtime. 93942043e4fSLaurent Vivier */ 94042043e4fSLaurent Vivier static void timebase_pre_save(void *opaque) 94142043e4fSLaurent Vivier { 94242043e4fSLaurent Vivier PPCTimebase *tb = opaque; 94342043e4fSLaurent Vivier 94442043e4fSLaurent Vivier timebase_save(tb); 94598a8b524SAlexey Kardashevskiy } 94698a8b524SAlexey Kardashevskiy 94798a8b524SAlexey Kardashevskiy const VMStateDescription vmstate_ppc_timebase = { 94898a8b524SAlexey Kardashevskiy .name = "timebase", 94998a8b524SAlexey Kardashevskiy .version_id = 1, 95098a8b524SAlexey Kardashevskiy .minimum_version_id = 1, 95198a8b524SAlexey Kardashevskiy .minimum_version_id_old = 1, 95298a8b524SAlexey Kardashevskiy .pre_save = timebase_pre_save, 95398a8b524SAlexey Kardashevskiy .fields = (VMStateField []) { 95498a8b524SAlexey Kardashevskiy VMSTATE_UINT64(guest_timebase, PPCTimebase), 95598a8b524SAlexey Kardashevskiy VMSTATE_INT64(time_of_the_day_ns, PPCTimebase), 95698a8b524SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 95798a8b524SAlexey Kardashevskiy }, 95898a8b524SAlexey Kardashevskiy }; 95998a8b524SAlexey Kardashevskiy 96053018216SPaolo Bonzini /* Set up (once) timebase frequency (in Hz) */ 96153018216SPaolo Bonzini clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) 96253018216SPaolo Bonzini { 96353018216SPaolo Bonzini PowerPCCPU *cpu = ppc_env_get_cpu(env); 96453018216SPaolo Bonzini ppc_tb_t *tb_env; 96553018216SPaolo Bonzini 96653018216SPaolo Bonzini tb_env = g_malloc0(sizeof(ppc_tb_t)); 96753018216SPaolo Bonzini env->tb_env = tb_env; 96853018216SPaolo Bonzini tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; 969e81a982aSAlexander Graf if (env->insns_flags & PPC_SEGMENT_64B) { 970e81a982aSAlexander Graf /* All Book3S 64bit CPUs implement level based DEC logic */ 971e81a982aSAlexander Graf tb_env->flags |= PPC_DECR_UNDERFLOW_LEVEL; 972e81a982aSAlexander Graf } 97353018216SPaolo Bonzini /* Create new timer */ 974bc72ad67SAlex Bligh tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu); 9754b236b62SBenjamin Herrenschmidt if (env->has_hv_mode) { 976bc72ad67SAlex Bligh tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb, 97753018216SPaolo Bonzini cpu); 97853018216SPaolo Bonzini } else { 97953018216SPaolo Bonzini tb_env->hdecr_timer = NULL; 98053018216SPaolo Bonzini } 98153018216SPaolo Bonzini cpu_ppc_set_tb_clk(env, freq); 98253018216SPaolo Bonzini 98353018216SPaolo Bonzini return &cpu_ppc_set_tb_clk; 98453018216SPaolo Bonzini } 98553018216SPaolo Bonzini 98653018216SPaolo Bonzini /* Specific helpers for POWER & PowerPC 601 RTC */ 98753018216SPaolo Bonzini void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value) 98853018216SPaolo Bonzini { 98953018216SPaolo Bonzini _cpu_ppc_store_tbu(env, value); 99053018216SPaolo Bonzini } 99153018216SPaolo Bonzini 99253018216SPaolo Bonzini uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env) 99353018216SPaolo Bonzini { 99453018216SPaolo Bonzini return _cpu_ppc_load_tbu(env); 99553018216SPaolo Bonzini } 99653018216SPaolo Bonzini 99753018216SPaolo Bonzini void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value) 99853018216SPaolo Bonzini { 99953018216SPaolo Bonzini cpu_ppc_store_tbl(env, value & 0x3FFFFF80); 100053018216SPaolo Bonzini } 100153018216SPaolo Bonzini 100253018216SPaolo Bonzini uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env) 100353018216SPaolo Bonzini { 100453018216SPaolo Bonzini return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 100553018216SPaolo Bonzini } 100653018216SPaolo Bonzini 100753018216SPaolo Bonzini /*****************************************************************************/ 100853018216SPaolo Bonzini /* PowerPC 40x timers */ 100953018216SPaolo Bonzini 101053018216SPaolo Bonzini /* PIT, FIT & WDT */ 101153018216SPaolo Bonzini typedef struct ppc40x_timer_t ppc40x_timer_t; 101253018216SPaolo Bonzini struct ppc40x_timer_t { 101353018216SPaolo Bonzini uint64_t pit_reload; /* PIT auto-reload value */ 101453018216SPaolo Bonzini uint64_t fit_next; /* Tick for next FIT interrupt */ 10151246b259SStefan Weil QEMUTimer *fit_timer; 101653018216SPaolo Bonzini uint64_t wdt_next; /* Tick for next WDT interrupt */ 10171246b259SStefan Weil QEMUTimer *wdt_timer; 101853018216SPaolo Bonzini 101953018216SPaolo Bonzini /* 405 have the PIT, 440 have a DECR. */ 102053018216SPaolo Bonzini unsigned int decr_excp; 102153018216SPaolo Bonzini }; 102253018216SPaolo Bonzini 102353018216SPaolo Bonzini /* Fixed interval timer */ 102453018216SPaolo Bonzini static void cpu_4xx_fit_cb (void *opaque) 102553018216SPaolo Bonzini { 102653018216SPaolo Bonzini PowerPCCPU *cpu; 102753018216SPaolo Bonzini CPUPPCState *env; 102853018216SPaolo Bonzini ppc_tb_t *tb_env; 102953018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 103053018216SPaolo Bonzini uint64_t now, next; 103153018216SPaolo Bonzini 103253018216SPaolo Bonzini env = opaque; 103353018216SPaolo Bonzini cpu = ppc_env_get_cpu(env); 103453018216SPaolo Bonzini tb_env = env->tb_env; 103553018216SPaolo Bonzini ppc40x_timer = tb_env->opaque; 1036bc72ad67SAlex Bligh now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 103753018216SPaolo Bonzini switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) { 103853018216SPaolo Bonzini case 0: 103953018216SPaolo Bonzini next = 1 << 9; 104053018216SPaolo Bonzini break; 104153018216SPaolo Bonzini case 1: 104253018216SPaolo Bonzini next = 1 << 13; 104353018216SPaolo Bonzini break; 104453018216SPaolo Bonzini case 2: 104553018216SPaolo Bonzini next = 1 << 17; 104653018216SPaolo Bonzini break; 104753018216SPaolo Bonzini case 3: 104853018216SPaolo Bonzini next = 1 << 21; 104953018216SPaolo Bonzini break; 105053018216SPaolo Bonzini default: 105153018216SPaolo Bonzini /* Cannot occur, but makes gcc happy */ 105253018216SPaolo Bonzini return; 105353018216SPaolo Bonzini } 105473bcb24dSRutuja Shah next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->tb_freq); 105553018216SPaolo Bonzini if (next == now) 105653018216SPaolo Bonzini next++; 1057bc72ad67SAlex Bligh timer_mod(ppc40x_timer->fit_timer, next); 105853018216SPaolo Bonzini env->spr[SPR_40x_TSR] |= 1 << 26; 105953018216SPaolo Bonzini if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) { 106053018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1); 106153018216SPaolo Bonzini } 106253018216SPaolo Bonzini LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__, 106353018216SPaolo Bonzini (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1), 106453018216SPaolo Bonzini env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]); 106553018216SPaolo Bonzini } 106653018216SPaolo Bonzini 106753018216SPaolo Bonzini /* Programmable interval timer */ 106853018216SPaolo Bonzini static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) 106953018216SPaolo Bonzini { 107053018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 107153018216SPaolo Bonzini uint64_t now, next; 107253018216SPaolo Bonzini 107353018216SPaolo Bonzini ppc40x_timer = tb_env->opaque; 107453018216SPaolo Bonzini if (ppc40x_timer->pit_reload <= 1 || 107553018216SPaolo Bonzini !((env->spr[SPR_40x_TCR] >> 26) & 0x1) || 107653018216SPaolo Bonzini (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) { 107753018216SPaolo Bonzini /* Stop PIT */ 107853018216SPaolo Bonzini LOG_TB("%s: stop PIT\n", __func__); 1079bc72ad67SAlex Bligh timer_del(tb_env->decr_timer); 108053018216SPaolo Bonzini } else { 108153018216SPaolo Bonzini LOG_TB("%s: start PIT %016" PRIx64 "\n", 108253018216SPaolo Bonzini __func__, ppc40x_timer->pit_reload); 1083bc72ad67SAlex Bligh now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 108453018216SPaolo Bonzini next = now + muldiv64(ppc40x_timer->pit_reload, 108573bcb24dSRutuja Shah NANOSECONDS_PER_SECOND, tb_env->decr_freq); 108653018216SPaolo Bonzini if (is_excp) 108753018216SPaolo Bonzini next += tb_env->decr_next - now; 108853018216SPaolo Bonzini if (next == now) 108953018216SPaolo Bonzini next++; 1090bc72ad67SAlex Bligh timer_mod(tb_env->decr_timer, next); 109153018216SPaolo Bonzini tb_env->decr_next = next; 109253018216SPaolo Bonzini } 109353018216SPaolo Bonzini } 109453018216SPaolo Bonzini 109553018216SPaolo Bonzini static void cpu_4xx_pit_cb (void *opaque) 109653018216SPaolo Bonzini { 109753018216SPaolo Bonzini PowerPCCPU *cpu; 109853018216SPaolo Bonzini CPUPPCState *env; 109953018216SPaolo Bonzini ppc_tb_t *tb_env; 110053018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 110153018216SPaolo Bonzini 110253018216SPaolo Bonzini env = opaque; 110353018216SPaolo Bonzini cpu = ppc_env_get_cpu(env); 110453018216SPaolo Bonzini tb_env = env->tb_env; 110553018216SPaolo Bonzini ppc40x_timer = tb_env->opaque; 110653018216SPaolo Bonzini env->spr[SPR_40x_TSR] |= 1 << 27; 110753018216SPaolo Bonzini if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) { 110853018216SPaolo Bonzini ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1); 110953018216SPaolo Bonzini } 111053018216SPaolo Bonzini start_stop_pit(env, tb_env, 1); 111153018216SPaolo Bonzini LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " " 111253018216SPaolo Bonzini "%016" PRIx64 "\n", __func__, 111353018216SPaolo Bonzini (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1), 111453018216SPaolo Bonzini (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1), 111553018216SPaolo Bonzini env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR], 111653018216SPaolo Bonzini ppc40x_timer->pit_reload); 111753018216SPaolo Bonzini } 111853018216SPaolo Bonzini 111953018216SPaolo Bonzini /* Watchdog timer */ 112053018216SPaolo Bonzini static void cpu_4xx_wdt_cb (void *opaque) 112153018216SPaolo Bonzini { 112253018216SPaolo Bonzini PowerPCCPU *cpu; 112353018216SPaolo Bonzini CPUPPCState *env; 112453018216SPaolo Bonzini ppc_tb_t *tb_env; 112553018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 112653018216SPaolo Bonzini uint64_t now, next; 112753018216SPaolo Bonzini 112853018216SPaolo Bonzini env = opaque; 112953018216SPaolo Bonzini cpu = ppc_env_get_cpu(env); 113053018216SPaolo Bonzini tb_env = env->tb_env; 113153018216SPaolo Bonzini ppc40x_timer = tb_env->opaque; 1132bc72ad67SAlex Bligh now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 113353018216SPaolo Bonzini switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) { 113453018216SPaolo Bonzini case 0: 113553018216SPaolo Bonzini next = 1 << 17; 113653018216SPaolo Bonzini break; 113753018216SPaolo Bonzini case 1: 113853018216SPaolo Bonzini next = 1 << 21; 113953018216SPaolo Bonzini break; 114053018216SPaolo Bonzini case 2: 114153018216SPaolo Bonzini next = 1 << 25; 114253018216SPaolo Bonzini break; 114353018216SPaolo Bonzini case 3: 114453018216SPaolo Bonzini next = 1 << 29; 114553018216SPaolo Bonzini break; 114653018216SPaolo Bonzini default: 114753018216SPaolo Bonzini /* Cannot occur, but makes gcc happy */ 114853018216SPaolo Bonzini return; 114953018216SPaolo Bonzini } 115073bcb24dSRutuja Shah next = now + muldiv64(next, NANOSECONDS_PER_SECOND, tb_env->decr_freq); 115153018216SPaolo Bonzini if (next == now) 115253018216SPaolo Bonzini next++; 115353018216SPaolo Bonzini LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__, 115453018216SPaolo Bonzini env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]); 115553018216SPaolo Bonzini switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) { 115653018216SPaolo Bonzini case 0x0: 115753018216SPaolo Bonzini case 0x1: 1158bc72ad67SAlex Bligh timer_mod(ppc40x_timer->wdt_timer, next); 115953018216SPaolo Bonzini ppc40x_timer->wdt_next = next; 1160a1f7f97bSPeter Maydell env->spr[SPR_40x_TSR] |= 1U << 31; 116153018216SPaolo Bonzini break; 116253018216SPaolo Bonzini case 0x2: 1163bc72ad67SAlex Bligh timer_mod(ppc40x_timer->wdt_timer, next); 116453018216SPaolo Bonzini ppc40x_timer->wdt_next = next; 116553018216SPaolo Bonzini env->spr[SPR_40x_TSR] |= 1 << 30; 116653018216SPaolo Bonzini if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) { 116753018216SPaolo Bonzini ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1); 116853018216SPaolo Bonzini } 116953018216SPaolo Bonzini break; 117053018216SPaolo Bonzini case 0x3: 117153018216SPaolo Bonzini env->spr[SPR_40x_TSR] &= ~0x30000000; 117253018216SPaolo Bonzini env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000; 117353018216SPaolo Bonzini switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) { 117453018216SPaolo Bonzini case 0x0: 117553018216SPaolo Bonzini /* No reset */ 117653018216SPaolo Bonzini break; 117753018216SPaolo Bonzini case 0x1: /* Core reset */ 117853018216SPaolo Bonzini ppc40x_core_reset(cpu); 117953018216SPaolo Bonzini break; 118053018216SPaolo Bonzini case 0x2: /* Chip reset */ 118153018216SPaolo Bonzini ppc40x_chip_reset(cpu); 118253018216SPaolo Bonzini break; 118353018216SPaolo Bonzini case 0x3: /* System reset */ 118453018216SPaolo Bonzini ppc40x_system_reset(cpu); 118553018216SPaolo Bonzini break; 118653018216SPaolo Bonzini } 118753018216SPaolo Bonzini } 118853018216SPaolo Bonzini } 118953018216SPaolo Bonzini 119053018216SPaolo Bonzini void store_40x_pit (CPUPPCState *env, target_ulong val) 119153018216SPaolo Bonzini { 119253018216SPaolo Bonzini ppc_tb_t *tb_env; 119353018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 119453018216SPaolo Bonzini 119553018216SPaolo Bonzini tb_env = env->tb_env; 119653018216SPaolo Bonzini ppc40x_timer = tb_env->opaque; 119753018216SPaolo Bonzini LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val); 119853018216SPaolo Bonzini ppc40x_timer->pit_reload = val; 119953018216SPaolo Bonzini start_stop_pit(env, tb_env, 0); 120053018216SPaolo Bonzini } 120153018216SPaolo Bonzini 120253018216SPaolo Bonzini target_ulong load_40x_pit (CPUPPCState *env) 120353018216SPaolo Bonzini { 120453018216SPaolo Bonzini return cpu_ppc_load_decr(env); 120553018216SPaolo Bonzini } 120653018216SPaolo Bonzini 120753018216SPaolo Bonzini static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq) 120853018216SPaolo Bonzini { 120953018216SPaolo Bonzini CPUPPCState *env = opaque; 121053018216SPaolo Bonzini ppc_tb_t *tb_env = env->tb_env; 121153018216SPaolo Bonzini 121253018216SPaolo Bonzini LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__, 121353018216SPaolo Bonzini freq); 121453018216SPaolo Bonzini tb_env->tb_freq = freq; 121553018216SPaolo Bonzini tb_env->decr_freq = freq; 121653018216SPaolo Bonzini /* XXX: we should also update all timers */ 121753018216SPaolo Bonzini } 121853018216SPaolo Bonzini 121953018216SPaolo Bonzini clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, 122053018216SPaolo Bonzini unsigned int decr_excp) 122153018216SPaolo Bonzini { 122253018216SPaolo Bonzini ppc_tb_t *tb_env; 122353018216SPaolo Bonzini ppc40x_timer_t *ppc40x_timer; 122453018216SPaolo Bonzini 122553018216SPaolo Bonzini tb_env = g_malloc0(sizeof(ppc_tb_t)); 122653018216SPaolo Bonzini env->tb_env = tb_env; 122753018216SPaolo Bonzini tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; 122853018216SPaolo Bonzini ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t)); 122953018216SPaolo Bonzini tb_env->tb_freq = freq; 123053018216SPaolo Bonzini tb_env->decr_freq = freq; 123153018216SPaolo Bonzini tb_env->opaque = ppc40x_timer; 123253018216SPaolo Bonzini LOG_TB("%s freq %" PRIu32 "\n", __func__, freq); 123353018216SPaolo Bonzini if (ppc40x_timer != NULL) { 123453018216SPaolo Bonzini /* We use decr timer for PIT */ 1235bc72ad67SAlex Bligh tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env); 123653018216SPaolo Bonzini ppc40x_timer->fit_timer = 1237bc72ad67SAlex Bligh timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env); 123853018216SPaolo Bonzini ppc40x_timer->wdt_timer = 1239bc72ad67SAlex Bligh timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env); 124053018216SPaolo Bonzini ppc40x_timer->decr_excp = decr_excp; 124153018216SPaolo Bonzini } 124253018216SPaolo Bonzini 124353018216SPaolo Bonzini return &ppc_40x_set_tb_clk; 124453018216SPaolo Bonzini } 124553018216SPaolo Bonzini 124653018216SPaolo Bonzini /*****************************************************************************/ 124753018216SPaolo Bonzini /* Embedded PowerPC Device Control Registers */ 124853018216SPaolo Bonzini typedef struct ppc_dcrn_t ppc_dcrn_t; 124953018216SPaolo Bonzini struct ppc_dcrn_t { 125053018216SPaolo Bonzini dcr_read_cb dcr_read; 125153018216SPaolo Bonzini dcr_write_cb dcr_write; 125253018216SPaolo Bonzini void *opaque; 125353018216SPaolo Bonzini }; 125453018216SPaolo Bonzini 125553018216SPaolo Bonzini /* XXX: on 460, DCR addresses are 32 bits wide, 125653018216SPaolo Bonzini * using DCRIPR to get the 22 upper bits of the DCR address 125753018216SPaolo Bonzini */ 125853018216SPaolo Bonzini #define DCRN_NB 1024 125953018216SPaolo Bonzini struct ppc_dcr_t { 126053018216SPaolo Bonzini ppc_dcrn_t dcrn[DCRN_NB]; 126153018216SPaolo Bonzini int (*read_error)(int dcrn); 126253018216SPaolo Bonzini int (*write_error)(int dcrn); 126353018216SPaolo Bonzini }; 126453018216SPaolo Bonzini 126553018216SPaolo Bonzini int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 126653018216SPaolo Bonzini { 126753018216SPaolo Bonzini ppc_dcrn_t *dcr; 126853018216SPaolo Bonzini 126953018216SPaolo Bonzini if (dcrn < 0 || dcrn >= DCRN_NB) 127053018216SPaolo Bonzini goto error; 127153018216SPaolo Bonzini dcr = &dcr_env->dcrn[dcrn]; 127253018216SPaolo Bonzini if (dcr->dcr_read == NULL) 127353018216SPaolo Bonzini goto error; 127453018216SPaolo Bonzini *valp = (*dcr->dcr_read)(dcr->opaque, dcrn); 127553018216SPaolo Bonzini 127653018216SPaolo Bonzini return 0; 127753018216SPaolo Bonzini 127853018216SPaolo Bonzini error: 127953018216SPaolo Bonzini if (dcr_env->read_error != NULL) 128053018216SPaolo Bonzini return (*dcr_env->read_error)(dcrn); 128153018216SPaolo Bonzini 128253018216SPaolo Bonzini return -1; 128353018216SPaolo Bonzini } 128453018216SPaolo Bonzini 128553018216SPaolo Bonzini int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 128653018216SPaolo Bonzini { 128753018216SPaolo Bonzini ppc_dcrn_t *dcr; 128853018216SPaolo Bonzini 128953018216SPaolo Bonzini if (dcrn < 0 || dcrn >= DCRN_NB) 129053018216SPaolo Bonzini goto error; 129153018216SPaolo Bonzini dcr = &dcr_env->dcrn[dcrn]; 129253018216SPaolo Bonzini if (dcr->dcr_write == NULL) 129353018216SPaolo Bonzini goto error; 129453018216SPaolo Bonzini (*dcr->dcr_write)(dcr->opaque, dcrn, val); 129553018216SPaolo Bonzini 129653018216SPaolo Bonzini return 0; 129753018216SPaolo Bonzini 129853018216SPaolo Bonzini error: 129953018216SPaolo Bonzini if (dcr_env->write_error != NULL) 130053018216SPaolo Bonzini return (*dcr_env->write_error)(dcrn); 130153018216SPaolo Bonzini 130253018216SPaolo Bonzini return -1; 130353018216SPaolo Bonzini } 130453018216SPaolo Bonzini 130553018216SPaolo Bonzini int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque, 130653018216SPaolo Bonzini dcr_read_cb dcr_read, dcr_write_cb dcr_write) 130753018216SPaolo Bonzini { 130853018216SPaolo Bonzini ppc_dcr_t *dcr_env; 130953018216SPaolo Bonzini ppc_dcrn_t *dcr; 131053018216SPaolo Bonzini 131153018216SPaolo Bonzini dcr_env = env->dcr_env; 131253018216SPaolo Bonzini if (dcr_env == NULL) 131353018216SPaolo Bonzini return -1; 131453018216SPaolo Bonzini if (dcrn < 0 || dcrn >= DCRN_NB) 131553018216SPaolo Bonzini return -1; 131653018216SPaolo Bonzini dcr = &dcr_env->dcrn[dcrn]; 131753018216SPaolo Bonzini if (dcr->opaque != NULL || 131853018216SPaolo Bonzini dcr->dcr_read != NULL || 131953018216SPaolo Bonzini dcr->dcr_write != NULL) 132053018216SPaolo Bonzini return -1; 132153018216SPaolo Bonzini dcr->opaque = opaque; 132253018216SPaolo Bonzini dcr->dcr_read = dcr_read; 132353018216SPaolo Bonzini dcr->dcr_write = dcr_write; 132453018216SPaolo Bonzini 132553018216SPaolo Bonzini return 0; 132653018216SPaolo Bonzini } 132753018216SPaolo Bonzini 132853018216SPaolo Bonzini int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn), 132953018216SPaolo Bonzini int (*write_error)(int dcrn)) 133053018216SPaolo Bonzini { 133153018216SPaolo Bonzini ppc_dcr_t *dcr_env; 133253018216SPaolo Bonzini 133353018216SPaolo Bonzini dcr_env = g_malloc0(sizeof(ppc_dcr_t)); 133453018216SPaolo Bonzini dcr_env->read_error = read_error; 133553018216SPaolo Bonzini dcr_env->write_error = write_error; 133653018216SPaolo Bonzini env->dcr_env = dcr_env; 133753018216SPaolo Bonzini 133853018216SPaolo Bonzini return 0; 133953018216SPaolo Bonzini } 134053018216SPaolo Bonzini 134153018216SPaolo Bonzini /*****************************************************************************/ 134253018216SPaolo Bonzini /* Debug port */ 134353018216SPaolo Bonzini void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val) 134453018216SPaolo Bonzini { 134553018216SPaolo Bonzini addr &= 0xF; 134653018216SPaolo Bonzini switch (addr) { 134753018216SPaolo Bonzini case 0: 134853018216SPaolo Bonzini printf("%c", val); 134953018216SPaolo Bonzini break; 135053018216SPaolo Bonzini case 1: 135153018216SPaolo Bonzini printf("\n"); 135253018216SPaolo Bonzini fflush(stdout); 135353018216SPaolo Bonzini break; 135453018216SPaolo Bonzini case 2: 135553018216SPaolo Bonzini printf("Set loglevel to %04" PRIx32 "\n", val); 135653018216SPaolo Bonzini qemu_set_log(val | 0x100); 135753018216SPaolo Bonzini break; 135853018216SPaolo Bonzini } 135953018216SPaolo Bonzini } 136053018216SPaolo Bonzini 13610ce470cdSAlexey Kardashevskiy /* CPU device-tree ID helpers */ 13620ce470cdSAlexey Kardashevskiy int ppc_get_vcpu_dt_id(PowerPCCPU *cpu) 13630ce470cdSAlexey Kardashevskiy { 13640ce470cdSAlexey Kardashevskiy return cpu->cpu_dt_id; 13650ce470cdSAlexey Kardashevskiy } 13660ce470cdSAlexey Kardashevskiy 13670ce470cdSAlexey Kardashevskiy PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id) 13680ce470cdSAlexey Kardashevskiy { 13690ce470cdSAlexey Kardashevskiy CPUState *cs; 13700ce470cdSAlexey Kardashevskiy 13710ce470cdSAlexey Kardashevskiy CPU_FOREACH(cs) { 13720ce470cdSAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 13730ce470cdSAlexey Kardashevskiy 13740ce470cdSAlexey Kardashevskiy if (cpu->cpu_dt_id == cpu_dt_id) { 13750ce470cdSAlexey Kardashevskiy return cpu; 13760ce470cdSAlexey Kardashevskiy } 13770ce470cdSAlexey Kardashevskiy } 13780ce470cdSAlexey Kardashevskiy 13790ce470cdSAlexey Kardashevskiy return NULL; 13800ce470cdSAlexey Kardashevskiy } 1381e703d2f7SGreg Kurz 1382e703d2f7SGreg Kurz void ppc_cpu_parse_features(const char *cpu_model) 1383e703d2f7SGreg Kurz { 1384e703d2f7SGreg Kurz CPUClass *cc; 1385e703d2f7SGreg Kurz ObjectClass *oc; 1386e703d2f7SGreg Kurz const char *typename; 1387e703d2f7SGreg Kurz gchar **model_pieces; 1388e703d2f7SGreg Kurz 1389e703d2f7SGreg Kurz model_pieces = g_strsplit(cpu_model, ",", 2); 1390e703d2f7SGreg Kurz if (!model_pieces[0]) { 1391e703d2f7SGreg Kurz error_report("Invalid/empty CPU model name"); 1392e703d2f7SGreg Kurz exit(1); 1393e703d2f7SGreg Kurz } 1394e703d2f7SGreg Kurz 1395e703d2f7SGreg Kurz oc = cpu_class_by_name(TYPE_POWERPC_CPU, model_pieces[0]); 1396e703d2f7SGreg Kurz if (oc == NULL) { 1397e703d2f7SGreg Kurz error_report("Unable to find CPU definition: %s", model_pieces[0]); 1398e703d2f7SGreg Kurz exit(1); 1399e703d2f7SGreg Kurz } 1400e703d2f7SGreg Kurz 1401e703d2f7SGreg Kurz typename = object_class_get_name(oc); 1402e703d2f7SGreg Kurz cc = CPU_CLASS(oc); 1403e703d2f7SGreg Kurz cc->parse_features(typename, model_pieces[1], &error_fatal); 1404e703d2f7SGreg Kurz g_strfreev(model_pieces); 1405e703d2f7SGreg Kurz } 1406