^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * KVM/MIPS: Interrupt delivery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Authors: Sanjay Lal <sanjayl@kymasys.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kvm_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "interrupt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, unsigned int priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) set_bit(priority, &vcpu->arch.pending_exceptions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, unsigned int priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) clear_bit(priority, &vcpu->arch.pending_exceptions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Cause bits to reflect the pending timer interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * the EXC code will be set when we are actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * delivering the interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Queue up an INT exception for the core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_TIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct kvm_mips_interrupt *irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int intr = (int)irq->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Cause bits to reflect the pending IO interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * the EXC code will be set when we are actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * delivering the interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) kvm_set_c0_guest_cause(vcpu->arch.cop0, 1 << (intr + 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) kvm_mips_queue_irq(vcpu, kvm_irq_to_priority(intr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct kvm_mips_interrupt *irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int intr = (int)irq->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) kvm_clear_c0_guest_cause(vcpu->arch.cop0, 1 << (-intr + 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) kvm_mips_dequeue_irq(vcpu, kvm_irq_to_priority(-intr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Deliver the interrupt of the corresponding priority, if possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u32 cause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int allowed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u32 exccode, ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct kvm_vcpu_arch *arch = &vcpu->arch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct mips_coproc *cop0 = vcpu->arch.cop0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (priority == MIPS_EXC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ie = 1 << (kvm_priority_to_irq[priority] + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if ((kvm_read_c0_guest_status(cop0) & ST0_IE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) && (kvm_read_c0_guest_status(cop0) & ie)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) allowed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) exccode = EXCCODE_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Are we allowed to deliver the interrupt ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (allowed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* save old pc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) kvm_write_c0_guest_epc(cop0, arch->pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) kvm_set_c0_guest_status(cop0, ST0_EXL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (cause & CAUSEF_BD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) kvm_debug("Delivering INT @ pc %#lx\n", arch->pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kvm_err("Trying to deliver interrupt when EXL is already set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) kvm_change_c0_guest_cause(cop0, CAUSEF_EXCCODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) (exccode << CAUSEB_EXCCODE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* XXXSL Set PC to the interrupt exception entry point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) arch->pc = kvm_mips_guest_exception_base(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (kvm_read_c0_guest_cause(cop0) & CAUSEF_IV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) arch->pc += 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) arch->pc += 0x180;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) clear_bit(priority, &vcpu->arch.pending_exceptions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return allowed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u32 cause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, u32 cause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned long *pending = &vcpu->arch.pending_exceptions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!(*pending) && !(*pending_clr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) priority = __ffs(*pending_clr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) while (priority <= MIPS_EXC_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (kvm_mips_callbacks->irq_clear(vcpu, priority, cause)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) priority = find_next_bit(pending_clr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) BITS_PER_BYTE * sizeof(*pending_clr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) priority + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) priority = __ffs(*pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) while (priority <= MIPS_EXC_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (kvm_mips_callbacks->irq_deliver(vcpu, priority, cause)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) priority = find_next_bit(pending,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) BITS_PER_BYTE * sizeof(*pending),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) priority + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int kvm_mips_pending_timer(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }