ChangeSet 1.2226.2.1, 2005/04/01 14:35:01-08:00, [EMAIL PROTECTED]

        [SPARC64]: Store per-cpu pointer in IMMU TSB register.
        
        This trick requires that we PAGE_SIZE align the per-cpu
        areas, but that is fine.  Also, reduce the __per_cpu_offsets[]
        array into just two values, a base and a shift.
        
        Signed-off-by: David S. Miller <[EMAIL PROTECTED]>



 arch/sparc64/kernel/etrap.S       |   14 ++------
 arch/sparc64/kernel/head.S        |    2 +
 arch/sparc64/kernel/rtrap.S       |    6 ++-
 arch/sparc64/kernel/smp.c         |   60 +++++++++++++++++++++++++++++++++-----
 arch/sparc64/kernel/vmlinux.lds.S |    2 -
 arch/sparc64/kernel/winfixup.S    |   21 +++----------
 include/asm-sparc64/percpu.h      |   12 +++++--
 7 files changed, 78 insertions(+), 39 deletions(-)


diff -Nru a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
--- a/arch/sparc64/kernel/etrap.S       2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/etrap.S       2005-04-03 21:22:20 -07:00
@@ -103,11 +103,8 @@
                wrpr    %g0, ETRAP_PSTATE2, %pstate
                mov     %l6, %g6
 #ifdef CONFIG_SMP
-               ldub    [%g6 + TI_CPU], %g3
-               sethi   %hi(__per_cpu_offset), %g2
-               or      %g2, %lo(__per_cpu_offset), %g2
-               sllx    %g3, 3, %g3
-               ldx     [%g2 + %g3], %g5
+               mov     TSB_REG, %g3
+               ldxa    [%g3] ASI_IMMU, %g5
 #endif
                jmpl    %l2 + 0x4, %g0
                 ldx    [%g6 + TI_TASK], %g4
@@ -259,11 +256,8 @@
                mov     %l6, %g6
                stx     %i7, [%sp + PTREGS_OFF + PT_V9_I7]
 #ifdef CONFIG_SMP
-               ldub    [%g6 + TI_CPU], %g3
-               sethi   %hi(__per_cpu_offset), %g2
-               or      %g2, %lo(__per_cpu_offset), %g2
-               sllx    %g3, 3, %g3
-               ldx     [%g2 + %g3], %g5
+               mov     TSB_REG, %g3
+               ldxa    [%g3] ASI_IMMU, %g5
 #endif
                ldx     [%g6 + TI_TASK], %g4
                done
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S        2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/head.S        2005-04-03 21:22:20 -07:00
@@ -657,6 +657,8 @@
        mov     TSB_REG, %g1
        stxa    %g0, [%g1] ASI_DMMU
        membar  #Sync
+       stxa    %g0, [%g1] ASI_IMMU
+       membar  #Sync
        mov     TLB_SFSR, %g1
        sethi   %uhi(KERN_HIGHBITS), %g2
        or      %g2, %ulo(KERN_HIGHBITS), %g2
diff -Nru a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
--- a/arch/sparc64/kernel/rtrap.S       2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/rtrap.S       2005-04-03 21:22:20 -07:00
@@ -222,8 +222,10 @@
 
                ldx                     [%sp + PTREGS_OFF + PT_V9_G3], %g3
                ldx                     [%sp + PTREGS_OFF + PT_V9_G4], %g4
-               brz,a,pn                %l3, 1f
-                ldx                    [%sp + PTREGS_OFF + PT_V9_G5], %g5
+               ldx                     [%sp + PTREGS_OFF + PT_V9_G5], %g5
+               mov                     TSB_REG, %g6
+               brnz,a,pn               %l3, 1f
+                ldxa                   [%g6] ASI_IMMU, %g5
 1:             ldx                     [%sp + PTREGS_OFF + PT_V9_G6], %g6
                ldx                     [%sp + PTREGS_OFF + PT_V9_G7], %g7
                wrpr                    %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c 2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/smp.c 2005-04-03 21:22:20 -07:00
@@ -3,6 +3,7 @@
  * Copyright (C) 1997 David S. Miller ([EMAIL PROTECTED])
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -20,6 +21,7 @@
 #include <linux/cache.h>
 #include <linux/jiffies.h>
 #include <linux/profile.h>
+#include <linux/bootmem.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -99,6 +101,16 @@
 
 extern void inherit_locked_prom_mappings(int save_p);
 
+static inline void cpu_setup_percpu_base(unsigned long cpu_id)
+{
+       __asm__ __volatile__("mov       %0, %%g5\n\t"
+                            "stxa      %0, [%1] %2\n\t"
+                            "membar    #Sync"
+                            : /* no outputs */
+                            : "r" (__per_cpu_offset(cpu_id)),
+                              "r" (TSB_REG), "i" (ASI_IMMU));
+}
+
 void __init smp_callin(void)
 {
        int cpuid = hard_smp_processor_id();
@@ -107,9 +119,7 @@
 
        __flush_tlb_all();
 
-       __asm__ __volatile__("mov %0, %%g5\n\t"
-                            : /* no outputs */
-                            : "r" (__per_cpu_offset[cpuid]));
+       cpu_setup_percpu_base(cpuid);
 
        smp_setup_percpu_timer();
 
@@ -1120,10 +1130,6 @@
 
        current_thread_info()->cpu = hard_smp_processor_id();
 
-       __asm__ __volatile__("mov %0, %%g5\n\t"
-                            : /* no outputs */
-                            : "r" (__per_cpu_offset[smp_processor_id()]));
-
        cpu_set(smp_processor_id(), cpu_online_map);
        cpu_set(smp_processor_id(), phys_cpu_present_map);
 }
@@ -1184,3 +1190,43 @@
 {
 }
 
+unsigned long __per_cpu_base;
+unsigned long __per_cpu_shift;
+
+EXPORT_SYMBOL(__per_cpu_base);
+EXPORT_SYMBOL(__per_cpu_shift);
+
+void __init setup_per_cpu_areas(void)
+{
+       unsigned long goal, size, i;
+       char *ptr;
+       /* Created by linker magic */
+       extern char __per_cpu_start[], __per_cpu_end[];
+
+       /* Copy section for each CPU (we discard the original) */
+       goal = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE);
+
+#ifdef CONFIG_MODULES
+       if (goal < PERCPU_ENOUGH_ROOM)
+               goal = PERCPU_ENOUGH_ROOM;
+#endif
+       __per_cpu_shift = 0;
+       for (size = 1UL; size < goal; size <<= 1UL)
+               __per_cpu_shift++;
+
+       ptr = alloc_bootmem_pages(size * NR_CPUS);
+
+       __per_cpu_base = ptr - __per_cpu_start;
+
+       for (i = 0; i < NR_CPUS; i++, ptr += size)
+               memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+
+       /* Finally, load in the boot cpu's base value.
+        * We abuse the IMMU TSB register for trap handler
+        * entry and exit loading of %g5.  That is why it
+        * has to be page aligned.
+        */
+       BUG_ON((__per_cpu_shift < PAGE_SHIFT) ||
+              (__per_cpu_base & ~PAGE_MASK));
+       cpu_setup_percpu_base(hard_smp_processor_id());
+}
diff -Nru a/arch/sparc64/kernel/vmlinux.lds.S 
b/arch/sparc64/kernel/vmlinux.lds.S
--- a/arch/sparc64/kernel/vmlinux.lds.S 2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/vmlinux.lds.S 2005-04-03 21:22:20 -07:00
@@ -72,7 +72,7 @@
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
-  . = ALIGN(32);
+  . = ALIGN(8192);
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
diff -Nru a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
--- a/arch/sparc64/kernel/winfixup.S    2005-04-03 21:22:20 -07:00
+++ b/arch/sparc64/kernel/winfixup.S    2005-04-03 21:22:20 -07:00
@@ -94,11 +94,8 @@
        mov             %o7, %g6
        ldx             [%g6 + TI_TASK], %g4
 #ifdef CONFIG_SMP
-       ldub            [%g6 + TI_CPU], %g1
-       sethi           %hi(__per_cpu_offset), %g2
-       or              %g2, %lo(__per_cpu_offset), %g2
-       sllx            %g1, 3, %g1
-       ldx             [%g2 + %g1], %g5
+       mov             TSB_REG, %g1
+       ldxa            [%g1] ASI_IMMU, %g5
 #endif
 
        /* This is the same as below, except we handle this a bit special
@@ -221,11 +218,8 @@
        mov             %o7, %g6                        ! Get current back.
        ldx             [%g6 + TI_TASK], %g4            ! Finish it.
 #ifdef CONFIG_SMP
-       ldub            [%g6 + TI_CPU], %g1
-       sethi           %hi(__per_cpu_offset), %g2
-       or              %g2, %lo(__per_cpu_offset), %g2
-       sllx            %g1, 3, %g1
-       ldx             [%g2 + %g1], %g5
+       mov             TSB_REG, %g1
+       ldxa            [%g1] ASI_IMMU, %g5
 #endif
        call            mem_address_unaligned
         add            %sp, PTREGS_OFF, %o0
@@ -333,11 +327,8 @@
        mov             %o7, %g6                        ! Get current back.
        ldx             [%g6 + TI_TASK], %g4            ! Finish it.
 #ifdef CONFIG_SMP
-       ldub            [%g6 + TI_CPU], %g1
-       sethi           %hi(__per_cpu_offset), %g2
-       or              %g2, %lo(__per_cpu_offset), %g2
-       sllx            %g1, 3, %g1
-       ldx             [%g2 + %g1], %g5
+       mov             TSB_REG, %g1
+       ldxa            [%g1] ASI_IMMU, %g5
 #endif
        call            data_access_exception
         add            %sp, PTREGS_OFF, %o0
diff -Nru a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
--- a/include/asm-sparc64/percpu.h      2005-04-03 21:22:20 -07:00
+++ b/include/asm-sparc64/percpu.h      2005-04-03 21:22:20 -07:00
@@ -3,10 +3,14 @@
 
 #include <linux/compiler.h>
 
-#define __GENERIC_PER_CPU
 #ifdef CONFIG_SMP
 
-extern unsigned long __per_cpu_offset[NR_CPUS];
+extern void setup_per_cpu_areas(void);
+
+extern unsigned long __per_cpu_base;
+extern unsigned long __per_cpu_shift;
+#define __per_cpu_offset(__cpu) \
+       (__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
 
 /* Separate out the type, so (int[3], foo) works. */
 #define DEFINE_PER_CPU(type, name) \
@@ -15,7 +19,7 @@
 register unsigned long __local_per_cpu_offset asm("g5");
 
 /* var is in discarded region: offset to particular copy we want */
-#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
+#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, 
__local_per_cpu_offset))
 
 /* A macro to avoid #include hell... */
@@ -24,7 +28,7 @@
        unsigned int __i;                                       \
        for (__i = 0; __i < NR_CPUS; __i++)                     \
                if (cpu_possible(__i))                          \
-                       memcpy((pcpudst)+__per_cpu_offset[__i], \
+                       memcpy((pcpudst)+__per_cpu_offset(__i), \
                               (src), (size));                  \
 } while (0)
 #else /* ! SMP */
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to