e500_emulate.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
  3. *
  4. * Author: Yu Liu, <yu.liu@freescale.com>
  5. *
  6. * Description:
  7. * This file is derived from arch/powerpc/kvm/44x_emulate.c,
  8. * by Hollis Blanchard <hollisb@us.ibm.com>.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License, version 2, as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <asm/kvm_ppc.h>
  15. #include <asm/disassemble.h>
  16. #include <asm/dbell.h>
  17. #include "booke.h"
  18. #include "e500.h"
  19. #define XOP_MSGSND 206
  20. #define XOP_MSGCLR 238
  21. #define XOP_TLBIVAX 786
  22. #define XOP_TLBSX 914
  23. #define XOP_TLBRE 946
  24. #define XOP_TLBWE 978
  25. #define XOP_TLBILX 18
  26. #ifdef CONFIG_KVM_E500MC
  27. static int dbell2prio(ulong param)
  28. {
  29. int msg = param & PPC_DBELL_TYPE_MASK;
  30. int prio = -1;
  31. switch (msg) {
  32. case PPC_DBELL_TYPE(PPC_DBELL):
  33. prio = BOOKE_IRQPRIO_DBELL;
  34. break;
  35. case PPC_DBELL_TYPE(PPC_DBELL_CRIT):
  36. prio = BOOKE_IRQPRIO_DBELL_CRIT;
  37. break;
  38. default:
  39. break;
  40. }
  41. return prio;
  42. }
  43. static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb)
  44. {
  45. ulong param = vcpu->arch.gpr[rb];
  46. int prio = dbell2prio(param);
  47. if (prio < 0)
  48. return EMULATE_FAIL;
  49. clear_bit(prio, &vcpu->arch.pending_exceptions);
  50. return EMULATE_DONE;
  51. }
  52. static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
  53. {
  54. ulong param = vcpu->arch.gpr[rb];
  55. int prio = dbell2prio(rb);
  56. int pir = param & PPC_DBELL_PIR_MASK;
  57. int i;
  58. struct kvm_vcpu *cvcpu;
  59. if (prio < 0)
  60. return EMULATE_FAIL;
  61. kvm_for_each_vcpu(i, cvcpu, vcpu->kvm) {
  62. int cpir = cvcpu->arch.shared->pir;
  63. if ((param & PPC_DBELL_MSG_BRDCAST) || (cpir == pir)) {
  64. set_bit(prio, &cvcpu->arch.pending_exceptions);
  65. kvm_vcpu_kick(cvcpu);
  66. }
  67. }
  68. return EMULATE_DONE;
  69. }
  70. #endif
  71. int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
  72. unsigned int inst, int *advance)
  73. {
  74. int emulated = EMULATE_DONE;
  75. int ra = get_ra(inst);
  76. int rb = get_rb(inst);
  77. int rt = get_rt(inst);
  78. gva_t ea;
  79. switch (get_op(inst)) {
  80. case 31:
  81. switch (get_xop(inst)) {
  82. #ifdef CONFIG_KVM_E500MC
  83. case XOP_MSGSND:
  84. emulated = kvmppc_e500_emul_msgsnd(vcpu, rb);
  85. break;
  86. case XOP_MSGCLR:
  87. emulated = kvmppc_e500_emul_msgclr(vcpu, rb);
  88. break;
  89. #endif
  90. case XOP_TLBRE:
  91. emulated = kvmppc_e500_emul_tlbre(vcpu);
  92. break;
  93. case XOP_TLBWE:
  94. emulated = kvmppc_e500_emul_tlbwe(vcpu);
  95. break;
  96. case XOP_TLBSX:
  97. ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
  98. emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
  99. break;
  100. case XOP_TLBILX: {
  101. int type = rt & 0x3;
  102. ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
  103. emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
  104. break;
  105. }
  106. case XOP_TLBIVAX:
  107. ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
  108. emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
  109. break;
  110. default:
  111. emulated = EMULATE_FAIL;
  112. }
  113. break;
  114. default:
  115. emulated = EMULATE_FAIL;
  116. }
  117. if (emulated == EMULATE_FAIL)
  118. emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
  119. return emulated;
  120. }
  121. int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
  122. {
  123. struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
  124. int emulated = EMULATE_DONE;
  125. switch (sprn) {
  126. #ifndef CONFIG_KVM_BOOKE_HV
  127. case SPRN_PID:
  128. kvmppc_set_pid(vcpu, spr_val);
  129. break;
  130. case SPRN_PID1:
  131. if (spr_val != 0)
  132. return EMULATE_FAIL;
  133. vcpu_e500->pid[1] = spr_val;
  134. break;
  135. case SPRN_PID2:
  136. if (spr_val != 0)
  137. return EMULATE_FAIL;
  138. vcpu_e500->pid[2] = spr_val;
  139. break;
  140. case SPRN_MAS0:
  141. vcpu->arch.shared->mas0 = spr_val;
  142. break;
  143. case SPRN_MAS1:
  144. vcpu->arch.shared->mas1 = spr_val;
  145. break;
  146. case SPRN_MAS2:
  147. vcpu->arch.shared->mas2 = spr_val;
  148. break;
  149. case SPRN_MAS3:
  150. vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
  151. vcpu->arch.shared->mas7_3 |= spr_val;
  152. break;
  153. case SPRN_MAS4:
  154. vcpu->arch.shared->mas4 = spr_val;
  155. break;
  156. case SPRN_MAS6:
  157. vcpu->arch.shared->mas6 = spr_val;
  158. break;
  159. case SPRN_MAS7:
  160. vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
  161. vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
  162. break;
  163. #endif
  164. case SPRN_L1CSR0:
  165. vcpu_e500->l1csr0 = spr_val;
  166. vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
  167. break;
  168. case SPRN_L1CSR1:
  169. vcpu_e500->l1csr1 = spr_val;
  170. break;
  171. case SPRN_HID0:
  172. vcpu_e500->hid0 = spr_val;
  173. break;
  174. case SPRN_HID1:
  175. vcpu_e500->hid1 = spr_val;
  176. break;
  177. case SPRN_MMUCSR0:
  178. emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
  179. spr_val);
  180. break;
  181. /* extra exceptions */
  182. case SPRN_IVOR32:
  183. vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
  184. break;
  185. case SPRN_IVOR33:
  186. vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
  187. break;
  188. case SPRN_IVOR34:
  189. vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
  190. break;
  191. case SPRN_IVOR35:
  192. vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
  193. break;
  194. #ifdef CONFIG_KVM_BOOKE_HV
  195. case SPRN_IVOR36:
  196. vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] = spr_val;
  197. break;
  198. case SPRN_IVOR37:
  199. vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] = spr_val;
  200. break;
  201. #endif
  202. default:
  203. emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val);
  204. }
  205. return emulated;
  206. }
  207. int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
  208. {
  209. struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
  210. int emulated = EMULATE_DONE;
  211. switch (sprn) {
  212. #ifndef CONFIG_KVM_BOOKE_HV
  213. case SPRN_PID:
  214. *spr_val = vcpu_e500->pid[0];
  215. break;
  216. case SPRN_PID1:
  217. *spr_val = vcpu_e500->pid[1];
  218. break;
  219. case SPRN_PID2:
  220. *spr_val = vcpu_e500->pid[2];
  221. break;
  222. case SPRN_MAS0:
  223. *spr_val = vcpu->arch.shared->mas0;
  224. break;
  225. case SPRN_MAS1:
  226. *spr_val = vcpu->arch.shared->mas1;
  227. break;
  228. case SPRN_MAS2:
  229. *spr_val = vcpu->arch.shared->mas2;
  230. break;
  231. case SPRN_MAS3:
  232. *spr_val = (u32)vcpu->arch.shared->mas7_3;
  233. break;
  234. case SPRN_MAS4:
  235. *spr_val = vcpu->arch.shared->mas4;
  236. break;
  237. case SPRN_MAS6:
  238. *spr_val = vcpu->arch.shared->mas6;
  239. break;
  240. case SPRN_MAS7:
  241. *spr_val = vcpu->arch.shared->mas7_3 >> 32;
  242. break;
  243. #endif
  244. case SPRN_DECAR:
  245. *spr_val = vcpu->arch.decar;
  246. break;
  247. case SPRN_TLB0CFG:
  248. *spr_val = vcpu->arch.tlbcfg[0];
  249. break;
  250. case SPRN_TLB1CFG:
  251. *spr_val = vcpu->arch.tlbcfg[1];
  252. break;
  253. case SPRN_L1CSR0:
  254. *spr_val = vcpu_e500->l1csr0;
  255. break;
  256. case SPRN_L1CSR1:
  257. *spr_val = vcpu_e500->l1csr1;
  258. break;
  259. case SPRN_HID0:
  260. *spr_val = vcpu_e500->hid0;
  261. break;
  262. case SPRN_HID1:
  263. *spr_val = vcpu_e500->hid1;
  264. break;
  265. case SPRN_SVR:
  266. *spr_val = vcpu_e500->svr;
  267. break;
  268. case SPRN_MMUCSR0:
  269. *spr_val = 0;
  270. break;
  271. case SPRN_MMUCFG:
  272. *spr_val = vcpu->arch.mmucfg;
  273. break;
  274. /* extra exceptions */
  275. case SPRN_IVOR32:
  276. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
  277. break;
  278. case SPRN_IVOR33:
  279. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA];
  280. break;
  281. case SPRN_IVOR34:
  282. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
  283. break;
  284. case SPRN_IVOR35:
  285. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
  286. break;
  287. #ifdef CONFIG_KVM_BOOKE_HV
  288. case SPRN_IVOR36:
  289. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL];
  290. break;
  291. case SPRN_IVOR37:
  292. *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT];
  293. break;
  294. #endif
  295. default:
  296. emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val);
  297. }
  298. return emulated;
  299. }