vgic-v2-sr.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright (C) 2012-2015 - ARM Ltd
  3. * Author: Marc Zyngier <marc.zyngier@arm.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <linux/compiler.h>
  18. #include <linux/irqchip/arm-gic.h>
  19. #include <linux/kvm_host.h>
  20. #include <asm/kvm_emulate.h>
  21. #include <asm/kvm_hyp.h>
  22. static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
  23. void __iomem *base)
  24. {
  25. struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
  26. int nr_lr = (kern_hyp_va(&kvm_vgic_global_state))->nr_lr;
  27. u32 eisr0, eisr1;
  28. int i;
  29. bool expect_mi;
  30. expect_mi = !!(cpu_if->vgic_hcr & GICH_HCR_UIE);
  31. for (i = 0; i < nr_lr; i++) {
  32. if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
  33. continue;
  34. expect_mi |= (!(cpu_if->vgic_lr[i] & GICH_LR_HW) &&
  35. (cpu_if->vgic_lr[i] & GICH_LR_EOI));
  36. }
  37. if (expect_mi) {
  38. cpu_if->vgic_misr = readl_relaxed(base + GICH_MISR);
  39. if (cpu_if->vgic_misr & GICH_MISR_EOI) {
  40. eisr0 = readl_relaxed(base + GICH_EISR0);
  41. if (unlikely(nr_lr > 32))
  42. eisr1 = readl_relaxed(base + GICH_EISR1);
  43. else
  44. eisr1 = 0;
  45. } else {
  46. eisr0 = eisr1 = 0;
  47. }
  48. } else {
  49. cpu_if->vgic_misr = 0;
  50. eisr0 = eisr1 = 0;
  51. }
  52. #ifdef CONFIG_CPU_BIG_ENDIAN
  53. cpu_if->vgic_eisr = ((u64)eisr0 << 32) | eisr1;
  54. #else
  55. cpu_if->vgic_eisr = ((u64)eisr1 << 32) | eisr0;
  56. #endif
  57. }
  58. static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
  59. {
  60. struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
  61. int nr_lr = (kern_hyp_va(&kvm_vgic_global_state))->nr_lr;
  62. u32 elrsr0, elrsr1;
  63. elrsr0 = readl_relaxed(base + GICH_ELRSR0);
  64. if (unlikely(nr_lr > 32))
  65. elrsr1 = readl_relaxed(base + GICH_ELRSR1);
  66. else
  67. elrsr1 = 0;
  68. cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0;
  69. }
  70. static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
  71. {
  72. struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
  73. int nr_lr = (kern_hyp_va(&kvm_vgic_global_state))->nr_lr;
  74. int i;
  75. for (i = 0; i < nr_lr; i++) {
  76. if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
  77. continue;
  78. if (cpu_if->vgic_elrsr & (1UL << i))
  79. cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
  80. else
  81. cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
  82. writel_relaxed(0, base + GICH_LR0 + (i * 4));
  83. }
  84. }
  85. /* vcpu is already in the HYP VA space */
  86. void __hyp_text __vgic_v2_save_state(struct kvm_vcpu *vcpu)
  87. {
  88. struct kvm *kvm = kern_hyp_va(vcpu->kvm);
  89. struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
  90. struct vgic_dist *vgic = &kvm->arch.vgic;
  91. void __iomem *base = kern_hyp_va(vgic->vctrl_base);
  92. if (!base)
  93. return;
  94. cpu_if->vgic_vmcr = readl_relaxed(base + GICH_VMCR);
  95. if (vcpu->arch.vgic_cpu.live_lrs) {
  96. cpu_if->vgic_apr = readl_relaxed(base + GICH_APR);
  97. save_maint_int_state(vcpu, base);
  98. save_elrsr(vcpu, base);
  99. save_lrs(vcpu, base);
  100. writel_relaxed(0, base + GICH_HCR);
  101. vcpu->arch.vgic_cpu.live_lrs = 0;
  102. } else {
  103. cpu_if->vgic_eisr = 0;
  104. cpu_if->vgic_elrsr = ~0UL;
  105. cpu_if->vgic_misr = 0;
  106. cpu_if->vgic_apr = 0;
  107. }
  108. }
  109. /* vcpu is already in the HYP VA space */
  110. void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
  111. {
  112. struct kvm *kvm = kern_hyp_va(vcpu->kvm);
  113. struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
  114. struct vgic_dist *vgic = &kvm->arch.vgic;
  115. void __iomem *base = kern_hyp_va(vgic->vctrl_base);
  116. int nr_lr = (kern_hyp_va(&kvm_vgic_global_state))->nr_lr;
  117. int i;
  118. u64 live_lrs = 0;
  119. if (!base)
  120. return;
  121. for (i = 0; i < nr_lr; i++)
  122. if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
  123. live_lrs |= 1UL << i;
  124. if (live_lrs) {
  125. writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
  126. writel_relaxed(cpu_if->vgic_apr, base + GICH_APR);
  127. for (i = 0; i < nr_lr; i++) {
  128. if (!(live_lrs & (1UL << i)))
  129. continue;
  130. writel_relaxed(cpu_if->vgic_lr[i],
  131. base + GICH_LR0 + (i * 4));
  132. }
  133. }
  134. writel_relaxed(cpu_if->vgic_vmcr, base + GICH_VMCR);
  135. vcpu->arch.vgic_cpu.live_lrs = live_lrs;
  136. }
  137. #ifdef CONFIG_ARM64
  138. /*
  139. * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
  140. * guest.
  141. *
  142. * @vcpu: the offending vcpu
  143. *
  144. * Returns:
  145. * 1: GICV access successfully performed
  146. * 0: Not a GICV access
  147. * -1: Illegal GICV access
  148. */
  149. int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
  150. {
  151. struct kvm *kvm = kern_hyp_va(vcpu->kvm);
  152. struct vgic_dist *vgic = &kvm->arch.vgic;
  153. phys_addr_t fault_ipa;
  154. void __iomem *addr;
  155. int rd;
  156. /* Build the full address */
  157. fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
  158. fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);
  159. /* If not for GICV, move on */
  160. if (fault_ipa < vgic->vgic_cpu_base ||
  161. fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
  162. return 0;
  163. /* Reject anything but a 32bit access */
  164. if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32))
  165. return -1;
  166. /* Not aligned? Don't bother */
  167. if (fault_ipa & 3)
  168. return -1;
  169. rd = kvm_vcpu_dabt_get_rd(vcpu);
  170. addr = kern_hyp_va(hyp_symbol_addr(kvm_vgic_global_state)->vcpu_base_va);
  171. addr += fault_ipa - vgic->vgic_cpu_base;
  172. if (kvm_vcpu_dabt_iswrite(vcpu)) {
  173. u32 data = vcpu_data_guest_to_host(vcpu,
  174. vcpu_get_reg(vcpu, rd),
  175. sizeof(u32));
  176. writel_relaxed(data, addr);
  177. } else {
  178. u32 data = readl_relaxed(addr);
  179. vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
  180. sizeof(u32)));
  181. }
  182. return 1;
  183. }
  184. #endif