fault.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright 2014 IBM Corp.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #include <linux/workqueue.h>
  10. #include <linux/sched.h>
  11. #include <linux/pid.h>
  12. #include <linux/mm.h>
  13. #include <linux/moduleparam.h>
  14. #undef MODULE_PARAM_PREFIX
  15. #define MODULE_PARAM_PREFIX "cxl" "."
  16. #include <asm/current.h>
  17. #include <asm/copro.h>
  18. #include <asm/mmu.h>
  19. #include "cxl.h"
  20. static struct cxl_sste* find_free_sste(struct cxl_sste *primary_group,
  21. bool sec_hash,
  22. struct cxl_sste *secondary_group,
  23. unsigned int *lru)
  24. {
  25. unsigned int i, entry;
  26. struct cxl_sste *sste, *group = primary_group;
  27. for (i = 0; i < 2; i++) {
  28. for (entry = 0; entry < 8; entry++) {
  29. sste = group + entry;
  30. if (!(be64_to_cpu(sste->esid_data) & SLB_ESID_V))
  31. return sste;
  32. }
  33. if (!sec_hash)
  34. break;
  35. group = secondary_group;
  36. }
  37. /* Nothing free, select an entry to cast out */
  38. if (sec_hash && (*lru & 0x8))
  39. sste = secondary_group + (*lru & 0x7);
  40. else
  41. sste = primary_group + (*lru & 0x7);
  42. *lru = (*lru + 1) & 0xf;
  43. return sste;
  44. }
  45. static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb)
  46. {
  47. /* mask is the group index, we search primary and secondary here. */
  48. unsigned int mask = (ctx->sst_size >> 7)-1; /* SSTP0[SegTableSize] */
  49. bool sec_hash = 1;
  50. struct cxl_sste *sste;
  51. unsigned int hash;
  52. unsigned long flags;
  53. sec_hash = !!(cxl_p1n_read(ctx->afu, CXL_PSL_SR_An) & CXL_PSL_SR_An_SC);
  54. if (slb->vsid & SLB_VSID_B_1T)
  55. hash = (slb->esid >> SID_SHIFT_1T) & mask;
  56. else /* 256M */
  57. hash = (slb->esid >> SID_SHIFT) & mask;
  58. spin_lock_irqsave(&ctx->sste_lock, flags);
  59. sste = find_free_sste(ctx->sstp + (hash << 3), sec_hash,
  60. ctx->sstp + ((~hash & mask) << 3), &ctx->sst_lru);
  61. pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",
  62. sste - ctx->sstp, slb->vsid, slb->esid);
  63. sste->vsid_data = cpu_to_be64(slb->vsid);
  64. sste->esid_data = cpu_to_be64(slb->esid);
  65. spin_unlock_irqrestore(&ctx->sste_lock, flags);
  66. }
  67. static int cxl_fault_segment(struct cxl_context *ctx, struct mm_struct *mm,
  68. u64 ea)
  69. {
  70. struct copro_slb slb = {0,0};
  71. int rc;
  72. if (!(rc = copro_calculate_slb(mm, ea, &slb))) {
  73. cxl_load_segment(ctx, &slb);
  74. }
  75. return rc;
  76. }
  77. static void cxl_ack_ae(struct cxl_context *ctx)
  78. {
  79. unsigned long flags;
  80. cxl_ack_irq(ctx, CXL_PSL_TFC_An_AE, 0);
  81. spin_lock_irqsave(&ctx->lock, flags);
  82. ctx->pending_fault = true;
  83. ctx->fault_addr = ctx->dar;
  84. ctx->fault_dsisr = ctx->dsisr;
  85. spin_unlock_irqrestore(&ctx->lock, flags);
  86. wake_up_all(&ctx->wq);
  87. }
  88. static int cxl_handle_segment_miss(struct cxl_context *ctx,
  89. struct mm_struct *mm, u64 ea)
  90. {
  91. int rc;
  92. pr_devel("CXL interrupt: Segment fault pe: %i ea: %#llx\n", ctx->pe, ea);
  93. if ((rc = cxl_fault_segment(ctx, mm, ea)))
  94. cxl_ack_ae(ctx);
  95. else {
  96. mb(); /* Order seg table write to TFC MMIO write */
  97. cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
  98. }
  99. return IRQ_HANDLED;
  100. }
  101. static void cxl_handle_page_fault(struct cxl_context *ctx,
  102. struct mm_struct *mm, u64 dsisr, u64 dar)
  103. {
  104. unsigned flt = 0;
  105. int result;
  106. unsigned long access, flags;
  107. if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) {
  108. pr_devel("copro_handle_mm_fault failed: %#x\n", result);
  109. return cxl_ack_ae(ctx);
  110. }
  111. /*
  112. * update_mmu_cache() will not have loaded the hash since current->trap
  113. * is not a 0x400 or 0x300, so just call hash_page_mm() here.
  114. */
  115. access = _PAGE_PRESENT;
  116. if (dsisr & CXL_PSL_DSISR_An_S)
  117. access |= _PAGE_RW;
  118. if ((!ctx->kernel) || ~(dar & (1ULL << 63)))
  119. access |= _PAGE_USER;
  120. local_irq_save(flags);
  121. hash_page_mm(mm, dar, access, 0x300);
  122. local_irq_restore(flags);
  123. pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe);
  124. cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
  125. }
  126. void cxl_handle_fault(struct work_struct *fault_work)
  127. {
  128. struct cxl_context *ctx =
  129. container_of(fault_work, struct cxl_context, fault_work);
  130. u64 dsisr = ctx->dsisr;
  131. u64 dar = ctx->dar;
  132. struct task_struct *task;
  133. struct mm_struct *mm;
  134. if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr ||
  135. cxl_p2n_read(ctx->afu, CXL_PSL_DAR_An) != dar ||
  136. cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) != ctx->pe) {
  137. /* Most likely explanation is harmless - a dedicated process
  138. * has detached and these were cleared by the PSL purge, but
  139. * warn about it just in case */
  140. dev_notice(&ctx->afu->dev, "cxl_handle_fault: Translation fault regs changed\n");
  141. return;
  142. }
  143. pr_devel("CXL BOTTOM HALF handling fault for afu pe: %i. "
  144. "DSISR: %#llx DAR: %#llx\n", ctx->pe, dsisr, dar);
  145. if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
  146. pr_devel("cxl_handle_fault unable to get task %i\n",
  147. pid_nr(ctx->pid));
  148. cxl_ack_ae(ctx);
  149. return;
  150. }
  151. if (!(mm = get_task_mm(task))) {
  152. pr_devel("cxl_handle_fault unable to get mm %i\n",
  153. pid_nr(ctx->pid));
  154. cxl_ack_ae(ctx);
  155. goto out;
  156. }
  157. if (dsisr & CXL_PSL_DSISR_An_DS)
  158. cxl_handle_segment_miss(ctx, mm, dar);
  159. else if (dsisr & CXL_PSL_DSISR_An_DM)
  160. cxl_handle_page_fault(ctx, mm, dsisr, dar);
  161. else
  162. WARN(1, "cxl_handle_fault has nothing to handle\n");
  163. mmput(mm);
  164. out:
  165. put_task_struct(task);
  166. }
  167. static void cxl_prefault_one(struct cxl_context *ctx, u64 ea)
  168. {
  169. int rc;
  170. struct task_struct *task;
  171. struct mm_struct *mm;
  172. if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
  173. pr_devel("cxl_prefault_one unable to get task %i\n",
  174. pid_nr(ctx->pid));
  175. return;
  176. }
  177. if (!(mm = get_task_mm(task))) {
  178. pr_devel("cxl_prefault_one unable to get mm %i\n",
  179. pid_nr(ctx->pid));
  180. put_task_struct(task);
  181. return;
  182. }
  183. rc = cxl_fault_segment(ctx, mm, ea);
  184. mmput(mm);
  185. put_task_struct(task);
  186. }
  187. static u64 next_segment(u64 ea, u64 vsid)
  188. {
  189. if (vsid & SLB_VSID_B_1T)
  190. ea |= (1ULL << 40) - 1;
  191. else
  192. ea |= (1ULL << 28) - 1;
  193. return ea + 1;
  194. }
  195. static void cxl_prefault_vma(struct cxl_context *ctx)
  196. {
  197. u64 ea, last_esid = 0;
  198. struct copro_slb slb;
  199. struct vm_area_struct *vma;
  200. int rc;
  201. struct task_struct *task;
  202. struct mm_struct *mm;
  203. if (!(task = get_pid_task(ctx->pid, PIDTYPE_PID))) {
  204. pr_devel("cxl_prefault_vma unable to get task %i\n",
  205. pid_nr(ctx->pid));
  206. return;
  207. }
  208. if (!(mm = get_task_mm(task))) {
  209. pr_devel("cxl_prefault_vm unable to get mm %i\n",
  210. pid_nr(ctx->pid));
  211. goto out1;
  212. }
  213. down_read(&mm->mmap_sem);
  214. for (vma = mm->mmap; vma; vma = vma->vm_next) {
  215. for (ea = vma->vm_start; ea < vma->vm_end;
  216. ea = next_segment(ea, slb.vsid)) {
  217. rc = copro_calculate_slb(mm, ea, &slb);
  218. if (rc)
  219. continue;
  220. if (last_esid == slb.esid)
  221. continue;
  222. cxl_load_segment(ctx, &slb);
  223. last_esid = slb.esid;
  224. }
  225. }
  226. up_read(&mm->mmap_sem);
  227. mmput(mm);
  228. out1:
  229. put_task_struct(task);
  230. }
  231. void cxl_prefault(struct cxl_context *ctx, u64 wed)
  232. {
  233. switch (ctx->afu->prefault_mode) {
  234. case CXL_PREFAULT_WED:
  235. cxl_prefault_one(ctx, wed);
  236. break;
  237. case CXL_PREFAULT_ALL:
  238. cxl_prefault_vma(ctx);
  239. break;
  240. default:
  241. break;
  242. }
  243. }