aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-04-02 19:59:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:05:07 -0400
commit7b8274e93fbabc7534aa51f95551c30aecdd0066 (patch)
treef1cfc0e87b07a4094ee06d2dc73673635b4b1775 /drivers/misc
parent27ca8a7b2bdfb3e22e67fbd5df58e6b6f0bbcd48 (diff)
sgi-gru: support multiple pagesizes in GRU
Add multiple pagesize support to the GRU driver. Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sgi-gru/grufault.c15
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c34
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h2
-rw-r--r--drivers/misc/sgi-gru/grukservices.c2
-rw-r--r--drivers/misc/sgi-gru/grumain.c17
-rw-r--r--drivers/misc/sgi-gru/grutables.h3
6 files changed, 35 insertions, 38 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 15507d31e62b..ab118558552e 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -360,6 +360,13 @@ static int gru_try_dropin(struct gru_thread_state *gts,
360 if (ret == -2) 360 if (ret == -2)
361 goto failupm; 361 goto failupm;
362 362
363 if (!(gts->ts_sizeavail & GRU_SIZEAVAIL(pageshift))) {
364 gts->ts_sizeavail |= GRU_SIZEAVAIL(pageshift);
365 if (atomic || !gru_update_cch(gts, 0)) {
366 gts->ts_force_cch_reload = 1;
367 goto failupm;
368 }
369 }
363 gru_cb_set_istatus_active(cb); 370 gru_cb_set_istatus_active(cb);
364 tfh_write_restart(tfh, gpa, GAA_RAM, vaddr, asid, write, 371 tfh_write_restart(tfh, gpa, GAA_RAM, vaddr, asid, write,
365 GRU_PAGESIZE(pageshift)); 372 GRU_PAGESIZE(pageshift));
@@ -535,6 +542,14 @@ int gru_handle_user_call_os(unsigned long cb)
535 gts->ts_force_unload = 1; 542 gts->ts_force_unload = 1;
536 } 543 }
537 544
545 /*
546 * CCH may contain stale data if ts_force_cch_reload is set.
547 */
548 if (gts->ts_gru && gts->ts_force_cch_reload) {
549 gru_update_cch(gts, 0);
550 gts->ts_force_cch_reload = 0;
551 }
552
538 ret = -EAGAIN; 553 ret = -EAGAIN;
539 cbrnum = thread_cbr_number(gts, ucbnum); 554 cbrnum = thread_cbr_number(gts, ucbnum);
540 if (gts->ts_force_unload) { 555 if (gts->ts_force_unload) {
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
index 9dcf5d896683..9b7ccb328697 100644
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -72,42 +72,16 @@ static int wait_instruction_complete(void *h, enum mcs_op opc)
72 return status; 72 return status;
73} 73}
74 74
75#if defined CONFIG_IA64 75int cch_allocate(struct gru_context_configuration_handle *cch,
76static void cch_allocate_set_asids( 76 int asidval, int sizeavail, unsigned long cbrmap,
77 struct gru_context_configuration_handle *cch, int asidval) 77 unsigned long dsrmap)
78{ 78{
79 int i; 79 int i;
80 80
81 for (i = 0; i < 8; i++) { 81 for (i = 0; i < 8; i++) {
82 cch->asid[i] = (asidval++); 82 cch->asid[i] = (asidval++);
83#if 0 83 cch->sizeavail[i] = sizeavail;
84 /* ZZZ hugepages not supported yet */
85 if (i == RGN_HPAGE)
86 cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift);
87 else
88#endif
89 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT);
90 } 84 }
91}
92#elif defined CONFIG_X86_64
93static void cch_allocate_set_asids(
94 struct gru_context_configuration_handle *cch, int asidval)
95{
96 int i;
97
98 for (i = 0; i < 8; i++) {
99 cch->asid[i] = asidval++;
100 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) |
101 GRU_SIZEAVAIL(21);
102 }
103}
104#endif
105
106int cch_allocate(struct gru_context_configuration_handle *cch,
107 int asidval, unsigned long cbrmap,
108 unsigned long dsrmap)
109{
110 cch_allocate_set_asids(cch, asidval);
111 cch->dsr_allocation_map = dsrmap; 85 cch->dsr_allocation_map = dsrmap;
112 cch->cbr_allocation_map = cbrmap; 86 cch->cbr_allocation_map = cbrmap;
113 cch->opc = CCHOP_ALLOCATE; 87 cch->opc = CCHOP_ALLOCATE;
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index dfce8ea5da24..1ed74d7508c8 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -496,7 +496,7 @@ enum gru_cbr_state {
496#define GRUMAXINVAL 1024UL 496#define GRUMAXINVAL 1024UL
497 497
498int cch_allocate(struct gru_context_configuration_handle *cch, 498int cch_allocate(struct gru_context_configuration_handle *cch,
499 int asidval, unsigned long cbrmap, unsigned long dsrmap); 499 int asidval, int sizeavail, unsigned long cbrmap, unsigned long dsrmap);
500 500
501int cch_start(struct gru_context_configuration_handle *cch); 501int cch_start(struct gru_context_configuration_handle *cch);
502int cch_interrupt(struct gru_context_configuration_handle *cch); 502int cch_interrupt(struct gru_context_configuration_handle *cch);
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 6b1efe447274..d8bd7d84a7cf 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -672,7 +672,7 @@ int gru_kservices_init(struct gru_state *gru)
672 cch->tlb_int_enable = 0; 672 cch->tlb_int_enable = 0;
673 cch->tfm_done_bit_enable = 0; 673 cch->tfm_done_bit_enable = 0;
674 cch->unmap_enable = 1; 674 cch->unmap_enable = 1;
675 err = cch_allocate(cch, 0, cbr_map, dsr_map); 675 err = cch_allocate(cch, 0, 0, cbr_map, dsr_map);
676 if (err) { 676 if (err) {
677 gru_dbg(grudev, 677 gru_dbg(grudev,
678 "Unable to allocate kernel CCH: gid %d, err %d\n", 678 "Unable to allocate kernel CCH: gid %d, err %d\n",
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 5fc7b5ecde66..ec3f7a17d221 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -326,6 +326,7 @@ static struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
326 gts->ts_vma = vma; 326 gts->ts_vma = vma;
327 gts->ts_tlb_int_select = -1; 327 gts->ts_tlb_int_select = -1;
328 gts->ts_gms = gru_register_mmu_notifier(); 328 gts->ts_gms = gru_register_mmu_notifier();
329 gts->ts_sizeavail = GRU_SIZEAVAIL(PAGE_SHIFT);
329 if (!gts->ts_gms) 330 if (!gts->ts_gms)
330 goto err; 331 goto err;
331 332
@@ -552,7 +553,8 @@ static void gru_load_context(struct gru_thread_state *gts)
552 cch->tlb_int_select = gts->ts_tlb_int_select; 553 cch->tlb_int_select = gts->ts_tlb_int_select;
553 } 554 }
554 cch->tfm_done_bit_enable = 0; 555 cch->tfm_done_bit_enable = 0;
555 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);
556 if (err) { 558 if (err) {
557 gru_dbg(grudev, 559 gru_dbg(grudev,
558 "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",
@@ -573,11 +575,12 @@ static void gru_load_context(struct gru_thread_state *gts)
573/* 575/*
574 * Update fields in an active CCH: 576 * Update fields in an active CCH:
575 * - retarget interrupts on local blade 577 * - retarget interrupts on local blade
578 * - update sizeavail mask
576 * - force a delayed context unload by clearing the CCH asids. This 579 * - force a delayed context unload by clearing the CCH asids. This
577 * forces TLB misses for new GRU instructions. The context is unloaded 580 * forces TLB misses for new GRU instructions. The context is unloaded
578 * when the next TLB miss occurs. 581 * when the next TLB miss occurs.
579 */ 582 */
580static int gru_update_cch(struct gru_thread_state *gts, int int_select) 583int gru_update_cch(struct gru_thread_state *gts, int force_unload)
581{ 584{
582 struct gru_context_configuration_handle *cch; 585 struct gru_context_configuration_handle *cch;
583 struct gru_state *gru = gts->ts_gru; 586 struct gru_state *gru = gts->ts_gru;
@@ -591,9 +594,11 @@ static int gru_update_cch(struct gru_thread_state *gts, int int_select)
591 goto exit; 594 goto exit;
592 if (cch_interrupt(cch)) 595 if (cch_interrupt(cch))
593 BUG(); 596 BUG();
594 if (int_select >= 0) { 597 if (!force_unload) {
595 gts->ts_tlb_int_select = int_select; 598 for (i = 0; i < 8; i++)
596 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();
597 } else { 602 } else {
598 for (i = 0; i < 8; i++) 603 for (i = 0; i < 8; i++)
599 cch->asid[i] = 0; 604 cch->asid[i] = 0;
@@ -625,7 +630,7 @@ static int gru_retarget_intr(struct gru_thread_state *gts)
625 630
626 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,
627 gru_cpu_fault_map_id()); 632 gru_cpu_fault_map_id());
628 return gru_update_cch(gts, gru_cpu_fault_map_id()); 633 return gru_update_cch(gts, 0);
629} 634}
630 635
631 636
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index 8e5c8e5bb533..bf1eeb7553ed 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -361,6 +361,7 @@ struct gru_thread_state {
361 long ts_user_options;/* misc user option flags */ 361 long ts_user_options;/* misc user option flags */
362 pid_t ts_tgid_owner; /* task that is using the 362 pid_t ts_tgid_owner; /* task that is using the
363 context - for migration */ 363 context - for migration */
364 unsigned short ts_sizeavail; /* Pagesizes in use */
364 int ts_tsid; /* thread that owns the 365 int ts_tsid; /* thread that owns the
365 structure */ 366 structure */
366 int ts_tlb_int_select;/* target cpu if interrupts 367 int ts_tlb_int_select;/* target cpu if interrupts
@@ -374,6 +375,7 @@ struct gru_thread_state {
374 required for contest */ 375 required for contest */
375 char ts_blade; /* If >= 0, migrate context if 376 char ts_blade; /* If >= 0, migrate context if
376 ref from diferent blade */ 377 ref from diferent blade */
378 char ts_force_cch_reload;
377 char ts_force_unload;/* force context to be unloaded 379 char ts_force_unload;/* force context to be unloaded
378 after migration */ 380 after migration */
379 char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each 381 char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each
@@ -597,6 +599,7 @@ extern struct gru_thread_state *gru_find_thread_state(struct vm_area_struct
597extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct 599extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct
598 *vma, int tsid); 600 *vma, int tsid);
599extern void gru_unload_context(struct gru_thread_state *gts, int savestate); 601extern void gru_unload_context(struct gru_thread_state *gts, int savestate);
602extern int gru_update_cch(struct gru_thread_state *gts, int force_unload);
600extern void gts_drop(struct gru_thread_state *gts); 603extern void gts_drop(struct gru_thread_state *gts);
601extern void gru_tgh_flush_init(struct gru_state *gru); 604extern void gru_tgh_flush_init(struct gru_state *gru);
602extern int gru_kservices_init(struct gru_state *gru); 605extern int gru_kservices_init(struct gru_state *gru);