interrupt.c 5.7 KB

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