aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/sgi-gru/gru_instructions.h10
-rw-r--r--drivers/misc/sgi-gru/grufile.c8
-rw-r--r--drivers/misc/sgi-gru/grukservices.c6
-rw-r--r--drivers/misc/sgi-gru/grumain.c16
-rw-r--r--drivers/misc/sgi-gru/gruprocfs.c4
-rw-r--r--drivers/misc/sgi-gru/grutables.h74
-rw-r--r--drivers/misc/sgi-gru/grutlbpurge.c4
7 files changed, 93 insertions, 29 deletions
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h
index 3159b261c5a7..0dc36225c7c6 100644
--- a/drivers/misc/sgi-gru/gru_instructions.h
+++ b/drivers/misc/sgi-gru/gru_instructions.h
@@ -285,16 +285,6 @@ __opword(unsigned char opcode, unsigned char exopc, unsigned char xtype,
285} 285}
286 286
287/* 287/*
288 * Prefetch a cacheline. Fetch is unconditional. Must page fault if
289 * no valid TLB entry is found.
290 * ??? should I use actual "load" or hardware prefetch???
291 */
292static inline void gru_prefetch(void *p)
293{
294 *(volatile char *)p;
295}
296
297/*
298 * Architecture specific intrinsics 288 * Architecture specific intrinsics
299 */ 289 */
300static inline void gru_flush_cache(void *p) 290static inline void gru_flush_cache(void *p)
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index 09c9c65ff9d1..23c91f5f6b61 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -112,6 +112,10 @@ static int gru_file_mmap(struct file *file, struct vm_area_struct *vma)
112 if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) != (VM_SHARED | VM_WRITE)) 112 if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) != (VM_SHARED | VM_WRITE))
113 return -EPERM; 113 return -EPERM;
114 114
115 if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) ||
116 vma->vm_end & (GRU_GSEG_PAGESIZE - 1))
117 return -EINVAL;
118
115 vma->vm_flags |= 119 vma->vm_flags |=
116 (VM_IO | VM_DONTCOPY | VM_LOCKED | VM_DONTEXPAND | VM_PFNMAP | 120 (VM_IO | VM_DONTCOPY | VM_LOCKED | VM_DONTEXPAND | VM_PFNMAP |
117 VM_RESERVED); 121 VM_RESERVED);
@@ -471,8 +475,8 @@ struct vm_operations_struct gru_vm_ops = {
471module_init(gru_init); 475module_init(gru_init);
472module_exit(gru_exit); 476module_exit(gru_exit);
473 477
474module_param(options, ulong, 0644); 478module_param(gru_options, ulong, 0644);
475MODULE_PARM_DESC(options, "Various debug options"); 479MODULE_PARM_DESC(gru_options, "Various debug options");
476 480
477MODULE_AUTHOR("Silicon Graphics, Inc."); 481MODULE_AUTHOR("Silicon Graphics, Inc.");
478MODULE_LICENSE("GPL"); 482MODULE_LICENSE("GPL");
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 234d165fb11e..dfd49af0fe18 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -638,11 +638,11 @@ int gru_kservices_init(struct gru_state *gru)
638 cpus_possible = uv_blade_nr_possible_cpus(gru->gs_blade_id); 638 cpus_possible = uv_blade_nr_possible_cpus(gru->gs_blade_id);
639 639
640 num = GRU_NUM_KERNEL_CBR * cpus_possible; 640 num = GRU_NUM_KERNEL_CBR * cpus_possible;
641 cbr_map = reserve_gru_cb_resources(gru, GRU_CB_COUNT_TO_AU(num), NULL); 641 cbr_map = gru_reserve_cb_resources(gru, GRU_CB_COUNT_TO_AU(num), NULL);
642 gru->gs_reserved_cbrs += num; 642 gru->gs_reserved_cbrs += num;
643 643
644 num = GRU_NUM_KERNEL_DSR_BYTES * cpus_possible; 644 num = GRU_NUM_KERNEL_DSR_BYTES * cpus_possible;
645 dsr_map = reserve_gru_ds_resources(gru, GRU_DS_BYTES_TO_AU(num), NULL); 645 dsr_map = gru_reserve_ds_resources(gru, GRU_DS_BYTES_TO_AU(num), NULL);
646 gru->gs_reserved_dsr_bytes += num; 646 gru->gs_reserved_dsr_bytes += num;
647 647
648 gru->gs_active_contexts++; 648 gru->gs_active_contexts++;
@@ -673,7 +673,7 @@ int gru_kservices_init(struct gru_state *gru)
673 } 673 }
674 unlock_cch_handle(cch); 674 unlock_cch_handle(cch);
675 675
676 if (options & GRU_QUICKLOOK) 676 if (gru_options & GRU_QUICKLOOK)
677 quicktest(gru); 677 quicktest(gru);
678 return 0; 678 return 0;
679} 679}
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index aef6822cb80e..0eeb8dddd2f5 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -22,7 +22,7 @@
22#include "grutables.h" 22#include "grutables.h"
23#include "gruhandles.h" 23#include "gruhandles.h"
24 24
25unsigned long options __read_mostly; 25unsigned long gru_options __read_mostly;
26 26
27static struct device_driver gru_driver = { 27static struct device_driver gru_driver = {
28 .name = "gru" 28 .name = "gru"
@@ -163,14 +163,14 @@ static unsigned long reserve_resources(unsigned long *p, int n, int mmax,
163 return bits; 163 return bits;
164} 164}
165 165
166unsigned long reserve_gru_cb_resources(struct gru_state *gru, int cbr_au_count, 166unsigned long gru_reserve_cb_resources(struct gru_state *gru, int cbr_au_count,
167 char *cbmap) 167 char *cbmap)
168{ 168{
169 return reserve_resources(&gru->gs_cbr_map, cbr_au_count, GRU_CBR_AU, 169 return reserve_resources(&gru->gs_cbr_map, cbr_au_count, GRU_CBR_AU,
170 cbmap); 170 cbmap);
171} 171}
172 172
173unsigned long reserve_gru_ds_resources(struct gru_state *gru, int dsr_au_count, 173unsigned long gru_reserve_ds_resources(struct gru_state *gru, int dsr_au_count,
174 char *dsmap) 174 char *dsmap)
175{ 175{
176 return reserve_resources(&gru->gs_dsr_map, dsr_au_count, GRU_DSR_AU, 176 return reserve_resources(&gru->gs_dsr_map, dsr_au_count, GRU_DSR_AU,
@@ -182,10 +182,10 @@ static void reserve_gru_resources(struct gru_state *gru,
182{ 182{
183 gru->gs_active_contexts++; 183 gru->gs_active_contexts++;
184 gts->ts_cbr_map = 184 gts->ts_cbr_map =
185 reserve_gru_cb_resources(gru, gts->ts_cbr_au_count, 185 gru_reserve_cb_resources(gru, gts->ts_cbr_au_count,
186 gts->ts_cbr_idx); 186 gts->ts_cbr_idx);
187 gts->ts_dsr_map = 187 gts->ts_dsr_map =
188 reserve_gru_ds_resources(gru, gts->ts_dsr_au_count, NULL); 188 gru_reserve_ds_resources(gru, gts->ts_dsr_au_count, NULL);
189} 189}
190 190
191static void free_gru_resources(struct gru_state *gru, 191static void free_gru_resources(struct gru_state *gru,
@@ -416,6 +416,7 @@ static void gru_free_gru_context(struct gru_thread_state *gts)
416 416
417/* 417/*
418 * Prefetching cachelines help hardware performance. 418 * Prefetching cachelines help hardware performance.
419 * (Strictly a performance enhancement. Not functionally required).
419 */ 420 */
420static void prefetch_data(void *p, int num, int stride) 421static void prefetch_data(void *p, int num, int stride)
421{ 422{
@@ -746,6 +747,8 @@ again:
746 * gru_nopage 747 * gru_nopage
747 * 748 *
748 * Map the user's GRU segment 749 * Map the user's GRU segment
750 *
751 * Note: gru segments alway mmaped on GRU_GSEG_PAGESIZE boundaries.
749 */ 752 */
750int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 753int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
751{ 754{
@@ -757,6 +760,7 @@ int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
757 vma, vaddr, GSEG_BASE(vaddr)); 760 vma, vaddr, GSEG_BASE(vaddr));
758 STAT(nopfn); 761 STAT(nopfn);
759 762
763 /* The following check ensures vaddr is a valid address in the VMA */
760 gts = gru_find_thread_state(vma, TSID(vaddr, vma)); 764 gts = gru_find_thread_state(vma, TSID(vaddr, vma));
761 if (!gts) 765 if (!gts)
762 return VM_FAULT_SIGBUS; 766 return VM_FAULT_SIGBUS;
@@ -775,7 +779,7 @@ again:
775 } 779 }
776 780
777 if (!gts->ts_gru) { 781 if (!gts->ts_gru) {
778 while (!gru_assign_gru_context(gts)) { 782 if (!gru_assign_gru_context(gts)) {
779 mutex_unlock(&gts->ts_ctxlock); 783 mutex_unlock(&gts->ts_ctxlock);
780 preempt_enable(); 784 preempt_enable();
781 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */ 785 schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index bdb1ad83bbfb..533923f83f1a 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -122,7 +122,7 @@ static ssize_t statistics_write(struct file *file, const char __user *userbuf,
122 122
123static int options_show(struct seq_file *s, void *p) 123static int options_show(struct seq_file *s, void *p)
124{ 124{
125 seq_printf(s, "0x%lx\n", options); 125 seq_printf(s, "0x%lx\n", gru_options);
126 return 0; 126 return 0;
127} 127}
128 128
@@ -136,7 +136,7 @@ static ssize_t options_write(struct file *file, const char __user *userbuf,
136 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf))) 136 (buf, userbuf, count < sizeof(buf) ? count : sizeof(buf)))
137 return -EFAULT; 137 return -EFAULT;
138 if (!strict_strtoul(buf, 10, &val)) 138 if (!strict_strtoul(buf, 10, &val))
139 options = val; 139 gru_options = val;
140 140
141 return count; 141 return count;
142} 142}
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index f97d84640129..4251018f70ff 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -24,6 +24,70 @@
24#define __GRUTABLES_H__ 24#define __GRUTABLES_H__
25 25
26/* 26/*
27 * GRU Chiplet:
28 * The GRU is a user addressible memory accelerator. It provides
29 * several forms of load, store, memset, bcopy instructions. In addition, it
30 * contains special instructions for AMOs, sending messages to message
31 * queues, etc.
32 *
33 * The GRU is an integral part of the node controller. It connects
34 * directly to the cpu socket. In its current implementation, there are 2
35 * GRU chiplets in the node controller on each blade (~node).
36 *
37 * The entire GRU memory space is fully coherent and cacheable by the cpus.
38 *
39 * Each GRU chiplet has a physical memory map that looks like the following:
40 *
41 * +-----------------+
42 * |/////////////////|
43 * |/////////////////|
44 * |/////////////////|
45 * |/////////////////|
46 * |/////////////////|
47 * |/////////////////|
48 * |/////////////////|
49 * |/////////////////|
50 * +-----------------+
51 * | system control |
52 * +-----------------+ _______ +-------------+
53 * |/////////////////| / | |
54 * |/////////////////| / | |
55 * |/////////////////| / | instructions|
56 * |/////////////////| / | |
57 * |/////////////////| / | |
58 * |/////////////////| / |-------------|
59 * |/////////////////| / | |
60 * +-----------------+ | |
61 * | context 15 | | data |
62 * +-----------------+ | |
63 * | ...... | \ | |
64 * +-----------------+ \____________ +-------------+
65 * | context 1 |
66 * +-----------------+
67 * | context 0 |
68 * +-----------------+
69 *
70 * Each of the "contexts" is a chunk of memory that can be mmaped into user
71 * space. The context consists of 2 parts:
72 *
73 * - an instruction space that can be directly accessed by the user
74 * to issue GRU instructions and to check instruction status.
75 *
76 * - a data area that acts as normal RAM.
77 *
78 * User instructions contain virtual addresses of data to be accessed by the
79 * GRU. The GRU contains a TLB that is used to convert these user virtual
80 * addresses to physical addresses.
81 *
82 * The "system control" area of the GRU chiplet is used by the kernel driver
83 * to manage user contexts and to perform functions such as TLB dropin and
84 * purging.
85 *
86 * One context may be reserved for the kernel and used for cross-partition
87 * communication. The GRU will also be used to asynchronously zero out
88 * large blocks of memory (not currently implemented).
89 *
90 *
27 * Tables: 91 * Tables:
28 * 92 *
29 * VDATA-VMA Data - Holds a few parameters. Head of linked list of 93 * VDATA-VMA Data - Holds a few parameters. Head of linked list of
@@ -190,14 +254,14 @@ struct gru_stats_s {
190#define GRU_STEAL_DELAY ((HZ * 200) / 1000) 254#define GRU_STEAL_DELAY ((HZ * 200) / 1000)
191 255
192#define STAT(id) do { \ 256#define STAT(id) do { \
193 if (options & OPT_STATS) \ 257 if (gru_options & OPT_STATS) \
194 atomic_long_inc(&gru_stats.id); \ 258 atomic_long_inc(&gru_stats.id); \
195 } while (0) 259 } while (0)
196 260
197#ifdef CONFIG_SGI_GRU_DEBUG 261#ifdef CONFIG_SGI_GRU_DEBUG
198#define gru_dbg(dev, fmt, x...) \ 262#define gru_dbg(dev, fmt, x...) \
199 do { \ 263 do { \
200 if (options & OPT_DPRINT) \ 264 if (gru_options & OPT_DPRINT) \
201 dev_dbg(dev, "%s: " fmt, __func__, x); \ 265 dev_dbg(dev, "%s: " fmt, __func__, x); \
202 } while (0) 266 } while (0)
203#else 267#else
@@ -529,9 +593,9 @@ extern void gru_flush_all_tlb(struct gru_state *gru);
529extern int gru_proc_init(void); 593extern int gru_proc_init(void);
530extern void gru_proc_exit(void); 594extern void gru_proc_exit(void);
531 595
532extern unsigned long reserve_gru_cb_resources(struct gru_state *gru, 596extern unsigned long gru_reserve_cb_resources(struct gru_state *gru,
533 int cbr_au_count, char *cbmap); 597 int cbr_au_count, char *cbmap);
534extern unsigned long reserve_gru_ds_resources(struct gru_state *gru, 598extern unsigned long gru_reserve_ds_resources(struct gru_state *gru,
535 int dsr_au_count, char *dsmap); 599 int dsr_au_count, char *dsmap);
536extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf); 600extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf);
537extern struct gru_mm_struct *gru_register_mmu_notifier(void); 601extern struct gru_mm_struct *gru_register_mmu_notifier(void);
@@ -540,6 +604,6 @@ extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms);
540extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start, 604extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start,
541 unsigned long len); 605 unsigned long len);
542 606
543extern unsigned long options; 607extern unsigned long gru_options;
544 608
545#endif /* __GRUTABLES_H__ */ 609#endif /* __GRUTABLES_H__ */
diff --git a/drivers/misc/sgi-gru/grutlbpurge.c b/drivers/misc/sgi-gru/grutlbpurge.c
index bb6b0e64e101..bcfd5425e2e6 100644
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -242,7 +242,9 @@ static void gru_invalidate_range_end(struct mmu_notifier *mn,
242 struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct, 242 struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct,
243 ms_notifier); 243 ms_notifier);
244 244
245 atomic_dec(&gms->ms_range_active); 245 /* ..._and_test() provides needed barrier */
246 (void)atomic_dec_and_test(&gms->ms_range_active);
247
246 wake_up_all(&gms->ms_wait_queue); 248 wake_up_all(&gms->ms_wait_queue);
247 gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx\n", gms, start, end); 249 gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx\n", gms, start, end);
248} 250}