17b9cbadbSAurelien Jarno /* 27b9cbadbSAurelien Jarno * QEMU MIPS interrupt support 37b9cbadbSAurelien Jarno * 47b9cbadbSAurelien Jarno * Permission is hereby granted, free of charge, to any person obtaining a copy 57b9cbadbSAurelien Jarno * of this software and associated documentation files (the "Software"), to deal 67b9cbadbSAurelien Jarno * in the Software without restriction, including without limitation the rights 77b9cbadbSAurelien Jarno * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 87b9cbadbSAurelien Jarno * copies of the Software, and to permit persons to whom the Software is 97b9cbadbSAurelien Jarno * furnished to do so, subject to the following conditions: 107b9cbadbSAurelien Jarno * 117b9cbadbSAurelien Jarno * The above copyright notice and this permission notice shall be included in 127b9cbadbSAurelien Jarno * all copies or substantial portions of the Software. 137b9cbadbSAurelien Jarno * 147b9cbadbSAurelien Jarno * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157b9cbadbSAurelien Jarno * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167b9cbadbSAurelien Jarno * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177b9cbadbSAurelien Jarno * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 187b9cbadbSAurelien Jarno * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 197b9cbadbSAurelien Jarno * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 207b9cbadbSAurelien Jarno * THE SOFTWARE. 217b9cbadbSAurelien Jarno */ 227b9cbadbSAurelien Jarno 23c684822aSPeter Maydell #include "qemu/osdep.h" 24215581bdSAleksandar Markovic #include "qemu/main-loop.h" 2564552b6bSMarkus Armbruster #include "hw/irq.h" 260d09e41aSPaolo Bonzini #include "hw/mips/cpudevs.h" 274de9b249Sths #include "cpu.h" 28b1bd8b28SSanjay Lal #include "sysemu/kvm.h" 29b1bd8b28SSanjay Lal #include "kvm_mips.h" 304de9b249Sths 31d537cf6cSpbrook static void cpu_mips_irq_request(void *opaque, int irq, int level) 324de9b249Sths { 33d8ed887bSAndreas Färber MIPSCPU *cpu = opaque; 34d8ed887bSAndreas Färber CPUMIPSState *env = &cpu->env; 35d8ed887bSAndreas Färber CPUState *cs = CPU(cpu); 36215581bdSAleksandar Markovic bool locked = false; 374de9b249Sths 386c06ea4cSAleksandar Markovic if (irq < 0 || irq > 7) { 394de9b249Sths return; 406c06ea4cSAleksandar Markovic } 414de9b249Sths 42215581bdSAleksandar Markovic /* Make sure locking works even if BQL is already held by the caller */ 43215581bdSAleksandar Markovic if (!qemu_mutex_iothread_locked()) { 44215581bdSAleksandar Markovic locked = true; 45215581bdSAleksandar Markovic qemu_mutex_lock_iothread(); 46215581bdSAleksandar Markovic } 47215581bdSAleksandar Markovic 484de9b249Sths if (level) { 4939d51eb8Sths env->CP0_Cause |= 1 << (irq + CP0Ca_IP); 50b1bd8b28SSanjay Lal 51b1bd8b28SSanjay Lal if (kvm_enabled() && irq == 2) { 52b1bd8b28SSanjay Lal kvm_mips_set_interrupt(cpu, irq, level); 53b1bd8b28SSanjay Lal } 54b1bd8b28SSanjay Lal 554de9b249Sths } else { 5639d51eb8Sths env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP)); 57b1bd8b28SSanjay Lal 58b1bd8b28SSanjay Lal if (kvm_enabled() && irq == 2) { 59b1bd8b28SSanjay Lal kvm_mips_set_interrupt(cpu, irq, level); 60b1bd8b28SSanjay Lal } 614de9b249Sths } 6236388314SEdgar E. Iglesias 6336388314SEdgar E. Iglesias if (env->CP0_Cause & CP0Ca_IP_mask) { 64c3affe56SAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_HARD); 6536388314SEdgar E. Iglesias } else { 66d8ed887bSAndreas Färber cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 6736388314SEdgar E. Iglesias } 68215581bdSAleksandar Markovic 69215581bdSAleksandar Markovic if (locked) { 70215581bdSAleksandar Markovic qemu_mutex_unlock_iothread(); 71215581bdSAleksandar Markovic } 724de9b249Sths } 73d537cf6cSpbrook 745a975d43SPaolo Bonzini void cpu_mips_irq_init_cpu(MIPSCPU *cpu) 75d537cf6cSpbrook { 765a975d43SPaolo Bonzini CPUMIPSState *env = &cpu->env; 77d537cf6cSpbrook qemu_irq *qi; 78d537cf6cSpbrook int i; 79d537cf6cSpbrook 805a7330b3SRichard Henderson qi = qemu_allocate_irqs(cpu_mips_irq_request, env_archcpu(env), 8); 81d537cf6cSpbrook for (i = 0; i < 8; i++) { 82d537cf6cSpbrook env->irq[i] = qi[i]; 83d537cf6cSpbrook } 84*0287d89fSPaolo Bonzini g_free(qi); 85d537cf6cSpbrook } 865dc5d9f0SAurelien Jarno 8761c56c8cSAndreas Färber void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level) 885dc5d9f0SAurelien Jarno { 895dc5d9f0SAurelien Jarno if (irq < 0 || irq > 2) { 905dc5d9f0SAurelien Jarno return; 915dc5d9f0SAurelien Jarno } 925dc5d9f0SAurelien Jarno 935dc5d9f0SAurelien Jarno qemu_set_irq(env->irq[irq], level); 945dc5d9f0SAurelien Jarno } 95