diff options
-rw-r--r-- | drivers/misc/sgi-gru/gru_instructions.h | 20 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 25 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.h | 23 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 3 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruprocfs.c | 5 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 2 |
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 | ||
406 | failnoexception: | ||
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 | |||
404 | failidle: | 415 | failidle: |
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(>s->ts_mm->mmap_sem)) { | 486 | if (!gts->ts_force_cch_reload && |
487 | down_read_trylock(>s->ts_mm->mmap_sem)) { | ||
476 | gru_try_dropin(gts, tfh, NULL); | 488 | gru_try_dropin(gts, tfh, NULL); |
477 | up_read(>s->ts_mm->mmap_sem); | 489 | up_read(>s->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; |