aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/sgi-gru/Makefile2
-rw-r--r--drivers/misc/sgi-gru/gruhandles.c197
-rw-r--r--drivers/misc/sgi-gru/gruhandles.h176
-rw-r--r--drivers/misc/sgi-gru/grutables.h3
4 files changed, 218 insertions, 160 deletions
diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile
index 9e9170b3599a..bcd8136d2f98 100644
--- a/drivers/misc/sgi-gru/Makefile
+++ b/drivers/misc/sgi-gru/Makefile
@@ -3,5 +3,5 @@ ifdef CONFIG_SGI_GRU_DEBUG
3endif 3endif
4 4
5obj-$(CONFIG_SGI_GRU) := gru.o 5obj-$(CONFIG_SGI_GRU) := gru.o
6gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o 6gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o
7 7
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
new file mode 100644
index 000000000000..5b82e7def16d
--- /dev/null
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -0,0 +1,197 @@
1/*
2 * GRU KERNEL MCS INSTRUCTIONS
3 *
4 * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include "gru.h"
23#include "grulib.h"
24#include "grutables.h"
25
26/* 10 sec */
27#ifdef CONFIG_IA64
28#include <asm/processor.h>
29#define GRU_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10)
30#else
31#include <asm/tsc.h>
32#define GRU_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000)
33#endif
34
35/* Extract the status field from a kernel handle */
36#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3)
37
38static void start_instruction(void *h)
39{
40 unsigned long *w0 = h;
41
42 wmb(); /* setting CMD bit must be last */
43 *w0 = *w0 | 1;
44 gru_flush_cache(h);
45}
46
47static int wait_instruction_complete(void *h, enum mcs_op opc)
48{
49 int status;
50 cycles_t start_time = get_cycles();
51
52 while (1) {
53 cpu_relax();
54 status = GET_MSEG_HANDLE_STATUS(h);
55 if (status != CCHSTATUS_ACTIVE)
56 break;
57 if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
58 panic("GRU %p is malfunctioning\n", h);
59 }
60 return status;
61}
62
63#if defined CONFIG_IA64
64static void cch_allocate_set_asids(
65 struct gru_context_configuration_handle *cch, int asidval)
66{
67 int i;
68
69 for (i = 0; i < 8; i++) {
70 cch->asid[i] = (asidval++);
71#if 0
72 /* ZZZ hugepages not supported yet */
73 if (i == RGN_HPAGE)
74 cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift);
75 else
76#endif
77 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT);
78 }
79}
80#elif defined CONFIG_X86_64
81static void cch_allocate_set_asids(
82 struct gru_context_configuration_handle *cch, int asidval)
83{
84 int i;
85
86 for (i = 0; i < 8; i++) {
87 cch->asid[i] = asidval++;
88 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) |
89 GRU_SIZEAVAIL(21);
90 }
91}
92#endif
93
94int cch_allocate(struct gru_context_configuration_handle *cch,
95 int asidval, unsigned long cbrmap,
96 unsigned long dsrmap)
97{
98 cch_allocate_set_asids(cch, asidval);
99 cch->dsr_allocation_map = dsrmap;
100 cch->cbr_allocation_map = cbrmap;
101 cch->opc = CCHOP_ALLOCATE;
102 start_instruction(cch);
103 return wait_instruction_complete(cch, cchop_allocate);
104}
105
106int cch_start(struct gru_context_configuration_handle *cch)
107{
108 cch->opc = CCHOP_START;
109 start_instruction(cch);
110 return wait_instruction_complete(cch, cchop_start);
111}
112
113int cch_interrupt(struct gru_context_configuration_handle *cch)
114{
115 cch->opc = CCHOP_INTERRUPT;
116 start_instruction(cch);
117 return wait_instruction_complete(cch, cchop_interrupt);
118}
119
120int cch_deallocate(struct gru_context_configuration_handle *cch)
121{
122 cch->opc = CCHOP_DEALLOCATE;
123 start_instruction(cch);
124 return wait_instruction_complete(cch, cchop_deallocate);
125}
126
127int cch_interrupt_sync(struct gru_context_configuration_handle
128 *cch)
129{
130 cch->opc = CCHOP_INTERRUPT_SYNC;
131 start_instruction(cch);
132 return wait_instruction_complete(cch, cchop_interrupt_sync);
133}
134
135int tgh_invalidate(struct gru_tlb_global_handle *tgh,
136 unsigned long vaddr, unsigned long vaddrmask,
137 int asid, int pagesize, int global, int n,
138 unsigned short ctxbitmap)
139{
140 tgh->vaddr = vaddr;
141 tgh->asid = asid;
142 tgh->pagesize = pagesize;
143 tgh->n = n;
144 tgh->global = global;
145 tgh->vaddrmask = vaddrmask;
146 tgh->ctxbitmap = ctxbitmap;
147 tgh->opc = TGHOP_TLBINV;
148 start_instruction(tgh);
149 return wait_instruction_complete(tgh, tghop_invalidate);
150}
151
152void tfh_write_only(struct gru_tlb_fault_handle *tfh,
153 unsigned long pfn, unsigned long vaddr,
154 int asid, int dirty, int pagesize)
155{
156 tfh->fillasid = asid;
157 tfh->fillvaddr = vaddr;
158 tfh->pfn = pfn;
159 tfh->dirty = dirty;
160 tfh->pagesize = pagesize;
161 tfh->opc = TFHOP_WRITE_ONLY;
162 start_instruction(tfh);
163}
164
165void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
166 unsigned long paddr, int gaa,
167 unsigned long vaddr, int asid, int dirty,
168 int pagesize)
169{
170 tfh->fillasid = asid;
171 tfh->fillvaddr = vaddr;
172 tfh->pfn = paddr >> GRU_PADDR_SHIFT;
173 tfh->gaa = gaa;
174 tfh->dirty = dirty;
175 tfh->pagesize = pagesize;
176 tfh->opc = TFHOP_WRITE_RESTART;
177 start_instruction(tfh);
178}
179
180void tfh_restart(struct gru_tlb_fault_handle *tfh)
181{
182 tfh->opc = TFHOP_RESTART;
183 start_instruction(tfh);
184}
185
186void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh)
187{
188 tfh->opc = TFHOP_USER_POLLING_MODE;
189 start_instruction(tfh);
190}
191
192void tfh_exception(struct gru_tlb_fault_handle *tfh)
193{
194 tfh->opc = TFHOP_EXCEPTION;
195 start_instruction(tfh);
196}
197
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index fb72a52a34a8..dfce8ea5da24 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -495,164 +495,22 @@ enum gru_cbr_state {
495/* minimum TLB purge count to ensure a full purge */ 495/* minimum TLB purge count to ensure a full purge */
496#define GRUMAXINVAL 1024UL 496#define GRUMAXINVAL 1024UL
497 497
498 498int cch_allocate(struct gru_context_configuration_handle *cch,
499/* Extract the status field from a kernel handle */ 499 int asidval, unsigned long cbrmap, unsigned long dsrmap);
500#define GET_MSEG_HANDLE_STATUS(h) (((*(unsigned long *)(h)) >> 16) & 3) 500
501 501int cch_start(struct gru_context_configuration_handle *cch);
502static inline void start_instruction(void *h) 502int cch_interrupt(struct gru_context_configuration_handle *cch);
503{ 503int cch_deallocate(struct gru_context_configuration_handle *cch);
504 unsigned long *w0 = h; 504int cch_interrupt_sync(struct gru_context_configuration_handle *cch);
505 505int tgh_invalidate(struct gru_tlb_global_handle *tgh, unsigned long vaddr,
506 wmb(); /* setting CMD bit must be last */ 506 unsigned long vaddrmask, int asid, int pagesize, int global, int n,
507 *w0 = *w0 | 1; 507 unsigned short ctxbitmap);
508 gru_flush_cache(h); 508void tfh_write_only(struct gru_tlb_fault_handle *tfh, unsigned long pfn,
509} 509 unsigned long vaddr, int asid, int dirty, int pagesize);
510 510void tfh_write_restart(struct gru_tlb_fault_handle *tfh, unsigned long paddr,
511static inline int wait_instruction_complete(void *h) 511 int gaa, unsigned long vaddr, int asid, int dirty, int pagesize);
512{ 512void tfh_restart(struct gru_tlb_fault_handle *tfh);
513 int status; 513void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh);
514 514void tfh_exception(struct gru_tlb_fault_handle *tfh);
515 do {
516 cpu_relax();
517 barrier();
518 status = GET_MSEG_HANDLE_STATUS(h);
519 } while (status == CCHSTATUS_ACTIVE);
520 return status;
521}
522
523#if defined CONFIG_IA64
524static inline void cch_allocate_set_asids(
525 struct gru_context_configuration_handle *cch, int asidval)
526{
527 int i;
528
529 for (i = 0; i <= RGN_HPAGE; i++) { /* assume HPAGE is last region */
530 cch->asid[i] = (asidval++);
531#if 0
532 /* ZZZ hugepages not supported yet */
533 if (i == RGN_HPAGE)
534 cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift);
535 else
536#endif
537 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT);
538 }
539}
540#elif defined CONFIG_X86_64
541static inline void cch_allocate_set_asids(
542 struct gru_context_configuration_handle *cch, int asidval)
543{
544 int i;
545
546 for (i = 0; i < 8; i++) {
547 cch->asid[i] = asidval++;
548 cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) |
549 GRU_SIZEAVAIL(21);
550 }
551}
552#endif
553
554static inline int cch_allocate(struct gru_context_configuration_handle *cch,
555 int asidval, unsigned long cbrmap,
556 unsigned long dsrmap)
557{
558 cch_allocate_set_asids(cch, asidval);
559 cch->dsr_allocation_map = dsrmap;
560 cch->cbr_allocation_map = cbrmap;
561 cch->opc = CCHOP_ALLOCATE;
562 start_instruction(cch);
563 return wait_instruction_complete(cch);
564}
565
566static inline int cch_start(struct gru_context_configuration_handle *cch)
567{
568 cch->opc = CCHOP_START;
569 start_instruction(cch);
570 return wait_instruction_complete(cch);
571}
572
573static inline int cch_interrupt(struct gru_context_configuration_handle *cch)
574{
575 cch->opc = CCHOP_INTERRUPT;
576 start_instruction(cch);
577 return wait_instruction_complete(cch);
578}
579
580static inline int cch_deallocate(struct gru_context_configuration_handle *cch)
581{
582 cch->opc = CCHOP_DEALLOCATE;
583 start_instruction(cch);
584 return wait_instruction_complete(cch);
585}
586
587static inline int cch_interrupt_sync(struct gru_context_configuration_handle
588 *cch)
589{
590 cch->opc = CCHOP_INTERRUPT_SYNC;
591 start_instruction(cch);
592 return wait_instruction_complete(cch);
593}
594
595static inline int tgh_invalidate(struct gru_tlb_global_handle *tgh,
596 unsigned long vaddr, unsigned long vaddrmask,
597 int asid, int pagesize, int global, int n,
598 unsigned short ctxbitmap)
599{
600 tgh->vaddr = vaddr;
601 tgh->asid = asid;
602 tgh->pagesize = pagesize;
603 tgh->n = n;
604 tgh->global = global;
605 tgh->vaddrmask = vaddrmask;
606 tgh->ctxbitmap = ctxbitmap;
607 tgh->opc = TGHOP_TLBINV;
608 start_instruction(tgh);
609 return wait_instruction_complete(tgh);
610}
611
612static inline void tfh_write_only(struct gru_tlb_fault_handle *tfh,
613 unsigned long pfn, unsigned long vaddr,
614 int asid, int dirty, int pagesize)
615{
616 tfh->fillasid = asid;
617 tfh->fillvaddr = vaddr;
618 tfh->pfn = pfn;
619 tfh->dirty = dirty;
620 tfh->pagesize = pagesize;
621 tfh->opc = TFHOP_WRITE_ONLY;
622 start_instruction(tfh);
623}
624
625static inline void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
626 unsigned long paddr, int gaa,
627 unsigned long vaddr, int asid, int dirty,
628 int pagesize)
629{
630 tfh->fillasid = asid;
631 tfh->fillvaddr = vaddr;
632 tfh->pfn = paddr >> GRU_PADDR_SHIFT;
633 tfh->gaa = gaa;
634 tfh->dirty = dirty;
635 tfh->pagesize = pagesize;
636 tfh->opc = TFHOP_WRITE_RESTART;
637 start_instruction(tfh);
638}
639
640static inline void tfh_restart(struct gru_tlb_fault_handle *tfh)
641{
642 tfh->opc = TFHOP_RESTART;
643 start_instruction(tfh);
644}
645
646static inline void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh)
647{
648 tfh->opc = TFHOP_USER_POLLING_MODE;
649 start_instruction(tfh);
650}
651
652static inline void tfh_exception(struct gru_tlb_fault_handle *tfh)
653{
654 tfh->opc = TFHOP_EXCEPTION;
655 start_instruction(tfh);
656}
657 515
658#endif /* __GRUHANDLES_H__ */ 516#endif /* __GRUHANDLES_H__ */
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index cc0fc734405e..378a0894198e 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -239,6 +239,9 @@ struct gru_stats_s {
239 239
240}; 240};
241 241
242enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync,
243 cchop_deallocate, tghop_invalidate, mcsop_last};
244
242#define OPT_DPRINT 1 245#define OPT_DPRINT 1
243#define OPT_STATS 2 246#define OPT_STATS 2
244#define GRU_QUICKLOOK 4 247#define GRU_QUICKLOOK 4