X86: uv: implement a gru_read_gpa kernel function
authorRobin Holt <holt@sgi.com>
Wed, 16 Dec 2009 00:47:55 +0000 (16:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2009 15:20:13 +0000 (07:20 -0800)
The BIOS has decided to store a pointer to the partition reserved page in
a scratch MMR.  The GRU is only able to read an MMR using a vload
instruction.  The gru_read_gpa() function will implemented.

Signed-off-by: Robin Holt <holt@sgi.com>
Signed-off-by: Jack Steiner <steiner@sgi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/misc/sgi-gru/gru_instructions.h
drivers/misc/sgi-gru/grukservices.c
drivers/misc/sgi-gru/grukservices.h
drivers/misc/sgi-gru/gruprocfs.c
drivers/misc/sgi-gru/grutables.h

index 3c9c066..e033b6c 100644 (file)
@@ -340,6 +340,19 @@ static inline void gru_start_instruction(struct gru_instruction *ins, int op32)
  *             - nelem and stride are in elements
  *             - tri0/tri1 is in bytes for the beginning of the data segment.
  */
+static inline void gru_vload_phys(void *cb, unsigned long gpa,
+               unsigned int tri0, int iaa, unsigned long hints)
+{
+       struct gru_instruction *ins = (struct gru_instruction *)cb;
+
+       ins->baddr0 = (long)gpa | ((unsigned long)iaa << 62);
+       ins->nelem = 1;
+       ins->tri0 = tri0;
+       ins->op1_stride = 1;
+       gru_start_instruction(ins, __opword(OP_VLOAD, 0, XTYPE_DW, iaa, 0,
+                                       CB_IMA(hints)));
+}
+
 static inline void gru_vload(void *cb, unsigned long mem_addr,
                unsigned int tri0, unsigned char xtype, unsigned long nelem,
                unsigned long stride, unsigned long hints)
index 766e21e..d2b149f 100644 (file)
@@ -858,6 +858,29 @@ EXPORT_SYMBOL_GPL(gru_get_next_message);
 /* ---------------------- GRU DATA COPY FUNCTIONS ---------------------------*/
 
 /*
+ * Load a DW from a global GPA. The GPA can be a memory or MMR address.
+ */
+int gru_read_gpa(unsigned long *value, unsigned long gpa)
+{
+       void *cb;
+       void *dsr;
+       int ret, iaa;
+
+       STAT(read_gpa);
+       if (gru_get_cpu_resources(GRU_NUM_KERNEL_DSR_BYTES, &cb, &dsr))
+               return MQE_BUG_NO_RESOURCES;
+       iaa = gpa >> 62;
+       gru_vload_phys(cb, gpa, gru_get_tri(dsr), iaa, IMA);
+       ret = gru_wait(cb);
+       if (ret == CBS_IDLE)
+               *value = *(unsigned long *)dsr;
+       gru_free_cpu_resources(cb, dsr);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(gru_read_gpa);
+
+
+/*
  * Copy a block of data using the GRU resources
  */
 int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa,
index d60d34b..02aa94d 100644 (file)
@@ -131,6 +131,20 @@ extern void *gru_get_next_message(struct gru_message_queue_desc *mqd);
 
 
 /*
+ * Read a GRU global GPA. Source can be located in a remote partition.
+ *
+ *    Input:
+ *     value           memory address where MMR value is returned
+ *     gpa             source numalink physical address of GPA
+ *
+ *    Output:
+ *     0               OK
+ *     >0              error
+ */
+int gru_read_gpa(unsigned long *value, unsigned long gpa);
+
+
+/*
  * Copy data using the GRU. Source or destination can be located in a remote
  * partition.
  *
index 3f2375c..cf6b3e3 100644 (file)
@@ -98,6 +98,7 @@ static int statistics_show(struct seq_file *s, void *p)
        printstat(s, flush_tlb_gru_tgh);
        printstat(s, flush_tlb_gru_zero_asid);
        printstat(s, copy_gpa);
+       printstat(s, read_gpa);
        printstat(s, mesq_receive);
        printstat(s, mesq_receive_none);
        printstat(s, mesq_send);
index 46990bc..f7b553a 100644 (file)
@@ -224,6 +224,7 @@ struct gru_stats_s {
        atomic_long_t flush_tlb_gru_zero_asid;
 
        atomic_long_t copy_gpa;
+       atomic_long_t read_gpa;
 
        atomic_long_t mesq_receive;
        atomic_long_t mesq_receive_none;