diff options
| -rw-r--r-- | drivers/misc/sgi-gru/gru_instructions.h | 10 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grufile.c | 8 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 6 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 16 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/gruprocfs.c | 4 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 74 | ||||
| -rw-r--r-- | drivers/misc/sgi-gru/grutlbpurge.c | 4 |
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 | */ | ||
| 292 | static inline void gru_prefetch(void *p) | ||
| 293 | { | ||
| 294 | *(volatile char *)p; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Architecture specific intrinsics | 288 | * Architecture specific intrinsics |
| 299 | */ | 289 | */ |
| 300 | static inline void gru_flush_cache(void *p) | 290 | static 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 = { | |||
| 471 | module_init(gru_init); | 475 | module_init(gru_init); |
| 472 | module_exit(gru_exit); | 476 | module_exit(gru_exit); |
| 473 | 477 | ||
| 474 | module_param(options, ulong, 0644); | 478 | module_param(gru_options, ulong, 0644); |
| 475 | MODULE_PARM_DESC(options, "Various debug options"); | 479 | MODULE_PARM_DESC(gru_options, "Various debug options"); |
| 476 | 480 | ||
| 477 | MODULE_AUTHOR("Silicon Graphics, Inc."); | 481 | MODULE_AUTHOR("Silicon Graphics, Inc."); |
| 478 | MODULE_LICENSE("GPL"); | 482 | MODULE_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 | ||
| 25 | unsigned long options __read_mostly; | 25 | unsigned long gru_options __read_mostly; |
| 26 | 26 | ||
| 27 | static struct device_driver gru_driver = { | 27 | static 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 | ||
| 166 | unsigned long reserve_gru_cb_resources(struct gru_state *gru, int cbr_au_count, | 166 | unsigned 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 | ||
| 173 | unsigned long reserve_gru_ds_resources(struct gru_state *gru, int dsr_au_count, | 173 | unsigned 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 | ||
| 191 | static void free_gru_resources(struct gru_state *gru, | 191 | static 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 | */ |
| 420 | static void prefetch_data(void *p, int num, int stride) | 421 | static 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 | */ |
| 750 | int gru_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 753 | int 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(>s->ts_ctxlock); | 783 | mutex_unlock(>s->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 | ||
| 123 | static int options_show(struct seq_file *s, void *p) | 123 | static 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); | |||
| 529 | extern int gru_proc_init(void); | 593 | extern int gru_proc_init(void); |
| 530 | extern void gru_proc_exit(void); | 594 | extern void gru_proc_exit(void); |
| 531 | 595 | ||
| 532 | extern unsigned long reserve_gru_cb_resources(struct gru_state *gru, | 596 | extern unsigned long gru_reserve_cb_resources(struct gru_state *gru, |
| 533 | int cbr_au_count, char *cbmap); | 597 | int cbr_au_count, char *cbmap); |
| 534 | extern unsigned long reserve_gru_ds_resources(struct gru_state *gru, | 598 | extern unsigned long gru_reserve_ds_resources(struct gru_state *gru, |
| 535 | int dsr_au_count, char *dsmap); | 599 | int dsr_au_count, char *dsmap); |
| 536 | extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf); | 600 | extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf); |
| 537 | extern struct gru_mm_struct *gru_register_mmu_notifier(void); | 601 | extern struct gru_mm_struct *gru_register_mmu_notifier(void); |
| @@ -540,6 +604,6 @@ extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms); | |||
| 540 | extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start, | 604 | extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start, |
| 541 | unsigned long len); | 605 | unsigned long len); |
| 542 | 606 | ||
| 543 | extern unsigned long options; | 607 | extern 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 | } |
