1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2014 IBM Corp.
6 #include <linux/workqueue.h>
7 #include <linux/sched/signal.h>
8 #include <linux/sched/mm.h>
11 #include <linux/moduleparam.h>
13 #undef MODULE_PARAM_PREFIX
14 #define MODULE_PARAM_PREFIX "cxl" "."
15 #include <asm/current.h>
16 #include <asm/copro.h>
22 static bool sste_matches(struct cxl_sste
*sste
, struct copro_slb
*slb
)
24 return ((sste
->vsid_data
== cpu_to_be64(slb
->vsid
)) &&
25 (sste
->esid_data
== cpu_to_be64(slb
->esid
)));
29 * This finds a free SSTE for the given SLB, or returns NULL if it's already in
32 static struct cxl_sste
*find_free_sste(struct cxl_context
*ctx
,
33 struct copro_slb
*slb
)
35 struct cxl_sste
*primary
, *sste
, *ret
= NULL
;
36 unsigned int mask
= (ctx
->sst_size
>> 7) - 1; /* SSTP0[SegTableSize] */
40 if (slb
->vsid
& SLB_VSID_B_1T
)
41 hash
= (slb
->esid
>> SID_SHIFT_1T
) & mask
;
43 hash
= (slb
->esid
>> SID_SHIFT
) & mask
;
45 primary
= ctx
->sstp
+ (hash
<< 3);
47 for (entry
= 0, sste
= primary
; entry
< 8; entry
++, sste
++) {
48 if (!ret
&& !(be64_to_cpu(sste
->esid_data
) & SLB_ESID_V
))
50 if (sste_matches(sste
, slb
))
56 /* Nothing free, select an entry to cast out */
57 ret
= primary
+ ctx
->sst_lru
;
58 ctx
->sst_lru
= (ctx
->sst_lru
+ 1) & 0x7;
63 static void cxl_load_segment(struct cxl_context
*ctx
, struct copro_slb
*slb
)
65 /* mask is the group index, we search primary and secondary here. */
66 struct cxl_sste
*sste
;
69 spin_lock_irqsave(&ctx
->sste_lock
, flags
);
70 sste
= find_free_sste(ctx
, slb
);
74 pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",
75 sste
- ctx
->sstp
, slb
->vsid
, slb
->esid
);
76 trace_cxl_ste_write(ctx
, sste
- ctx
->sstp
, slb
->esid
, slb
->vsid
);
78 sste
->vsid_data
= cpu_to_be64(slb
->vsid
);
79 sste
->esid_data
= cpu_to_be64(slb
->esid
);
81 spin_unlock_irqrestore(&ctx
->sste_lock
, flags
);
84 static int cxl_fault_segment(struct cxl_context
*ctx
, struct mm_struct
*mm
,
87 struct copro_slb slb
= {0,0};
90 if (!(rc
= copro_calculate_slb(mm
, ea
, &slb
))) {
91 cxl_load_segment(ctx
, &slb
);
97 static void cxl_ack_ae(struct cxl_context
*ctx
)
101 cxl_ops
->ack_irq(ctx
, CXL_PSL_TFC_An_AE
, 0);
103 spin_lock_irqsave(&ctx
->lock
, flags
);
104 ctx
->pending_fault
= true;
105 ctx
->fault_addr
= ctx
->dar
;
106 ctx
->fault_dsisr
= ctx
->dsisr
;
107 spin_unlock_irqrestore(&ctx
->lock
, flags
);
109 wake_up_all(&ctx
->wq
);
112 static int cxl_handle_segment_miss(struct cxl_context
*ctx
,
113 struct mm_struct
*mm
, u64 ea
)
117 pr_devel("CXL interrupt: Segment fault pe: %i ea: %#llx\n", ctx
->pe
, ea
);
118 trace_cxl_ste_miss(ctx
, ea
);
120 if ((rc
= cxl_fault_segment(ctx
, mm
, ea
)))
124 mb(); /* Order seg table write to TFC MMIO write */
125 cxl_ops
->ack_irq(ctx
, CXL_PSL_TFC_An_R
, 0);
131 int cxl_handle_mm_fault(struct mm_struct
*mm
, u64 dsisr
, u64 dar
)
135 unsigned long access
, flags
, inv_flags
= 0;
138 * Add the fault handling cpu to task mm cpumask so that we
139 * can do a safe lockless page table walk when inserting the
140 * hash page table entry. This function get called with a
141 * valid mm for user space addresses. Hence using the if (mm)
142 * check is sufficient here.
144 if (mm
&& !cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm
))) {
145 cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm
));
147 * We need to make sure we walk the table only after
148 * we update the cpumask. The other side of the barrier
149 * is explained in serialize_against_pte_lookup()
153 if ((result
= copro_handle_mm_fault(mm
, dar
, dsisr
, &flt
))) {
154 pr_devel("copro_handle_mm_fault failed: %#x\n", result
);
158 if (!radix_enabled()) {
160 * update_mmu_cache() will not have loaded the hash since current->trap
161 * is not a 0x400 or 0x300, so just call hash_page_mm() here.
163 access
= _PAGE_PRESENT
| _PAGE_READ
;
164 if (dsisr
& CXL_PSL_DSISR_An_S
)
165 access
|= _PAGE_WRITE
;
167 if (!mm
&& (get_region_id(dar
) != USER_REGION_ID
))
168 access
|= _PAGE_PRIVILEGED
;
170 if (dsisr
& DSISR_NOHPTE
)
171 inv_flags
|= HPTE_NOHPTE_UPDATE
;
173 local_irq_save(flags
);
174 hash_page_mm(mm
, dar
, access
, 0x300, inv_flags
);
175 local_irq_restore(flags
);
180 static void cxl_handle_page_fault(struct cxl_context
*ctx
,
181 struct mm_struct
*mm
,
184 trace_cxl_pte_miss(ctx
, dsisr
, dar
);
186 if (cxl_handle_mm_fault(mm
, dsisr
, dar
)) {
189 pr_devel("Page fault successfully handled for pe: %i!\n", ctx
->pe
);
190 cxl_ops
->ack_irq(ctx
, CXL_PSL_TFC_An_R
, 0);
195 * Returns the mm_struct corresponding to the context ctx.
196 * mm_users == 0, the context may be in the process of being closed.
198 static struct mm_struct
*get_mem_context(struct cxl_context
*ctx
)
203 if (!atomic_inc_not_zero(&ctx
->mm
->mm_users
))
209 static bool cxl_is_segment_miss(struct cxl_context
*ctx
, u64 dsisr
)
211 if ((cxl_is_power8() && (dsisr
& CXL_PSL_DSISR_An_DS
)))
217 static bool cxl_is_page_fault(struct cxl_context
*ctx
, u64 dsisr
)
219 if ((cxl_is_power8()) && (dsisr
& CXL_PSL_DSISR_An_DM
))
228 void cxl_handle_fault(struct work_struct
*fault_work
)
230 struct cxl_context
*ctx
=
231 container_of(fault_work
, struct cxl_context
, fault_work
);
232 u64 dsisr
= ctx
->dsisr
;
234 struct mm_struct
*mm
= NULL
;
236 if (cpu_has_feature(CPU_FTR_HVMODE
)) {
237 if (cxl_p2n_read(ctx
->afu
, CXL_PSL_DSISR_An
) != dsisr
||
238 cxl_p2n_read(ctx
->afu
, CXL_PSL_DAR_An
) != dar
||
239 cxl_p2n_read(ctx
->afu
, CXL_PSL_PEHandle_An
) != ctx
->pe
) {
240 /* Most likely explanation is harmless - a dedicated
241 * process has detached and these were cleared by the
242 * PSL purge, but warn about it just in case
244 dev_notice(&ctx
->afu
->dev
, "cxl_handle_fault: Translation fault regs changed\n");
249 /* Early return if the context is being / has been detached */
250 if (ctx
->status
== CLOSED
) {
255 pr_devel("CXL BOTTOM HALF handling fault for afu pe: %i. "
256 "DSISR: %#llx DAR: %#llx\n", ctx
->pe
, dsisr
, dar
);
260 mm
= get_mem_context(ctx
);
262 pr_devel("%s: unable to get mm for pe=%d pid=%i\n",
263 __func__
, ctx
->pe
, pid_nr(ctx
->pid
));
267 pr_devel("Handling page fault for pe=%d pid=%i\n",
268 ctx
->pe
, pid_nr(ctx
->pid
));
272 if (cxl_is_segment_miss(ctx
, dsisr
))
273 cxl_handle_segment_miss(ctx
, mm
, dar
);
274 else if (cxl_is_page_fault(ctx
, dsisr
))
275 cxl_handle_page_fault(ctx
, mm
, dsisr
, dar
);
277 WARN(1, "cxl_handle_fault has nothing to handle\n");
283 static void cxl_prefault_one(struct cxl_context
*ctx
, u64 ea
)
285 struct mm_struct
*mm
;
287 mm
= get_mem_context(ctx
);
289 pr_devel("cxl_prefault_one unable to get mm %i\n",
294 cxl_fault_segment(ctx
, mm
, ea
);
299 static u64
next_segment(u64 ea
, u64 vsid
)
301 if (vsid
& SLB_VSID_B_1T
)
302 ea
|= (1ULL << 40) - 1;
304 ea
|= (1ULL << 28) - 1;
309 static void cxl_prefault_vma(struct cxl_context
*ctx
)
311 u64 ea
, last_esid
= 0;
312 struct copro_slb slb
;
313 struct vm_area_struct
*vma
;
315 struct mm_struct
*mm
;
317 mm
= get_mem_context(ctx
);
319 pr_devel("cxl_prefault_vm unable to get mm %i\n",
324 down_read(&mm
->mmap_sem
);
325 for (vma
= mm
->mmap
; vma
; vma
= vma
->vm_next
) {
326 for (ea
= vma
->vm_start
; ea
< vma
->vm_end
;
327 ea
= next_segment(ea
, slb
.vsid
)) {
328 rc
= copro_calculate_slb(mm
, ea
, &slb
);
332 if (last_esid
== slb
.esid
)
335 cxl_load_segment(ctx
, &slb
);
336 last_esid
= slb
.esid
;
339 up_read(&mm
->mmap_sem
);
344 void cxl_prefault(struct cxl_context
*ctx
, u64 wed
)
346 switch (ctx
->afu
->prefault_mode
) {
347 case CXL_PREFAULT_WED
:
348 cxl_prefault_one(ctx
, wed
);
350 case CXL_PREFAULT_ALL
:
351 cxl_prefault_vma(ctx
);