0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/mm.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/sched.h>
0015 #include <linux/device.h>
0016 #include <linux/list.h>
0017 #include <linux/err.h>
0018 #include <linux/prefetch.h>
0019 #include <asm/uv/uv_hub.h>
0020 #include "gru.h"
0021 #include "grutables.h"
0022 #include "gruhandles.h"
0023
0024 unsigned long gru_options __read_mostly;
0025
0026 static struct device_driver gru_driver = {
0027 .name = "gru"
0028 };
0029
0030 static struct device gru_device = {
0031 .init_name = "",
0032 .driver = &gru_driver,
0033 };
0034
0035 struct device *grudev = &gru_device;
0036
0037
0038
0039
0040
0041
0042 int gru_cpu_fault_map_id(void)
0043 {
0044 #ifdef CONFIG_IA64
0045 return uv_blade_processor_id() % GRU_NUM_TFM;
0046 #else
0047 int cpu = smp_processor_id();
0048 int id, core;
0049
0050 core = uv_cpu_core_number(cpu);
0051 id = core + UV_MAX_INT_CORES * uv_cpu_socket_number(cpu);
0052 return id;
0053 #endif
0054 }
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 static int gru_wrap_asid(struct gru_state *gru)
0085 {
0086 gru_dbg(grudev, "gid %d\n", gru->gs_gid);
0087 STAT(asid_wrap);
0088 gru->gs_asid_gen++;
0089 return MIN_ASID;
0090 }
0091
0092
0093 static int gru_reset_asid_limit(struct gru_state *gru, int asid)
0094 {
0095 int i, gid, inuse_asid, limit;
0096
0097 gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid);
0098 STAT(asid_next);
0099 limit = MAX_ASID;
0100 if (asid >= limit)
0101 asid = gru_wrap_asid(gru);
0102 gru_flush_all_tlb(gru);
0103 gid = gru->gs_gid;
0104 again:
0105 for (i = 0; i < GRU_NUM_CCH; i++) {
0106 if (!gru->gs_gts[i] || is_kernel_context(gru->gs_gts[i]))
0107 continue;
0108 inuse_asid = gru->gs_gts[i]->ts_gms->ms_asids[gid].mt_asid;
0109 gru_dbg(grudev, "gid %d, gts %p, gms %p, inuse 0x%x, cxt %d\n",
0110 gru->gs_gid, gru->gs_gts[i], gru->gs_gts[i]->ts_gms,
0111 inuse_asid, i);
0112 if (inuse_asid == asid) {
0113 asid += ASID_INC;
0114 if (asid >= limit) {
0115
0116
0117
0118
0119 limit = MAX_ASID;
0120 if (asid >= MAX_ASID)
0121 asid = gru_wrap_asid(gru);
0122 goto again;
0123 }
0124 }
0125
0126 if ((inuse_asid > asid) && (inuse_asid < limit))
0127 limit = inuse_asid;
0128 }
0129 gru->gs_asid_limit = limit;
0130 gru->gs_asid = asid;
0131 gru_dbg(grudev, "gid %d, new asid 0x%x, new_limit 0x%x\n", gru->gs_gid,
0132 asid, limit);
0133 return asid;
0134 }
0135
0136
0137 static int gru_assign_asid(struct gru_state *gru)
0138 {
0139 int asid;
0140
0141 gru->gs_asid += ASID_INC;
0142 asid = gru->gs_asid;
0143 if (asid >= gru->gs_asid_limit)
0144 asid = gru_reset_asid_limit(gru, asid);
0145
0146 gru_dbg(grudev, "gid %d, asid 0x%x\n", gru->gs_gid, asid);
0147 return asid;
0148 }
0149
0150
0151
0152
0153
0154 static unsigned long reserve_resources(unsigned long *p, int n, int mmax,
0155 char *idx)
0156 {
0157 unsigned long bits = 0;
0158 int i;
0159
0160 while (n--) {
0161 i = find_first_bit(p, mmax);
0162 if (i == mmax)
0163 BUG();
0164 __clear_bit(i, p);
0165 __set_bit(i, &bits);
0166 if (idx)
0167 *idx++ = i;
0168 }
0169 return bits;
0170 }
0171
0172 unsigned long gru_reserve_cb_resources(struct gru_state *gru, int cbr_au_count,
0173 char *cbmap)
0174 {
0175 return reserve_resources(&gru->gs_cbr_map, cbr_au_count, GRU_CBR_AU,
0176 cbmap);
0177 }
0178
0179 unsigned long gru_reserve_ds_resources(struct gru_state *gru, int dsr_au_count,
0180 char *dsmap)
0181 {
0182 return reserve_resources(&gru->gs_dsr_map, dsr_au_count, GRU_DSR_AU,
0183 dsmap);
0184 }
0185
0186 static void reserve_gru_resources(struct gru_state *gru,
0187 struct gru_thread_state *gts)
0188 {
0189 gru->gs_active_contexts++;
0190 gts->ts_cbr_map =
0191 gru_reserve_cb_resources(gru, gts->ts_cbr_au_count,
0192 gts->ts_cbr_idx);
0193 gts->ts_dsr_map =
0194 gru_reserve_ds_resources(gru, gts->ts_dsr_au_count, NULL);
0195 }
0196
0197 static void free_gru_resources(struct gru_state *gru,
0198 struct gru_thread_state *gts)
0199 {
0200 gru->gs_active_contexts--;
0201 gru->gs_cbr_map |= gts->ts_cbr_map;
0202 gru->gs_dsr_map |= gts->ts_dsr_map;
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 static int check_gru_resources(struct gru_state *gru, int cbr_au_count,
0213 int dsr_au_count, int max_active_contexts)
0214 {
0215 return hweight64(gru->gs_cbr_map) >= cbr_au_count
0216 && hweight64(gru->gs_dsr_map) >= dsr_au_count
0217 && gru->gs_active_contexts < max_active_contexts;
0218 }
0219
0220
0221
0222
0223
0224 static int gru_load_mm_tracker(struct gru_state *gru,
0225 struct gru_thread_state *gts)
0226 {
0227 struct gru_mm_struct *gms = gts->ts_gms;
0228 struct gru_mm_tracker *asids = &gms->ms_asids[gru->gs_gid];
0229 unsigned short ctxbitmap = (1 << gts->ts_ctxnum);
0230 int asid;
0231
0232 spin_lock(&gms->ms_asid_lock);
0233 asid = asids->mt_asid;
0234
0235 spin_lock(&gru->gs_asid_lock);
0236 if (asid == 0 || (asids->mt_ctxbitmap == 0 && asids->mt_asid_gen !=
0237 gru->gs_asid_gen)) {
0238 asid = gru_assign_asid(gru);
0239 asids->mt_asid = asid;
0240 asids->mt_asid_gen = gru->gs_asid_gen;
0241 STAT(asid_new);
0242 } else {
0243 STAT(asid_reuse);
0244 }
0245 spin_unlock(&gru->gs_asid_lock);
0246
0247 BUG_ON(asids->mt_ctxbitmap & ctxbitmap);
0248 asids->mt_ctxbitmap |= ctxbitmap;
0249 if (!test_bit(gru->gs_gid, gms->ms_asidmap))
0250 __set_bit(gru->gs_gid, gms->ms_asidmap);
0251 spin_unlock(&gms->ms_asid_lock);
0252
0253 gru_dbg(grudev,
0254 "gid %d, gts %p, gms %p, ctxnum %d, asid 0x%x, asidmap 0x%lx\n",
0255 gru->gs_gid, gts, gms, gts->ts_ctxnum, asid,
0256 gms->ms_asidmap[0]);
0257 return asid;
0258 }
0259
0260 static void gru_unload_mm_tracker(struct gru_state *gru,
0261 struct gru_thread_state *gts)
0262 {
0263 struct gru_mm_struct *gms = gts->ts_gms;
0264 struct gru_mm_tracker *asids;
0265 unsigned short ctxbitmap;
0266
0267 asids = &gms->ms_asids[gru->gs_gid];
0268 ctxbitmap = (1 << gts->ts_ctxnum);
0269 spin_lock(&gms->ms_asid_lock);
0270 spin_lock(&gru->gs_asid_lock);
0271 BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap);
0272 asids->mt_ctxbitmap ^= ctxbitmap;
0273 gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum %d, asidmap 0x%lx\n",
0274 gru->gs_gid, gts, gms, gts->ts_ctxnum, gms->ms_asidmap[0]);
0275 spin_unlock(&gru->gs_asid_lock);
0276 spin_unlock(&gms->ms_asid_lock);
0277 }
0278
0279
0280
0281
0282
0283 void gts_drop(struct gru_thread_state *gts)
0284 {
0285 if (gts && refcount_dec_and_test(>s->ts_refcnt)) {
0286 if (gts->ts_gms)
0287 gru_drop_mmu_notifier(gts->ts_gms);
0288 kfree(gts);
0289 STAT(gts_free);
0290 }
0291 }
0292
0293
0294
0295
0296 static struct gru_thread_state *gru_find_current_gts_nolock(struct gru_vma_data
0297 *vdata, int tsid)
0298 {
0299 struct gru_thread_state *gts;
0300
0301 list_for_each_entry(gts, &vdata->vd_head, ts_next)
0302 if (gts->ts_tsid == tsid)
0303 return gts;
0304 return NULL;
0305 }
0306
0307
0308
0309
0310 struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
0311 int cbr_au_count, int dsr_au_count,
0312 unsigned char tlb_preload_count, int options, int tsid)
0313 {
0314 struct gru_thread_state *gts;
0315 struct gru_mm_struct *gms;
0316 int bytes;
0317
0318 bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count);
0319 bytes += sizeof(struct gru_thread_state);
0320 gts = kmalloc(bytes, GFP_KERNEL);
0321 if (!gts)
0322 return ERR_PTR(-ENOMEM);
0323
0324 STAT(gts_alloc);
0325 memset(gts, 0, sizeof(struct gru_thread_state));
0326 refcount_set(>s->ts_refcnt, 1);
0327 mutex_init(>s->ts_ctxlock);
0328 gts->ts_cbr_au_count = cbr_au_count;
0329 gts->ts_dsr_au_count = dsr_au_count;
0330 gts->ts_tlb_preload_count = tlb_preload_count;
0331 gts->ts_user_options = options;
0332 gts->ts_user_blade_id = -1;
0333 gts->ts_user_chiplet_id = -1;
0334 gts->ts_tsid = tsid;
0335 gts->ts_ctxnum = NULLCTX;
0336 gts->ts_tlb_int_select = -1;
0337 gts->ts_cch_req_slice = -1;
0338 gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT);
0339 if (vma) {
0340 gts->ts_mm = current->mm;
0341 gts->ts_vma = vma;
0342 gms = gru_register_mmu_notifier();
0343 if (IS_ERR(gms))
0344 goto err;
0345 gts->ts_gms = gms;
0346 }
0347
0348 gru_dbg(grudev, "alloc gts %p\n", gts);
0349 return gts;
0350
0351 err:
0352 gts_drop(gts);
0353 return ERR_CAST(gms);
0354 }
0355
0356
0357
0358
0359 struct gru_vma_data *gru_alloc_vma_data(struct vm_area_struct *vma, int tsid)
0360 {
0361 struct gru_vma_data *vdata = NULL;
0362
0363 vdata = kmalloc(sizeof(*vdata), GFP_KERNEL);
0364 if (!vdata)
0365 return NULL;
0366
0367 STAT(vdata_alloc);
0368 INIT_LIST_HEAD(&vdata->vd_head);
0369 spin_lock_init(&vdata->vd_lock);
0370 gru_dbg(grudev, "alloc vdata %p\n", vdata);
0371 return vdata;
0372 }
0373
0374
0375
0376
0377 struct gru_thread_state *gru_find_thread_state(struct vm_area_struct *vma,
0378 int tsid)
0379 {
0380 struct gru_vma_data *vdata = vma->vm_private_data;
0381 struct gru_thread_state *gts;
0382
0383 spin_lock(&vdata->vd_lock);
0384 gts = gru_find_current_gts_nolock(vdata, tsid);
0385 spin_unlock(&vdata->vd_lock);
0386 gru_dbg(grudev, "vma %p, gts %p\n", vma, gts);
0387 return gts;
0388 }
0389
0390
0391
0392
0393
0394 struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct *vma,
0395 int tsid)
0396 {
0397 struct gru_vma_data *vdata = vma->vm_private_data;
0398 struct gru_thread_state *gts, *ngts;
0399
0400 gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count,
0401 vdata->vd_dsr_au_count,
0402 vdata->vd_tlb_preload_count,
0403 vdata->vd_user_options, tsid);
0404 if (IS_ERR(gts))
0405 return gts;
0406
0407 spin_lock(&vdata->vd_lock);
0408 ngts = gru_find_current_gts_nolock(vdata, tsid);
0409 if (ngts) {
0410 gts_drop(gts);
0411 gts = ngts;
0412 STAT(gts_double_allocate);
0413 } else {
0414 list_add(>s->ts_next, &vdata->vd_head);
0415 }
0416 spin_unlock(&vdata->vd_lock);
0417 gru_dbg(grudev, "vma %p, gts %p\n", vma, gts);
0418 return gts;
0419 }
0420
0421
0422
0423
0424 static void gru_free_gru_context(struct gru_thread_state *gts)
0425 {
0426 struct gru_state *gru;
0427
0428 gru = gts->ts_gru;
0429 gru_dbg(grudev, "gts %p, gid %d\n", gts, gru->gs_gid);
0430
0431 spin_lock(&gru->gs_lock);
0432 gru->gs_gts[gts->ts_ctxnum] = NULL;
0433 free_gru_resources(gru, gts);
0434 BUG_ON(test_bit(gts->ts_ctxnum, &gru->gs_context_map) == 0);
0435 __clear_bit(gts->ts_ctxnum, &gru->gs_context_map);
0436 gts->ts_ctxnum = NULLCTX;
0437 gts->ts_gru = NULL;
0438 gts->ts_blade = -1;
0439 spin_unlock(&gru->gs_lock);
0440
0441 gts_drop(gts);
0442 STAT(free_context);
0443 }
0444
0445
0446
0447
0448
0449 static void prefetch_data(void *p, int num, int stride)
0450 {
0451 while (num-- > 0) {
0452 prefetchw(p);
0453 p += stride;
0454 }
0455 }
0456
0457 static inline long gru_copy_handle(void *d, void *s)
0458 {
0459 memcpy(d, s, GRU_HANDLE_BYTES);
0460 return GRU_HANDLE_BYTES;
0461 }
0462
0463 static void gru_prefetch_context(void *gseg, void *cb, void *cbe,
0464 unsigned long cbrmap, unsigned long length)
0465 {
0466 int i, scr;
0467
0468 prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES,
0469 GRU_CACHE_LINE_BYTES);
0470
0471 for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
0472 prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES);
0473 prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1,
0474 GRU_CACHE_LINE_BYTES);
0475 cb += GRU_HANDLE_STRIDE;
0476 }
0477 }
0478
0479 static void gru_load_context_data(void *save, void *grubase, int ctxnum,
0480 unsigned long cbrmap, unsigned long dsrmap,
0481 int data_valid)
0482 {
0483 void *gseg, *cb, *cbe;
0484 unsigned long length;
0485 int i, scr;
0486
0487 gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
0488 cb = gseg + GRU_CB_BASE;
0489 cbe = grubase + GRU_CBE_BASE;
0490 length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
0491 gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
0492
0493 for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
0494 if (data_valid) {
0495 save += gru_copy_handle(cb, save);
0496 save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE,
0497 save);
0498 } else {
0499 memset(cb, 0, GRU_CACHE_LINE_BYTES);
0500 memset(cbe + i * GRU_HANDLE_STRIDE, 0,
0501 GRU_CACHE_LINE_BYTES);
0502 }
0503
0504 mb();
0505 gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE);
0506 cb += GRU_HANDLE_STRIDE;
0507 }
0508
0509 if (data_valid)
0510 memcpy(gseg + GRU_DS_BASE, save, length);
0511 else
0512 memset(gseg + GRU_DS_BASE, 0, length);
0513 }
0514
0515 static void gru_unload_context_data(void *save, void *grubase, int ctxnum,
0516 unsigned long cbrmap, unsigned long dsrmap)
0517 {
0518 void *gseg, *cb, *cbe;
0519 unsigned long length;
0520 int i, scr;
0521
0522 gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
0523 cb = gseg + GRU_CB_BASE;
0524 cbe = grubase + GRU_CBE_BASE;
0525 length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
0526
0527
0528 for_each_cbr_in_allocation_map(i, &cbrmap, scr)
0529 gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE);
0530 mb();
0531
0532 gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
0533
0534 for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
0535 save += gru_copy_handle(save, cb);
0536 save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE);
0537 cb += GRU_HANDLE_STRIDE;
0538 }
0539 memcpy(save, gseg + GRU_DS_BASE, length);
0540 }
0541
0542 void gru_unload_context(struct gru_thread_state *gts, int savestate)
0543 {
0544 struct gru_state *gru = gts->ts_gru;
0545 struct gru_context_configuration_handle *cch;
0546 int ctxnum = gts->ts_ctxnum;
0547
0548 if (!is_kernel_context(gts))
0549 zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
0550 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
0551
0552 gru_dbg(grudev, "gts %p, cbrmap 0x%lx, dsrmap 0x%lx\n",
0553 gts, gts->ts_cbr_map, gts->ts_dsr_map);
0554 lock_cch_handle(cch);
0555 if (cch_interrupt_sync(cch))
0556 BUG();
0557
0558 if (!is_kernel_context(gts))
0559 gru_unload_mm_tracker(gru, gts);
0560 if (savestate) {
0561 gru_unload_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr,
0562 ctxnum, gts->ts_cbr_map,
0563 gts->ts_dsr_map);
0564 gts->ts_data_valid = 1;
0565 }
0566
0567 if (cch_deallocate(cch))
0568 BUG();
0569 unlock_cch_handle(cch);
0570
0571 gru_free_gru_context(gts);
0572 }
0573
0574
0575
0576
0577
0578 void gru_load_context(struct gru_thread_state *gts)
0579 {
0580 struct gru_state *gru = gts->ts_gru;
0581 struct gru_context_configuration_handle *cch;
0582 int i, err, asid, ctxnum = gts->ts_ctxnum;
0583
0584 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
0585 lock_cch_handle(cch);
0586 cch->tfm_fault_bit_enable =
0587 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
0588 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
0589 cch->tlb_int_enable = (gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
0590 if (cch->tlb_int_enable) {
0591 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
0592 cch->tlb_int_select = gts->ts_tlb_int_select;
0593 }
0594 if (gts->ts_cch_req_slice >= 0) {
0595 cch->req_slice_set_enable = 1;
0596 cch->req_slice = gts->ts_cch_req_slice;
0597 } else {
0598 cch->req_slice_set_enable =0;
0599 }
0600 cch->tfm_done_bit_enable = 0;
0601 cch->dsr_allocation_map = gts->ts_dsr_map;
0602 cch->cbr_allocation_map = gts->ts_cbr_map;
0603
0604 if (is_kernel_context(gts)) {
0605 cch->unmap_enable = 1;
0606 cch->tfm_done_bit_enable = 1;
0607 cch->cb_int_enable = 1;
0608 cch->tlb_int_select = 0;
0609 } else {
0610 cch->unmap_enable = 0;
0611 cch->tfm_done_bit_enable = 0;
0612 cch->cb_int_enable = 0;
0613 asid = gru_load_mm_tracker(gru, gts);
0614 for (i = 0; i < 8; i++) {
0615 cch->asid[i] = asid + i;
0616 cch->sizeavail[i] = gts->ts_sizeavail;
0617 }
0618 }
0619
0620 err = cch_allocate(cch);
0621 if (err) {
0622 gru_dbg(grudev,
0623 "err %d: cch %p, gts %p, cbr 0x%lx, dsr 0x%lx\n",
0624 err, cch, gts, gts->ts_cbr_map, gts->ts_dsr_map);
0625 BUG();
0626 }
0627
0628 gru_load_context_data(gts->ts_gdata, gru->gs_gru_base_vaddr, ctxnum,
0629 gts->ts_cbr_map, gts->ts_dsr_map, gts->ts_data_valid);
0630
0631 if (cch_start(cch))
0632 BUG();
0633 unlock_cch_handle(cch);
0634
0635 gru_dbg(grudev, "gid %d, gts %p, cbrmap 0x%lx, dsrmap 0x%lx, tie %d, tis %d\n",
0636 gts->ts_gru->gs_gid, gts, gts->ts_cbr_map, gts->ts_dsr_map,
0637 (gts->ts_user_options == GRU_OPT_MISS_FMM_INTR), gts->ts_tlb_int_select);
0638 }
0639
0640
0641
0642
0643
0644
0645 int gru_update_cch(struct gru_thread_state *gts)
0646 {
0647 struct gru_context_configuration_handle *cch;
0648 struct gru_state *gru = gts->ts_gru;
0649 int i, ctxnum = gts->ts_ctxnum, ret = 0;
0650
0651 cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
0652
0653 lock_cch_handle(cch);
0654 if (cch->state == CCHSTATE_ACTIVE) {
0655 if (gru->gs_gts[gts->ts_ctxnum] != gts)
0656 goto exit;
0657 if (cch_interrupt(cch))
0658 BUG();
0659 for (i = 0; i < 8; i++)
0660 cch->sizeavail[i] = gts->ts_sizeavail;
0661 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
0662 cch->tlb_int_select = gru_cpu_fault_map_id();
0663 cch->tfm_fault_bit_enable =
0664 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
0665 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
0666 if (cch_start(cch))
0667 BUG();
0668 ret = 1;
0669 }
0670 exit:
0671 unlock_cch_handle(cch);
0672 return ret;
0673 }
0674
0675
0676
0677
0678
0679
0680
0681
0682 static int gru_retarget_intr(struct gru_thread_state *gts)
0683 {
0684 if (gts->ts_tlb_int_select < 0
0685 || gts->ts_tlb_int_select == gru_cpu_fault_map_id())
0686 return 0;
0687
0688 gru_dbg(grudev, "retarget from %d to %d\n", gts->ts_tlb_int_select,
0689 gru_cpu_fault_map_id());
0690 return gru_update_cch(gts);
0691 }
0692
0693
0694
0695
0696
0697
0698
0699 static int gru_check_chiplet_assignment(struct gru_state *gru,
0700 struct gru_thread_state *gts)
0701 {
0702 int blade_id;
0703 int chiplet_id;
0704
0705 blade_id = gts->ts_user_blade_id;
0706 if (blade_id < 0)
0707 blade_id = uv_numa_blade_id();
0708
0709 chiplet_id = gts->ts_user_chiplet_id;
0710 return gru->gs_blade_id == blade_id &&
0711 (chiplet_id < 0 || chiplet_id == gru->gs_chiplet_id);
0712 }
0713
0714
0715
0716
0717
0718
0719 void gru_check_context_placement(struct gru_thread_state *gts)
0720 {
0721 struct gru_state *gru;
0722
0723
0724
0725
0726
0727
0728 gru = gts->ts_gru;
0729 if (!gru || gts->ts_tgid_owner != current->tgid)
0730 return;
0731
0732 if (!gru_check_chiplet_assignment(gru, gts)) {
0733 STAT(check_context_unload);
0734 gru_unload_context(gts, 1);
0735 } else if (gru_retarget_intr(gts)) {
0736 STAT(check_context_retarget_intr);
0737 }
0738 }
0739
0740
0741
0742
0743
0744
0745 #define next_ctxnum(n) ((n) < GRU_NUM_CCH - 2 ? (n) + 1 : 0)
0746 #define next_gru(b, g) (((g) < &(b)->bs_grus[GRU_CHIPLETS_PER_BLADE - 1]) ? \
0747 ((g)+1) : &(b)->bs_grus[0])
0748
0749 static int is_gts_stealable(struct gru_thread_state *gts,
0750 struct gru_blade_state *bs)
0751 {
0752 if (is_kernel_context(gts))
0753 return down_write_trylock(&bs->bs_kgts_sema);
0754 else
0755 return mutex_trylock(>s->ts_ctxlock);
0756 }
0757
0758 static void gts_stolen(struct gru_thread_state *gts,
0759 struct gru_blade_state *bs)
0760 {
0761 if (is_kernel_context(gts)) {
0762 up_write(&bs->bs_kgts_sema);
0763 STAT(steal_kernel_context);
0764 } else {
0765 mutex_unlock(>s->ts_ctxlock);
0766 STAT(steal_user_context);
0767 }
0768 }
0769
0770 void gru_steal_context(struct gru_thread_state *gts)
0771 {
0772 struct gru_blade_state *blade;
0773 struct gru_state *gru, *gru0;
0774 struct gru_thread_state *ngts = NULL;
0775 int ctxnum, ctxnum0, flag = 0, cbr, dsr;
0776 int blade_id;
0777
0778 blade_id = gts->ts_user_blade_id;
0779 if (blade_id < 0)
0780 blade_id = uv_numa_blade_id();
0781 cbr = gts->ts_cbr_au_count;
0782 dsr = gts->ts_dsr_au_count;
0783
0784 blade = gru_base[blade_id];
0785 spin_lock(&blade->bs_lock);
0786
0787 ctxnum = next_ctxnum(blade->bs_lru_ctxnum);
0788 gru = blade->bs_lru_gru;
0789 if (ctxnum == 0)
0790 gru = next_gru(blade, gru);
0791 blade->bs_lru_gru = gru;
0792 blade->bs_lru_ctxnum = ctxnum;
0793 ctxnum0 = ctxnum;
0794 gru0 = gru;
0795 while (1) {
0796 if (gru_check_chiplet_assignment(gru, gts)) {
0797 if (check_gru_resources(gru, cbr, dsr, GRU_NUM_CCH))
0798 break;
0799 spin_lock(&gru->gs_lock);
0800 for (; ctxnum < GRU_NUM_CCH; ctxnum++) {
0801 if (flag && gru == gru0 && ctxnum == ctxnum0)
0802 break;
0803 ngts = gru->gs_gts[ctxnum];
0804
0805
0806
0807
0808
0809
0810 if (ngts && is_gts_stealable(ngts, blade))
0811 break;
0812 ngts = NULL;
0813 }
0814 spin_unlock(&gru->gs_lock);
0815 if (ngts || (flag && gru == gru0 && ctxnum == ctxnum0))
0816 break;
0817 }
0818 if (flag && gru == gru0)
0819 break;
0820 flag = 1;
0821 ctxnum = 0;
0822 gru = next_gru(blade, gru);
0823 }
0824 spin_unlock(&blade->bs_lock);
0825
0826 if (ngts) {
0827 gts->ustats.context_stolen++;
0828 ngts->ts_steal_jiffies = jiffies;
0829 gru_unload_context(ngts, is_kernel_context(ngts) ? 0 : 1);
0830 gts_stolen(ngts, blade);
0831 } else {
0832 STAT(steal_context_failed);
0833 }
0834 gru_dbg(grudev,
0835 "stole gid %d, ctxnum %d from gts %p. Need cb %d, ds %d;"
0836 " avail cb %ld, ds %ld\n",
0837 gru->gs_gid, ctxnum, ngts, cbr, dsr, hweight64(gru->gs_cbr_map),
0838 hweight64(gru->gs_dsr_map));
0839 }
0840
0841
0842
0843
0844 static int gru_assign_context_number(struct gru_state *gru)
0845 {
0846 int ctxnum;
0847
0848 ctxnum = find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
0849 __set_bit(ctxnum, &gru->gs_context_map);
0850 return ctxnum;
0851 }
0852
0853
0854
0855
0856 struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts)
0857 {
0858 struct gru_state *gru, *grux;
0859 int i, max_active_contexts;
0860 int blade_id = gts->ts_user_blade_id;
0861
0862 if (blade_id < 0)
0863 blade_id = uv_numa_blade_id();
0864 again:
0865 gru = NULL;
0866 max_active_contexts = GRU_NUM_CCH;
0867 for_each_gru_on_blade(grux, blade_id, i) {
0868 if (!gru_check_chiplet_assignment(grux, gts))
0869 continue;
0870 if (check_gru_resources(grux, gts->ts_cbr_au_count,
0871 gts->ts_dsr_au_count,
0872 max_active_contexts)) {
0873 gru = grux;
0874 max_active_contexts = grux->gs_active_contexts;
0875 if (max_active_contexts == 0)
0876 break;
0877 }
0878 }
0879
0880 if (gru) {
0881 spin_lock(&gru->gs_lock);
0882 if (!check_gru_resources(gru, gts->ts_cbr_au_count,
0883 gts->ts_dsr_au_count, GRU_NUM_CCH)) {
0884 spin_unlock(&gru->gs_lock);
0885 goto again;
0886 }
0887 reserve_gru_resources(gru, gts);
0888 gts->ts_gru = gru;
0889 gts->ts_blade = gru->gs_blade_id;
0890 gts->ts_ctxnum = gru_assign_context_number(gru);
0891 refcount_inc(>s->ts_refcnt);
0892 gru->gs_gts[gts->ts_ctxnum] = gts;
0893 spin_unlock(&gru->gs_lock);
0894
0895 STAT(assign_context);
0896 gru_dbg(grudev,
0897 "gseg %p, gts %p, gid %d, ctx %d, cbr %d, dsr %d\n",
0898 gseg_virtual_address(gts->ts_gru, gts->ts_ctxnum), gts,
0899 gts->ts_gru->gs_gid, gts->ts_ctxnum,
0900 gts->ts_cbr_au_count, gts->ts_dsr_au_count);
0901 } else {
0902 gru_dbg(grudev, "failed to allocate a GTS %s\n", "");
0903 STAT(assign_context_failed);
0904 }
0905
0906 return gru;
0907 }
0908
0909
0910
0911
0912
0913
0914
0915
0916 vm_fault_t gru_fault(struct vm_fault *vmf)
0917 {
0918 struct vm_area_struct *vma = vmf->vma;
0919 struct gru_thread_state *gts;
0920 unsigned long paddr, vaddr;
0921 unsigned long expires;
0922
0923 vaddr = vmf->address;
0924 gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
0925 vma, vaddr, GSEG_BASE(vaddr));
0926 STAT(nopfn);
0927
0928
0929 gts = gru_find_thread_state(vma, TSID(vaddr, vma));
0930 if (!gts)
0931 return VM_FAULT_SIGBUS;
0932
0933 again:
0934 mutex_lock(>s->ts_ctxlock);
0935 preempt_disable();
0936
0937 gru_check_context_placement(gts);
0938
0939 if (!gts->ts_gru) {
0940 STAT(load_user_context);
0941 if (!gru_assign_gru_context(gts)) {
0942 preempt_enable();
0943 mutex_unlock(>s->ts_ctxlock);
0944 set_current_state(TASK_INTERRUPTIBLE);
0945 schedule_timeout(GRU_ASSIGN_DELAY);
0946 expires = gts->ts_steal_jiffies + GRU_STEAL_DELAY;
0947 if (time_before(expires, jiffies))
0948 gru_steal_context(gts);
0949 goto again;
0950 }
0951 gru_load_context(gts);
0952 paddr = gseg_physical_address(gts->ts_gru, gts->ts_ctxnum);
0953 remap_pfn_range(vma, vaddr & ~(GRU_GSEG_PAGESIZE - 1),
0954 paddr >> PAGE_SHIFT, GRU_GSEG_PAGESIZE,
0955 vma->vm_page_prot);
0956 }
0957
0958 preempt_enable();
0959 mutex_unlock(>s->ts_ctxlock);
0960
0961 return VM_FAULT_NOPAGE;
0962 }
0963