aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grukservices.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-gru/grukservices.c')
-rw-r--r--drivers/misc/sgi-gru/grukservices.c201
1 files changed, 120 insertions, 81 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 900f7aad2286..50b4dd8b0c9f 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -31,6 +31,7 @@
31#include <linux/proc_fs.h> 31#include <linux/proc_fs.h>
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33#include <linux/uaccess.h> 33#include <linux/uaccess.h>
34#include <linux/delay.h>
34#include "gru.h" 35#include "gru.h"
35#include "grulib.h" 36#include "grulib.h"
36#include "grutables.h" 37#include "grutables.h"
@@ -45,18 +46,17 @@
45 * resources. This will likely be replaced when we better understand the 46 * resources. This will likely be replaced when we better understand the
46 * kernel/user requirements. 47 * kernel/user requirements.
47 * 48 *
48 * At boot time, the kernel permanently reserves a fixed number of 49 * Blade percpu resources reserved for kernel use. These resources are
49 * CBRs/DSRs for each cpu to use. The resources are all taken from 50 * reserved whenever the the kernel context for the blade is loaded. Note
50 * the GRU chiplet 1 on the blade. This leaves the full set of resources 51 * that the kernel context is not guaranteed to be always available. It is
51 * of chiplet 0 available to be allocated to a single user. 52 * loaded on demand & can be stolen by a user if the user demand exceeds the
53 * kernel demand. The kernel can always reload the kernel context but
54 * a SLEEP may be required!!!.
52 */ 55 */
53
54/* Blade percpu resources PERMANENTLY reserved for kernel use */
55#define GRU_NUM_KERNEL_CBR 1 56#define GRU_NUM_KERNEL_CBR 1
56#define GRU_NUM_KERNEL_DSR_BYTES 256 57#define GRU_NUM_KERNEL_DSR_BYTES 256
57#define GRU_NUM_KERNEL_DSR_CL (GRU_NUM_KERNEL_DSR_BYTES / \ 58#define GRU_NUM_KERNEL_DSR_CL (GRU_NUM_KERNEL_DSR_BYTES / \
58 GRU_CACHE_LINE_BYTES) 59 GRU_CACHE_LINE_BYTES)
59#define KERNEL_CTXNUM 15
60 60
61/* GRU instruction attributes for all instructions */ 61/* GRU instruction attributes for all instructions */
62#define IMA IMA_CB_DELAY 62#define IMA IMA_CB_DELAY
@@ -98,6 +98,88 @@ struct message_header {
98 98
99#define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h])) 99#define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h]))
100 100
101/*
102 * Allocate a kernel context (GTS) for the specified blade.
103 * - protected by writelock on bs_kgts_sema.
104 */
105static void gru_alloc_kernel_context(struct gru_blade_state *bs, int blade_id)
106{
107 int cbr_au_count, dsr_au_count, ncpus;
108
109 ncpus = uv_blade_nr_possible_cpus(blade_id);
110 cbr_au_count = GRU_CB_COUNT_TO_AU(GRU_NUM_KERNEL_CBR * ncpus);
111 dsr_au_count = GRU_DS_BYTES_TO_AU(GRU_NUM_KERNEL_DSR_BYTES * ncpus);
112 bs->bs_kgts = gru_alloc_gts(NULL, cbr_au_count, dsr_au_count, 0, 0);
113}
114
115/*
116 * Reload the blade's kernel context into a GRU chiplet. Called holding
117 * the bs_kgts_sema for READ. Will steal user contexts if necessary.
118 */
119static void gru_load_kernel_context(struct gru_blade_state *bs, int blade_id)
120{
121 struct gru_state *gru;
122 struct gru_thread_state *kgts;
123 void *vaddr;
124 int ctxnum;
125
126 up_read(&bs->bs_kgts_sema);
127 down_write(&bs->bs_kgts_sema);
128
129 if (!bs->bs_kgts)
130 gru_alloc_kernel_context(bs, blade_id);
131 kgts = bs->bs_kgts;
132
133 if (!kgts->ts_gru) {
134 STAT(load_kernel_context);
135 while (!gru_assign_gru_context(kgts, blade_id)) {
136 msleep(1);
137 gru_steal_context(kgts, blade_id);
138 }
139 gru_load_context(kgts);
140 gru = bs->bs_kgts->ts_gru;
141 vaddr = gru->gs_gru_base_vaddr;
142 ctxnum = kgts->ts_ctxnum;
143 bs->kernel_cb = get_gseg_base_address_cb(vaddr, ctxnum, 0);
144 bs->kernel_dsr = get_gseg_base_address_ds(vaddr, ctxnum, 0);
145 }
146 downgrade_write(&bs->bs_kgts_sema);
147}
148
149/*
150 * Lock & load the kernel context for the specified blade.
151 */
152static struct gru_blade_state *gru_lock_kernel_context(int blade_id)
153{
154 struct gru_blade_state *bs;
155
156 STAT(lock_kernel_context);
157 bs = gru_base[blade_id];
158
159 down_read(&bs->bs_kgts_sema);
160 if (!bs->bs_kgts || !bs->bs_kgts->ts_gru)
161 gru_load_kernel_context(bs, blade_id);
162 return bs;
163
164}
165
166/*
167 * Unlock the kernel context for the specified blade. Context is not
168 * unloaded but may be stolen before next use.
169 */
170static void gru_unlock_kernel_context(int blade_id)
171{
172 struct gru_blade_state *bs;
173
174 bs = gru_base[blade_id];
175 up_read(&bs->bs_kgts_sema);
176 STAT(unlock_kernel_context);
177}
178
179/*
180 * Reserve & get pointers to the DSR/CBRs reserved for the current cpu.
181 * - returns with preemption disabled
182 */
101static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr) 183static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
102{ 184{
103 struct gru_blade_state *bs; 185 struct gru_blade_state *bs;
@@ -105,18 +187,23 @@ static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
105 187
106 BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES); 188 BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
107 preempt_disable(); 189 preempt_disable();
108 bs = gru_base[uv_numa_blade_id()]; 190 bs = gru_lock_kernel_context(uv_numa_blade_id());
109 lcpu = uv_blade_processor_id(); 191 lcpu = uv_blade_processor_id();
110 *cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE; 192 *cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
111 *dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES; 193 *dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES;
112 return 0; 194 return 0;
113} 195}
114 196
197/*
198 * Free the current cpus reserved DSR/CBR resources.
199 */
115static void gru_free_cpu_resources(void *cb, void *dsr) 200static void gru_free_cpu_resources(void *cb, void *dsr)
116{ 201{
202 gru_unlock_kernel_context(uv_numa_blade_id());
117 preempt_enable(); 203 preempt_enable();
118} 204}
119 205
206/*----------------------------------------------------------------------*/
120int gru_get_cb_exception_detail(void *cb, 207int gru_get_cb_exception_detail(void *cb,
121 struct control_block_extended_exc_detail *excdet) 208 struct control_block_extended_exc_detail *excdet)
122{ 209{
@@ -597,34 +684,36 @@ EXPORT_SYMBOL_GPL(gru_copy_gpa);
597 684
598/* ------------------- KERNEL QUICKTESTS RUN AT STARTUP ----------------*/ 685/* ------------------- KERNEL QUICKTESTS RUN AT STARTUP ----------------*/
599/* Temp - will delete after we gain confidence in the GRU */ 686/* Temp - will delete after we gain confidence in the GRU */
600static __cacheline_aligned unsigned long word0;
601static __cacheline_aligned unsigned long word1;
602 687
603static int quicktest(struct gru_state *gru) 688int quicktest(void)
604{ 689{
690 unsigned long word0;
691 unsigned long word1;
605 void *cb; 692 void *cb;
606 void *ds; 693 void *dsr;
607 unsigned long *p; 694 unsigned long *p;
608 695
609 cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0); 696 if (gru_get_cpu_resources(GRU_CACHE_LINE_BYTES, &cb, &dsr))
610 ds = get_gseg_base_address_ds(gru->gs_gru_base_vaddr, KERNEL_CTXNUM, 0); 697 return MQE_BUG_NO_RESOURCES;
611 p = ds; 698 p = dsr;
612 word0 = MAGIC; 699 word0 = MAGIC;
700 word1 = 0;
613 701
614 gru_vload(cb, uv_gpa(&word0), 0, XTYPE_DW, 1, 1, IMA); 702 gru_vload(cb, uv_gpa(&word0), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
615 if (gru_wait(cb) != CBS_IDLE) 703 if (gru_wait(cb) != CBS_IDLE)
616 BUG(); 704 BUG();
617 705
618 if (*(unsigned long *)ds != MAGIC) 706 if (*p != MAGIC)
619 BUG(); 707 BUG();
620 gru_vstore(cb, uv_gpa(&word1), 0, XTYPE_DW, 1, 1, IMA); 708 gru_vstore(cb, uv_gpa(&word1), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
621 if (gru_wait(cb) != CBS_IDLE) 709 if (gru_wait(cb) != CBS_IDLE)
622 BUG(); 710 BUG();
711 gru_free_cpu_resources(cb, dsr);
623 712
624 if (word0 != word1 || word0 != MAGIC) { 713 if (word0 != word1 || word1 != MAGIC) {
625 printk 714 printk
626 ("GRU quicktest err: gid %d, found 0x%lx, expected 0x%lx\n", 715 ("GRU quicktest err: found 0x%lx, expected 0x%lx\n",
627 gru->gs_gid, word1, MAGIC); 716 word1, MAGIC);
628 BUG(); /* ZZZ should not be fatal */ 717 BUG(); /* ZZZ should not be fatal */
629 } 718 }
630 719
@@ -635,80 +724,30 @@ static int quicktest(struct gru_state *gru)
635int gru_kservices_init(struct gru_state *gru) 724int gru_kservices_init(struct gru_state *gru)
636{ 725{
637 struct gru_blade_state *bs; 726 struct gru_blade_state *bs;
638 struct gru_context_configuration_handle *cch; 727
639 unsigned long cbr_map, dsr_map;
640 int err, num, cpus_possible;
641
642 /*
643 * Currently, resources are reserved ONLY on the second chiplet
644 * on each blade. This leaves ALL resources on chiplet 0 available
645 * for user code.
646 */
647 bs = gru->gs_blade; 728 bs = gru->gs_blade;
648 if (gru != &bs->bs_grus[1]) 729 if (gru != &bs->bs_grus[0])
649 return 0; 730 return 0;
650 731
651 cpus_possible = uv_blade_nr_possible_cpus(gru->gs_blade_id); 732 init_rwsem(&bs->bs_kgts_sema);
652
653 num = GRU_NUM_KERNEL_CBR * cpus_possible;
654 cbr_map = gru_reserve_cb_resources(gru, GRU_CB_COUNT_TO_AU(num), NULL);
655 gru->gs_reserved_cbrs += num;
656
657 num = GRU_NUM_KERNEL_DSR_BYTES * cpus_possible;
658 dsr_map = gru_reserve_ds_resources(gru, GRU_DS_BYTES_TO_AU(num), NULL);
659 gru->gs_reserved_dsr_bytes += num;
660
661 gru->gs_active_contexts++;
662 __set_bit(KERNEL_CTXNUM, &gru->gs_context_map);
663 cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM);
664
665 bs->kernel_cb = get_gseg_base_address_cb(gru->gs_gru_base_vaddr,
666 KERNEL_CTXNUM, 0);
667 bs->kernel_dsr = get_gseg_base_address_ds(gru->gs_gru_base_vaddr,
668 KERNEL_CTXNUM, 0);
669
670 lock_cch_handle(cch);
671 cch->tfm_fault_bit_enable = 0;
672 cch->tlb_int_enable = 0;
673 cch->tfm_done_bit_enable = 0;
674 cch->unmap_enable = 1;
675 cch->dsr_allocation_map = dsr_map;
676 cch->cbr_allocation_map = cbr_map;
677
678 err = cch_allocate(cch);
679 if (err) {
680 gru_dbg(grudev,
681 "Unable to allocate kernel CCH: gid %d, err %d\n",
682 gru->gs_gid, err);
683 BUG();
684 }
685 if (cch_start(cch)) {
686 gru_dbg(grudev, "Unable to start kernel CCH: gid %d, err %d\n",
687 gru->gs_gid, err);
688 BUG();
689 }
690 unlock_cch_handle(cch);
691 733
692 if (gru_options & GRU_QUICKLOOK) 734 if (gru_options & GRU_QUICKLOOK)
693 quicktest(gru); 735 quicktest();
694 return 0; 736 return 0;
695} 737}
696 738
697void gru_kservices_exit(struct gru_state *gru) 739void gru_kservices_exit(struct gru_state *gru)
698{ 740{
699 struct gru_context_configuration_handle *cch;
700 struct gru_blade_state *bs; 741 struct gru_blade_state *bs;
742 struct gru_thread_state *kgts;
701 743
702 bs = gru->gs_blade; 744 bs = gru->gs_blade;
703 if (gru != &bs->bs_grus[1]) 745 if (gru != &bs->bs_grus[0])
704 return; 746 return;
705 747
706 cch = get_cch(gru->gs_gru_base_vaddr, KERNEL_CTXNUM); 748 kgts = bs->bs_kgts;
707 lock_cch_handle(cch); 749 if (kgts && kgts->ts_gru)
708 if (cch_interrupt_sync(cch)) 750 gru_unload_context(kgts, 0);
709 BUG(); 751 kfree(kgts);
710 if (cch_deallocate(cch))
711 BUG();
712 unlock_cch_handle(cch);
713} 752}
714 753