aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grumain.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-gru/grumain.c')
-rw-r--r--drivers/misc/sgi-gru/grumain.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 3d2fc216bae5..ec3f7a17d221 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -76,10 +76,9 @@ int gru_cpu_fault_map_id(void)
76/* Hit the asid limit. Start over */ 76/* Hit the asid limit. Start over */
77static int gru_wrap_asid(struct gru_state *gru) 77static int gru_wrap_asid(struct gru_state *gru)
78{ 78{
79 gru_dbg(grudev, "gru %p\n", gru); 79 gru_dbg(grudev, "gid %d\n", gru->gs_gid);
80 STAT(asid_wrap); 80 STAT(asid_wrap);
81 gru->gs_asid_gen++; 81 gru->gs_asid_gen++;
82 gru_flush_all_tlb(gru);
83 return MIN_ASID; 82 return MIN_ASID;
84} 83}
85 84
@@ -88,19 +87,21 @@ static int gru_reset_asid_limit(struct gru_state *gru, int asid)
88{ 87{
89 int i, gid, inuse_asid, limit; 88 int i, gid, inuse_asid, limit;
90 89
91 gru_dbg(grudev, "gru %p, asid 0x%x\n", gru, asid); 90 gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid);
92 STAT(asid_next); 91 STAT(asid_next);
93 limit = MAX_ASID; 92 limit = MAX_ASID;
94 if (asid >= limit) 93 if (asid >= limit)
95 asid = gru_wrap_asid(gru); 94 asid = gru_wrap_asid(gru);
95 gru_flush_all_tlb(gru);
96 gid = gru->gs_gid; 96 gid = gru->gs_gid;
97again: 97again:
98 for (i = 0; i < GRU_NUM_CCH; i++) { 98 for (i = 0; i < GRU_NUM_CCH; i++) {
99 if (!gru->gs_gts[i]) 99 if (!gru->gs_gts[i])
100 continue; 100 continue;
101 inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid; 101 inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid;
102 gru_dbg(grudev, "gru %p, inuse_asid 0x%x, cxtnum %d, gts %p\n", 102 gru_dbg(grudev, "gid %d, gts %p, gms %p, inuse 0x%x, cxt %d\n",
103 gru, inuse_asid, i, gru->gs_gts[i]); 103 gru->gs_gid, gru->gs_gts[i], gru->gs_gts[i]->ts_gms,
104 inuse_asid, i);
104 if (inuse_asid == asid) { 105 if (inuse_asid == asid) {
105 asid += ASID_INC; 106 asid += ASID_INC;
106 if (asid >= limit) { 107 if (asid >= limit) {
@@ -120,8 +121,8 @@ again:
120 } 121 }
121 gru->gs_asid_limit = limit; 122 gru->gs_asid_limit = limit;
122 gru->gs_asid = asid; 123 gru->gs_asid = asid;
123 gru_dbg(grudev, "gru %p, new asid 0x%x, new_limit 0x%x\n", gru, asid, 124 gru_dbg(grudev, "gid %d, new asid 0x%x, new_limit 0x%x\n", gru->gs_gid,
124 limit); 125 asid, limit);
125 return asid; 126 return asid;
126} 127}
127 128
@@ -130,14 +131,12 @@ static int gru_assign_asid(struct gru_state *gru)
130{ 131{
131 int asid; 132 int asid;
132 133
133 spin_lock(&gru->gs_asid_lock);
134 gru->gs_asid += ASID_INC; 134 gru->gs_asid += ASID_INC;
135 asid = gru->gs_asid; 135 asid = gru->gs_asid;
136 if (asid >= gru->gs_asid_limit) 136 if (asid >= gru->gs_asid_limit)
137 asid = gru_reset_asid_limit(gru, asid); 137 asid = gru_reset_asid_limit(gru, asid);
138 spin_unlock(&gru->gs_asid_lock);
139 138
140 gru_dbg(grudev, "gru %p, asid 0x%x\n", gru, asid); 139 gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid);
141 return asid; 140 return asid;
142} 141}
143 142
@@ -215,17 +214,20 @@ static int check_gru_resources(struct gru_state *gru, int cbr_au_count,
215 * TLB manangment requires tracking all GRU chiplets that have loaded a GSEG 214 * TLB manangment requires tracking all GRU chiplets that have loaded a GSEG
216 * context. 215 * context.
217 */ 216 */
218static int gru_load_mm_tracker(struct gru_state *gru, struct gru_mm_struct *gms, 217static int gru_load_mm_tracker(struct gru_state *gru,
219 int ctxnum) 218 struct gru_thread_state *gts)
220{ 219{
220 struct gru_mm_struct *gms = gts->ts_gms;
221 struct gru_mm_tracker *asids = &gms->ms_asids[gru->gs_gid]; 221 struct gru_mm_tracker *asids = &gms->ms_asids[gru->gs_gid];
222 unsigned short ctxbitmap = (1 << ctxnum); 222 unsigned short ctxbitmap = (1 << gts->ts_ctxnum);
223 int asid; 223 int asid;
224 224
225 spin_lock(&gms->ms_asid_lock); 225 spin_lock(&gms->ms_asid_lock);
226 asid = asids->mt_asid; 226 asid = asids->mt_asid;
227 227
228 if (asid == 0 || asids->mt_asid_gen != gru->gs_asid_gen) { 228 spin_lock(&gru->gs_asid_lock);
229 if (asid == 0 || (asids->mt_ctxbitmap == 0 && asids->mt_asid_gen !=
230 gru->gs_asid_gen)) {
229 asid = gru_assign_asid(gru); 231 asid = gru_assign_asid(gru);
230 asids->mt_asid = asid; 232 asids->mt_asid = asid;
231 asids->mt_asid_gen = gru->gs_asid_gen; 233 asids->mt_asid_gen = gru->gs_asid_gen;
@@ -233,6 +235,7 @@ static int gru_load_mm_tracker(struct gru_state *gru, struct gru_mm_struct *gms,
233 } else { 235 } else {
234 STAT(asid_reuse); 236 STAT(asid_reuse);
235 } 237 }
238 spin_unlock(&gru->gs_asid_lock);
236 239
237 BUG_ON(asids->mt_ctxbitmap & ctxbitmap); 240 BUG_ON(asids->mt_ctxbitmap & ctxbitmap);
238 asids->mt_ctxbitmap |= ctxbitmap; 241 asids->mt_ctxbitmap |= ctxbitmap;
@@ -241,24 +244,28 @@ static int gru_load_mm_tracker(struct gru_state *gru, struct gru_mm_struct *gms,
241 spin_unlock(&gms->ms_asid_lock); 244 spin_unlock(&gms->ms_asid_lock);
242 245
243 gru_dbg(grudev, 246 gru_dbg(grudev,
244 "gru %x, gms %p, ctxnum 0x%d, asid 0x%x, asidmap 0x%lx\n", 247 "gid %d, gts %p, gms %p, ctxnum %d, asid 0x%x, asidmap 0x%lx\n",
245 gru->gs_gid, gms, ctxnum, asid, gms->ms_asidmap[0]); 248 gru->gs_gid, gts, gms, gts->ts_ctxnum, asid,
249 gms->ms_asidmap[0]);
246 return asid; 250 return asid;
247} 251}
248 252
249static void gru_unload_mm_tracker(struct gru_state *gru, 253static void gru_unload_mm_tracker(struct gru_state *gru,
250 struct gru_mm_struct *gms, int ctxnum) 254 struct gru_thread_state *gts)
251{ 255{
256 struct gru_mm_struct *gms = gts->ts_gms;
252 struct gru_mm_tracker *asids; 257 struct gru_mm_tracker *asids;
253 unsigned short ctxbitmap; 258 unsigned short ctxbitmap;
254 259
255 asids = &gms->ms_asids[gru->gs_gid]; 260 asids = &gms->ms_asids[gru->gs_gid];
256 ctxbitmap = (1 << ctxnum); 261 ctxbitmap = (1 << gts->ts_ctxnum);
257 spin_lock(&gms->ms_asid_lock); 262 spin_lock(&gms->ms_asid_lock);
263 spin_lock(&gru->gs_asid_lock);
258 BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap); 264 BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap);
259 asids->mt_ctxbitmap ^= ctxbitmap; 265 asids->mt_ctxbitmap ^= ctxbitmap;
260 gru_dbg(grudev, "gru %x, gms %p, ctxnum 0x%d, asidmap 0x%lx\n", 266 gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum 0x%d, asidmap 0x%lx\n",
261 gru->gs_gid, gms, ctxnum, gms->ms_asidmap[0]); 267 gru->gs_gid, gts, gms, gts->ts_ctxnum, gms->ms_asidmap[0]);
268 spin_unlock(&gru->gs_asid_lock);
262 spin_unlock(&gms->ms_asid_lock); 269 spin_unlock(&gms->ms_asid_lock);
263} 270}
264 271
@@ -319,6 +326,7 @@ static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
319 gts->ts_vma = vma; 326 gts->ts_vma = vma;
320 gts->ts_tlb_int_select = -1; 327 gts->ts_tlb_int_select = -1;
321 gts->ts_gms = gru_register_mmu_notifier(); 328 gts->ts_gms = gru_register_mmu_notifier();
329 gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT);
322 if (!gts->ts_gms) 330 if (!gts->ts_gms)
323 goto err; 331 goto err;
324 332
@@ -399,7 +407,7 @@ static void gru_free_gru_context(struct gru_thread_state *gts)
399 struct gru_state *gru; 407 struct gru_state *gru;
400 408
401 gru = gts->ts_gru; 409 gru = gts->ts_gru;
402 gru_dbg(grudev, "gts %p, gru %p\n", gts, gru); 410 gru_dbg(grudev, "gts %p, gid %d\n", gts, gru->gs_gid);
403 411
404 spin_lock(&gru->gs_lock); 412 spin_lock(&gru->gs_lock);
405 gru->gs_gts[gts->ts_ctxnum] = NULL; 413 gru->gs_gts[gts->ts_ctxnum] = NULL;
@@ -408,6 +416,7 @@ static void gru_free_gru_context(struct gru_thread_state *gts)
408 __clear_bit(gts->ts_ctxnum, &gru->gs_context_map); 416 __clear_bit(gts->ts_ctxnum, &gru->gs_context_map);
409 gts->ts_ctxnum = NULLCTX; 417 gts->ts_ctxnum = NULLCTX;
410 gts->ts_gru = NULL; 418 gts->ts_gru = NULL;
419 gts->ts_blade = -1;
411 spin_unlock(&gru->gs_lock); 420 spin_unlock(&gru->gs_lock);
412 421
413 gts_drop(gts); 422 gts_drop(gts);
@@ -432,8 +441,8 @@ static inline long gru_copy_handle(void *d, void *s)
432 return GRU_HANDLE_BYTES; 441 return GRU_HANDLE_BYTES;
433} 442}
434 443
435static void gru_prefetch_context(void *gseg, void *cb, void *cbe, unsigned long cbrmap, 444static void gru_prefetch_context(void *gseg, void *cb, void *cbe,
436 unsigned long length) 445 unsigned long cbrmap, unsigned long length)
437{ 446{
438 int i, scr; 447 int i, scr;
439 448
@@ -500,12 +509,12 @@ void gru_unload_context(struct gru_thread_state *gts, int savestate)
500 zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE); 509 zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
501 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum); 510 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
502 511
512 gru_dbg(grudev, "gts %p\n", gts);
503 lock_cch_handle(cch); 513 lock_cch_handle(cch);
504 if (cch_interrupt_sync(cch)) 514 if (cch_interrupt_sync(cch))
505 BUG(); 515 BUG();
506 gru_dbg(grudev, "gts %p\n", gts);
507 516
508 gru_unload_mm_tracker(gru, gts->ts_gms, gts->ts_ctxnum); 517 gru_unload_mm_tracker(gru, gts);
509 if (savestate) 518 if (savestate)
510 gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, 519 gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr,
511 ctxnum, gts->ts_cbr_map, 520 ctxnum, gts->ts_cbr_map,
@@ -534,7 +543,7 @@ static void gru_load_context(struct gru_thread_state *gts)
534 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum); 543 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
535 544
536 lock_cch_handle(cch); 545 lock_cch_handle(cch);
537 asid = gru_load_mm_tracker(gru, gts->ts_gms, gts->ts_ctxnum); 546 asid = gru_load_mm_tracker(gru, gts);
538 cch->tfm_fault_bit_enable = 547 cch->tfm_fault_bit_enable =
539 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL 548 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
540 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR); 549 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
@@ -544,7 +553,8 @@ static void gru_load_context(struct gru_thread_state *gts)
544 cch->tlb_int_select = gts->ts_tlb_int_select; 553 cch->tlb_int_select = gts->ts_tlb_int_select;
545 } 554 }
546 cch->tfm_done_bit_enable = 0; 555 cch->tfm_done_bit_enable = 0;
547 err = cch_allocate(cch, asid, gts->ts_cbr_map, gts->ts_dsr_map); 556 err = cch_allocate(cch, asid, gts->ts_sizeavail, gts->ts_cbr_map,
557 gts->ts_dsr_map);
548 if (err) { 558 if (err) {
549 gru_dbg(grudev, 559 gru_dbg(grudev,
550 "err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n", 560 "err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n",
@@ -565,11 +575,12 @@ static void gru_load_context(struct gru_thread_state *gts)
565/* 575/*
566 * Update fields in an active CCH: 576 * Update fields in an active CCH:
567 * - retarget interrupts on local blade 577 * - retarget interrupts on local blade
578 * - update sizeavail mask
568 * - force a delayed context unload by clearing the CCH asids. This 579 * - force a delayed context unload by clearing the CCH asids. This
569 * forces TLB misses for new GRU instructions. The context is unloaded 580 * forces TLB misses for new GRU instructions. The context is unloaded
570 * when the next TLB miss occurs. 581 * when the next TLB miss occurs.
571 */ 582 */
572static int gru_update_cch(struct gru_thread_state *gts, int int_select) 583int gru_update_cch(struct gru_thread_state *gts, int force_unload)
573{ 584{
574 struct gru_context_configuration_handle *cch; 585 struct gru_context_configuration_handle *cch;
575 struct gru_state *gru = gts->ts_gru; 586 struct gru_state *gru = gts->ts_gru;
@@ -583,9 +594,11 @@ static int gru_update_cch(struct gru_thread_state *gts, int int_select)
583 goto exit; 594 goto exit;
584 if (cch_interrupt(cch)) 595 if (cch_interrupt(cch))
585 BUG(); 596 BUG();
586 if (int_select >= 0) { 597 if (!force_unload) {
587 gts->ts_tlb_int_select = int_select; 598 for (i = 0; i < 8; i++)
588 cch->tlb_int_select = int_select; 599 cch->sizeavail[i] = gts->ts_sizeavail;
600 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
601 cch->tlb_int_select = gru_cpu_fault_map_id();
589 } else { 602 } else {
590 for (i = 0; i < 8; i++) 603 for (i = 0; i < 8; i++)
591 cch->asid[i] = 0; 604 cch->asid[i] = 0;
@@ -617,7 +630,7 @@ static int gru_retarget_intr(struct gru_thread_state *gts)
617 630
618 gru_dbg(grudev, "retarget from %d to %d\n", gts->ts_tlb_int_select, 631 gru_dbg(grudev, "retarget from %d to %d\n", gts->ts_tlb_int_select,
619 gru_cpu_fault_map_id()); 632 gru_cpu_fault_map_id());
620 return gru_update_cch(gts, gru_cpu_fault_map_id()); 633 return gru_update_cch(gts, 0);
621} 634}
622 635
623 636
@@ -688,7 +701,7 @@ static void gru_steal_context(struct gru_thread_state *gts)
688 STAT(steal_context_failed); 701 STAT(steal_context_failed);
689 } 702 }
690 gru_dbg(grudev, 703 gru_dbg(grudev,
691 "stole gru %x, ctxnum %d from gts %p. Need cb %d, ds %d;" 704 "stole gid %d, ctxnum %d from gts %p. Need cb %d, ds %d;"
692 " avail cb %ld, ds %ld\n", 705 " avail cb %ld, ds %ld\n",
693 gru->gs_gid, ctxnum, ngts, cbr, dsr, hweight64(gru->gs_cbr_map), 706 gru->gs_gid, ctxnum, ngts, cbr, dsr, hweight64(gru->gs_cbr_map),
694 hweight64(gru->gs_dsr_map)); 707 hweight64(gru->gs_dsr_map));
@@ -727,6 +740,7 @@ again:
727 } 740 }
728 reserve_gru_resources(gru, gts); 741 reserve_gru_resources(gru, gts);
729 gts->ts_gru = gru; 742 gts->ts_gru = gru;
743 gts->ts_blade = gru->gs_blade_id;
730 gts->ts_ctxnum = 744 gts->ts_ctxnum =
731 find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH); 745 find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
732 BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH); 746 BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH);
@@ -737,7 +751,7 @@ again:
737 751
738 STAT(assign_context); 752 STAT(assign_context);
739 gru_dbg(grudev, 753 gru_dbg(grudev,
740 "gseg %p, gts %p, gru %x, ctx %d, cbr %d, dsr %d\n", 754 "gseg %p, gts %p, gid %d, ctx %d, cbr %d, dsr %d\n",
741 gseg_virtual_address(gts->ts_gru, gts->ts_ctxnum), gts, 755 gseg_virtual_address(gts->ts_gru, gts->ts_ctxnum), gts,
742 gts->ts_gru->gs_gid, gts->ts_ctxnum, 756 gts->ts_gru->gs_gid, gts->ts_ctxnum,
743 gts->ts_cbr_au_count, gts->ts_dsr_au_count); 757 gts->ts_cbr_au_count, gts->ts_dsr_au_count);
@@ -773,8 +787,8 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
773 return VM_FAULT_SIGBUS; 787 return VM_FAULT_SIGBUS;
774 788
775again: 789again:
776 preempt_disable();
777 mutex_lock(&gts->ts_ctxlock); 790 mutex_lock(&gts->ts_ctxlock);
791 preempt_disable();
778 if (gts->ts_gru) { 792 if (gts->ts_gru) {
779 if (gts->ts_gru->gs_blade_id != uv_numa_blade_id()) { 793 if (gts->ts_gru->gs_blade_id != uv_numa_blade_id()) {
780 STAT(migrated_nopfn_unload); 794 STAT(migrated_nopfn_unload);