aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/sgi-gru/gru_instructions.h20
-rw-r--r--drivers/misc/sgi-gru/grufault.c25
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h23
-rw-r--r--drivers/misc/sgi-gru/grumain.c3
-rw-r--r--drivers/misc/sgi-gru/gruprocfs.c5
-rw-r--r--drivers/misc/sgi-gru/grutables.h2
6 files changed, 52 insertions, 26 deletions
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h
index 3fde33c1e8f..2feb885ca96 100644
--- a/drivers/misc/sgi-gru/gru_instructions.h
+++ b/drivers/misc/sgi-gru/gru_instructions.h
@@ -81,6 +81,8 @@ struct control_block_extended_exc_detail {
81 int exopc; 81 int exopc;
82 long exceptdet0; 82 long exceptdet0;
83 int exceptdet1; 83 int exceptdet1;
84 int cbrstate;
85 int cbrexecstatus;
84}; 86};
85 87
86/* 88/*
@@ -107,7 +109,8 @@ struct gru_instruction_bits {
107 unsigned char reserved2: 2; 109 unsigned char reserved2: 2;
108 unsigned char istatus: 2; 110 unsigned char istatus: 2;
109 unsigned char isubstatus:4; 111 unsigned char isubstatus:4;
110 unsigned char reserved3: 2; 112 unsigned char reserved3: 1;
113 unsigned char tlb_fault_color: 1;
111 /* DW 1 */ 114 /* DW 1 */
112 unsigned long idef4; /* 42 bits: TRi1, BufSize */ 115 unsigned long idef4; /* 42 bits: TRi1, BufSize */
113 /* DW 2-6 */ 116 /* DW 2-6 */
@@ -253,6 +256,21 @@ struct gru_instruction {
253#define CBE_CAUSE_RESPONSE_DATA_ERROR (1 << 16) 256#define CBE_CAUSE_RESPONSE_DATA_ERROR (1 << 16)
254#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR (1 << 17) 257#define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR (1 << 17)
255 258
259/* CBE cbrexecstatus bits */
260#define CBR_EXS_ABORT_OCC_BIT 0
261#define CBR_EXS_INT_OCC_BIT 1
262#define CBR_EXS_PENDING_BIT 2
263#define CBR_EXS_QUEUED_BIT 3
264#define CBR_EXS_TLBHW_BIT 4
265#define CBR_EXS_EXCEPTION_BIT 5
266
267#define CBR_EXS_ABORT_OCC (1 << CBR_EXS_ABORT_OCC_BIT)
268#define CBR_EXS_INT_OCC (1 << CBR_EXS_INT_OCC_BIT)
269#define CBR_EXS_PENDING (1 << CBR_EXS_PENDING_BIT)
270#define CBR_EXS_QUEUED (1 << CBR_EXS_QUEUED_BIT)
271#define CBR_EXS_TLBHW (1 << CBR_EXS_TLBHW_BIT)
272#define CBR_EXS_EXCEPTION (1 << CBR_EXS_EXCEPTION_BIT)
273
256/* 274/*
257 * Exceptions are retried for the following cases. If any OTHER bits are set 275 * Exceptions are retried for the following cases. If any OTHER bits are set
258 * in ecause, the exception is not retryable. 276 * in ecause, the exception is not retryable.
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index ab118558552..4089f862aa2 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -334,6 +334,8 @@ static int gru_try_dropin(struct gru_thread_state *gts,
334 * Might be a hardware race OR a stupid user. Ignore FMM because FMM 334 * Might be a hardware race OR a stupid user. Ignore FMM because FMM
335 * is a transient state. 335 * is a transient state.
336 */ 336 */
337 if (tfh->status != TFHSTATUS_EXCEPTION)
338 goto failnoexception;
337 if (tfh->state == TFHSTATE_IDLE) 339 if (tfh->state == TFHSTATE_IDLE)
338 goto failidle; 340 goto failidle;
339 if (tfh->state == TFHSTATE_MISS_FMM && cb) 341 if (tfh->state == TFHSTATE_MISS_FMM && cb)
@@ -401,8 +403,17 @@ failfmm:
401 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state); 403 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state);
402 return 0; 404 return 0;
403 405
406failnoexception:
407 /* TFH status did not show exception pending */
408 gru_flush_cache(tfh);
409 if (cb)
410 gru_flush_cache(cb);
411 STAT(tlb_dropin_fail_no_exception);
412 gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state);
413 return 0;
414
404failidle: 415failidle:
405 /* TFH was idle - no miss pending */ 416 /* TFH state was idle - no miss pending */
406 gru_flush_cache(tfh); 417 gru_flush_cache(tfh);
407 if (cb) 418 if (cb)
408 gru_flush_cache(cb); 419 gru_flush_cache(cb);
@@ -472,7 +483,8 @@ irqreturn_t gru_intr(int irq, void *dev_id)
472 * This is running in interrupt context. Trylock the mmap_sem. 483 * This is running in interrupt context. Trylock the mmap_sem.
473 * If it fails, retry the fault in user context. 484 * If it fails, retry the fault in user context.
474 */ 485 */
475 if (down_read_trylock(&gts->ts_mm->mmap_sem)) { 486 if (!gts->ts_force_cch_reload &&
487 down_read_trylock(&gts->ts_mm->mmap_sem)) {
476 gru_try_dropin(gts, tfh, NULL); 488 gru_try_dropin(gts, tfh, NULL);
477 up_read(&gts->ts_mm->mmap_sem); 489 up_read(&gts->ts_mm->mmap_sem);
478 } else { 490 } else {
@@ -595,14 +607,19 @@ int gru_get_exception_detail(unsigned long arg)
595 excdet.ecause = cbe->ecause; 607 excdet.ecause = cbe->ecause;
596 excdet.exceptdet0 = cbe->idef1upd; 608 excdet.exceptdet0 = cbe->idef1upd;
597 excdet.exceptdet1 = cbe->idef3upd; 609 excdet.exceptdet1 = cbe->idef3upd;
610 excdet.cbrstate = cbe->cbrstate;
611 excdet.cbrexecstatus = cbe->cbrexecstatus;
598 ret = 0; 612 ret = 0;
599 } else { 613 } else {
600 ret = -EAGAIN; 614 ret = -EAGAIN;
601 } 615 }
602 gru_unlock_gts(gts); 616 gru_unlock_gts(gts);
603 617
604 gru_dbg(grudev, "address 0x%lx, ecause 0x%x\n", excdet.cb, 618 gru_dbg(grudev,
605 excdet.ecause); 619 "cb 0x%lx, op %d, exopc %d, cbrstate %d, cbrexecstatus 0x%x, ecause 0x%x, "
620 "exdet0 0x%lx, exdet1 0x%x\n",
621 excdet.cb, excdet.opc, excdet.exopc, excdet.cbrstate, excdet.cbrexecstatus,
622 excdet.ecause, excdet.exceptdet0, excdet.exceptdet1);
606 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet))) 623 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet)))
607 ret = -EFAULT; 624 ret = -EFAULT;
608 return ret; 625 return ret;
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index 1ed74d7508c..03b76a1993c 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -251,15 +251,14 @@ struct gru_tlb_fault_handle {
251 unsigned int fill1:9; 251 unsigned int fill1:9;
252 252
253 unsigned int status:2; 253 unsigned int status:2;
254 unsigned int fill2:1; 254 unsigned int fill2:2;
255 unsigned int color:1;
256 unsigned int state:3; 255 unsigned int state:3;
257 unsigned int fill3:1; 256 unsigned int fill3:1;
258 257
259 unsigned int cause:7; /* DW 0 - high 32 */ 258 unsigned int cause:7;
260 unsigned int fill4:1; 259 unsigned int fill4:1;
261 260
262 unsigned int indexway:12; 261 unsigned int indexway:12; /* DW 0 - high 32 */
263 unsigned int fill5:4; 262 unsigned int fill5:4;
264 263
265 unsigned int ctxnum:4; 264 unsigned int ctxnum:4;
@@ -457,21 +456,7 @@ enum gru_cbr_state {
457 CBRSTATE_BUSY_INTERRUPT, 456 CBRSTATE_BUSY_INTERRUPT,
458}; 457};
459 458
460/* CBE cbrexecstatus bits */ 459/* CBE cbrexecstatus bits - defined in gru_instructions.h*/
461#define CBR_EXS_ABORT_OCC_BIT 0
462#define CBR_EXS_INT_OCC_BIT 1
463#define CBR_EXS_PENDING_BIT 2
464#define CBR_EXS_QUEUED_BIT 3
465#define CBR_EXS_TLBHW_BIT 4
466#define CBR_EXS_EXCEPTION_BIT 5
467
468#define CBR_EXS_ABORT_OCC (1 << CBR_EXS_ABORT_OCC_BIT)
469#define CBR_EXS_INT_OCC (1 << CBR_EXS_INT_OCC_BIT)
470#define CBR_EXS_PENDING (1 << CBR_EXS_PENDING_BIT)
471#define CBR_EXS_QUEUED (1 << CBR_EXS_QUEUED_BIT)
472#define CBR_EXS_TLBHW (1 << CBR_EXS_TLBHW_BIT)
473#define CBR_EXS_EXCEPTION (1 << CBR_EXS_EXCEPTION_BIT)
474
475/* CBE ecause bits - defined in gru_instructions.h */ 460/* CBE ecause bits - defined in gru_instructions.h */
476 461
477/* 462/*
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index ec3f7a17d22..374af38862e 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -599,6 +599,9 @@ int gru_update_cch(struct gru_thread_state *gts, int force_unload)
599 cch->sizeavail[i] = gts->ts_sizeavail; 599 cch->sizeavail[i] = gts->ts_sizeavail;
600 gts->ts_tlb_int_select = gru_cpu_fault_map_id(); 600 gts->ts_tlb_int_select = gru_cpu_fault_map_id();
601 cch->tlb_int_select = gru_cpu_fault_map_id(); 601 cch->tlb_int_select = gru_cpu_fault_map_id();
602 cch->tfm_fault_bit_enable =
603 (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
604 || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
602 } else { 605 } else {
603 for (i = 0; i < 8; i++) 606 for (i = 0; i < 8; i++)
604 cch->asid[i] = 0; 607 cch->asid[i] = 0;
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index ee74821b171..c46c1c5f0c7 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -84,6 +84,8 @@ static int statistics_show(struct seq_file *s, void *p)
84 printstat(s, tlb_dropin_fail_range_active); 84 printstat(s, tlb_dropin_fail_range_active);
85 printstat(s, tlb_dropin_fail_idle); 85 printstat(s, tlb_dropin_fail_idle);
86 printstat(s, tlb_dropin_fail_fmm); 86 printstat(s, tlb_dropin_fail_fmm);
87 printstat(s, tlb_dropin_fail_no_exception);
88 printstat(s, tlb_dropin_fail_no_exception_war);
87 printstat(s, mmu_invalidate_range); 89 printstat(s, mmu_invalidate_range);
88 printstat(s, mmu_invalidate_page); 90 printstat(s, mmu_invalidate_page);
89 printstat(s, mmu_clear_flush_young); 91 printstat(s, mmu_clear_flush_young);
@@ -158,8 +160,7 @@ static ssize_t options_write(struct file *file, const char __user *userbuf,
158 unsigned long val; 160 unsigned long val;
159 char buf[80]; 161 char buf[80];
160 162
161 if (copy_from_user 163 if (strncpy_from_user(buf, userbuf, sizeof(buf) - 1) < 0)
162 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf)))
163 return -EFAULT; 164 return -EFAULT;
164 buf[count - 1] = '\0'; 165 buf[count - 1] = '\0';
165 if (!strict_strtoul(buf, 10, &val)) 166 if (!strict_strtoul(buf, 10, &val))
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index bf1eeb7553e..ebf6183c163 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -207,6 +207,8 @@ struct gru_stats_s {
207 atomic_long_t tlb_dropin_fail_range_active; 207 atomic_long_t tlb_dropin_fail_range_active;
208 atomic_long_t tlb_dropin_fail_idle; 208 atomic_long_t tlb_dropin_fail_idle;
209 atomic_long_t tlb_dropin_fail_fmm; 209 atomic_long_t tlb_dropin_fail_fmm;
210 atomic_long_t tlb_dropin_fail_no_exception;
211 atomic_long_t tlb_dropin_fail_no_exception_war;
210 atomic_long_t mmu_invalidate_range; 212 atomic_long_t mmu_invalidate_range;
211 atomic_long_t mmu_invalidate_page; 213 atomic_long_t mmu_invalidate_page;
212 atomic_long_t mmu_clear_flush_young; 214 atomic_long_t mmu_clear_flush_young;