diff options
author | Jack Steiner <steiner@sgi.com> | 2009-04-02 19:59:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:07 -0400 |
commit | 7b8274e93fbabc7534aa51f95551c30aecdd0066 (patch) | |
tree | f1cfc0e87b07a4094ee06d2dc73673635b4b1775 /drivers/misc | |
parent | 27ca8a7b2bdfb3e22e67fbd5df58e6b6f0bbcd48 (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.c | 15 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.c | 34 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.h | 2 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 2 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 17 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 3 |
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 | 75 | int cch_allocate(struct gru_context_configuration_handle *cch, |
76 | static 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 | ||
93 | static 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 | |||
106 | int 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 | ||
498 | int cch_allocate(struct gru_context_configuration_handle *cch, | 498 | int 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 | ||
501 | int cch_start(struct gru_context_configuration_handle *cch); | 501 | int cch_start(struct gru_context_configuration_handle *cch); |
502 | int cch_interrupt(struct gru_context_configuration_handle *cch); | 502 | int 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 | */ |
580 | static int gru_update_cch(struct gru_thread_state *gts, int int_select) | 583 | int 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 | |||
597 | extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct | 599 | extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct |
598 | *vma, int tsid); | 600 | *vma, int tsid); |
599 | extern void gru_unload_context(struct gru_thread_state *gts, int savestate); | 601 | extern void gru_unload_context(struct gru_thread_state *gts, int savestate); |
602 | extern int gru_update_cch(struct gru_thread_state *gts, int force_unload); | ||
600 | extern void gts_drop(struct gru_thread_state *gts); | 603 | extern void gts_drop(struct gru_thread_state *gts); |
601 | extern void gru_tgh_flush_init(struct gru_state *gru); | 604 | extern void gru_tgh_flush_init(struct gru_state *gru); |
602 | extern int gru_kservices_init(struct gru_state *gru); | 605 | extern int gru_kservices_init(struct gru_state *gru); |