aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2012-07-04 16:37:11 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-07-11 00:18:40 -0400
commit18ad51dd342a7eb09dbcd059d0b451b616d4dafc (patch)
tree94809605669eb3b5e4e049501958a2fa93ae2de7 /arch/powerpc
parente6a74c6ea331b79c86e1898c504790b3dadc591d (diff)
powerpc: Add VDSO version of getcpu
We have a request for a fast method of getting CPU and NUMA node IDs from userspace. This patch implements a getcpu VDSO function, similar to x86. Ben suggested we use SPRG3 which is userspace readable. SPRG3 can be modified by a KVM guest, so we save the SPRG3 value in the paca and restore it when transitioning from the guest to the host. I have a glibc patch that implements sched_getcpu on top of this. Testing on a POWER7: baseline: 538 cycles vdso: 30 cycles Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_asm.h1
-rw-r--r--arch/powerpc/include/asm/reg.h5
-rw-r--r--arch/powerpc/include/asm/vdso.h2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/smp.c3
-rw-r--r--arch/powerpc/kernel/vdso.c28
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile4
-rw-r--r--arch/powerpc/kernel/vdso32/getcpu.S45
-rw-r--r--arch/powerpc/kernel/vdso32/vdso32.lds.S3
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile2
-rw-r--r--arch/powerpc/kernel/vdso64/getcpu.S45
-rw-r--r--arch/powerpc/kernel/vdso64/vdso64.lds.S1
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S4
13 files changed, 140 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index 88609b23b775..bfcd00c1485d 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -74,6 +74,7 @@ struct kvmppc_host_state {
74 ulong vmhandler; 74 ulong vmhandler;
75 ulong scratch0; 75 ulong scratch0;
76 ulong scratch1; 76 ulong scratch1;
77 ulong sprg3;
77 u8 in_guest; 78 u8 in_guest;
78 u8 restore_hid5; 79 u8 restore_hid5;
79 u8 napping; 80 u8 napping;
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index f0cb7f461b9d..2baeb7c8764f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -491,6 +491,7 @@
491#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ 491#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
492#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */ 492#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
493#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */ 493#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
494#define SPRN_USPRG3 0x103 /* SPRG3 userspace read */
494#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */ 495#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
495#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */ 496#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
496#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */ 497#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
@@ -753,14 +754,14 @@
753 * 64-bit server: 754 * 64-bit server:
754 * - SPRG0 unused (reserved for HV on Power4) 755 * - SPRG0 unused (reserved for HV on Power4)
755 * - SPRG2 scratch for exception vectors 756 * - SPRG2 scratch for exception vectors
756 * - SPRG3 unused (user visible) 757 * - SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
757 * - HSPRG0 stores PACA in HV mode 758 * - HSPRG0 stores PACA in HV mode
758 * - HSPRG1 scratch for "HV" exceptions 759 * - HSPRG1 scratch for "HV" exceptions
759 * 760 *
760 * 64-bit embedded 761 * 64-bit embedded
761 * - SPRG0 generic exception scratch 762 * - SPRG0 generic exception scratch
762 * - SPRG2 TLB exception stack 763 * - SPRG2 TLB exception stack
763 * - SPRG3 unused (user visible) 764 * - SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
764 * - SPRG4 unused (user visible) 765 * - SPRG4 unused (user visible)
765 * - SPRG6 TLB miss scratch (user visible, sorry !) 766 * - SPRG6 TLB miss scratch (user visible, sorry !)
766 * - SPRG7 critical exception scratch 767 * - SPRG7 critical exception scratch
diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h
index dc0419b66f17..50f261bc3e95 100644
--- a/arch/powerpc/include/asm/vdso.h
+++ b/arch/powerpc/include/asm/vdso.h
@@ -22,6 +22,8 @@ extern unsigned long vdso64_rt_sigtramp;
22extern unsigned long vdso32_sigtramp; 22extern unsigned long vdso32_sigtramp;
23extern unsigned long vdso32_rt_sigtramp; 23extern unsigned long vdso32_rt_sigtramp;
24 24
25int __cpuinit vdso_getcpu_init(void);
26
25#else /* __ASSEMBLY__ */ 27#else /* __ASSEMBLY__ */
26 28
27#ifdef __VDSO64__ 29#ifdef __VDSO64__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 52c7ad78242e..85b05c463fae 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -533,6 +533,7 @@ int main(void)
533 HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler); 533 HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
534 HSTATE_FIELD(HSTATE_SCRATCH0, scratch0); 534 HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
535 HSTATE_FIELD(HSTATE_SCRATCH1, scratch1); 535 HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
536 HSTATE_FIELD(HSTATE_SPRG3, sprg3);
536 HSTATE_FIELD(HSTATE_IN_GUEST, in_guest); 537 HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
537 HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5); 538 HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
538 HSTATE_FIELD(HSTATE_NAPPING, napping); 539 HSTATE_FIELD(HSTATE_NAPPING, napping);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e1417c42155c..0321007086f7 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -48,6 +48,7 @@
48#ifdef CONFIG_PPC64 48#ifdef CONFIG_PPC64
49#include <asm/paca.h> 49#include <asm/paca.h>
50#endif 50#endif
51#include <asm/vdso.h>
51#include <asm/debug.h> 52#include <asm/debug.h>
52 53
53#ifdef DEBUG 54#ifdef DEBUG
@@ -570,6 +571,8 @@ void __devinit start_secondary(void *unused)
570#ifdef CONFIG_PPC64 571#ifdef CONFIG_PPC64
571 if (system_state == SYSTEM_RUNNING) 572 if (system_state == SYSTEM_RUNNING)
572 vdso_data->processorCount++; 573 vdso_data->processorCount++;
574
575 vdso_getcpu_init();
573#endif 576#endif
574 notify_cpu_starting(cpu); 577 notify_cpu_starting(cpu);
575 set_cpu_online(cpu, true); 578 set_cpu_online(cpu, true);
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 9eb5b9b536a7..b67db22e102d 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -706,6 +706,34 @@ static void __init vdso_setup_syscall_map(void)
706 } 706 }
707} 707}
708 708
709#ifdef CONFIG_PPC64
710int __cpuinit vdso_getcpu_init(void)
711{
712 unsigned long cpu, node, val;
713
714 /*
715 * SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in
716 * the next 16 bits. The VDSO uses this to implement getcpu().
717 */
718 cpu = get_cpu();
719 WARN_ON_ONCE(cpu > 0xffff);
720
721 node = cpu_to_node(cpu);
722 WARN_ON_ONCE(node > 0xffff);
723
724 val = (cpu & 0xfff) | ((node & 0xffff) << 16);
725 mtspr(SPRN_SPRG3, val);
726#ifdef CONFIG_KVM_BOOK3S_HANDLER
727 get_paca()->kvm_hstate.sprg3 = val;
728#endif
729
730 put_cpu();
731
732 return 0;
733}
734/* We need to call this before SMP init */
735early_initcall(vdso_getcpu_init);
736#endif
709 737
710static int __init vdso_init(void) 738static int __init vdso_init(void)
711{ 739{
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 9a7946c41738..53e6c9b979ec 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -1,7 +1,9 @@
1 1
2# List of files in the vdso, has to be asm only for now 2# List of files in the vdso, has to be asm only for now
3 3
4obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o 4obj-vdso32-$(CONFIG_PPC64) = getcpu.o
5obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o \
6 $(obj-vdso32-y)
5 7
6# Build rules 8# Build rules
7 9
diff --git a/arch/powerpc/kernel/vdso32/getcpu.S b/arch/powerpc/kernel/vdso32/getcpu.S
new file mode 100644
index 000000000000..47afd08c90f7
--- /dev/null
+++ b/arch/powerpc/kernel/vdso32/getcpu.S
@@ -0,0 +1,45 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) IBM Corporation, 2012
17 *
18 * Author: Anton Blanchard <anton@au.ibm.com>
19 */
20#include <asm/ppc_asm.h>
21#include <asm/vdso.h>
22
23 .text
24/*
25 * Exact prototype of getcpu
26 *
27 * int __kernel_getcpu(unsigned *cpu, unsigned *node);
28 *
29 */
30V_FUNCTION_BEGIN(__kernel_getcpu)
31 .cfi_startproc
32 mfspr r5,SPRN_USPRG3
33 cmpdi cr0,r3,0
34 cmpdi cr1,r4,0
35 clrlwi r6,r5,16
36 rlwinm r7,r5,16,31-15,31-0
37 beq cr0,1f
38 stw r6,0(r3)
391: beq cr1,2f
40 stw r7,0(r4)
412: crclr cr0*4+so
42 li r3,0 /* always success */
43 blr
44 .cfi_endproc
45V_FUNCTION_END(__kernel_getcpu)
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index 0546bcd49cd0..43200ba2e570 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -147,6 +147,9 @@ VERSION
147 __kernel_sync_dicache_p5; 147 __kernel_sync_dicache_p5;
148 __kernel_sigtramp32; 148 __kernel_sigtramp32;
149 __kernel_sigtramp_rt32; 149 __kernel_sigtramp_rt32;
150#ifdef CONFIG_PPC64
151 __kernel_getcpu;
152#endif
150 153
151 local: *; 154 local: *;
152 }; 155 };
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index 8c500d8622e4..effca9404b17 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -1,6 +1,6 @@
1# List of files in the vdso, has to be asm only for now 1# List of files in the vdso, has to be asm only for now
2 2
3obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o 3obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
4 4
5# Build rules 5# Build rules
6 6
diff --git a/arch/powerpc/kernel/vdso64/getcpu.S b/arch/powerpc/kernel/vdso64/getcpu.S
new file mode 100644
index 000000000000..47afd08c90f7
--- /dev/null
+++ b/arch/powerpc/kernel/vdso64/getcpu.S
@@ -0,0 +1,45 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) IBM Corporation, 2012
17 *
18 * Author: Anton Blanchard <anton@au.ibm.com>
19 */
20#include <asm/ppc_asm.h>
21#include <asm/vdso.h>
22
23 .text
24/*
25 * Exact prototype of getcpu
26 *
27 * int __kernel_getcpu(unsigned *cpu, unsigned *node);
28 *
29 */
30V_FUNCTION_BEGIN(__kernel_getcpu)
31 .cfi_startproc
32 mfspr r5,SPRN_USPRG3
33 cmpdi cr0,r3,0
34 cmpdi cr1,r4,0
35 clrlwi r6,r5,16
36 rlwinm r7,r5,16,31-15,31-0
37 beq cr0,1f
38 stw r6,0(r3)
391: beq cr1,2f
40 stw r7,0(r4)
412: crclr cr0*4+so
42 li r3,0 /* always success */
43 blr
44 .cfi_endproc
45V_FUNCTION_END(__kernel_getcpu)
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 0e615404e247..e6c1758f3588 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -146,6 +146,7 @@ VERSION
146 __kernel_sync_dicache; 146 __kernel_sync_dicache;
147 __kernel_sync_dicache_p5; 147 __kernel_sync_dicache_p5;
148 __kernel_sigtramp_rt64; 148 __kernel_sigtramp_rt64;
149 __kernel_getcpu;
149 150
150 local: *; 151 local: *;
151 }; 152 };
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index e764e2361d47..5a84c8d3d040 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1064,6 +1064,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
1064 mtspr SPRN_DABR,r5 1064 mtspr SPRN_DABR,r5
1065 mtspr SPRN_DABRX,r6 1065 mtspr SPRN_DABRX,r6
1066 1066
1067 /* Restore SPRG3 */
1068 ld r3,HSTATE_SPRG3(r13)
1069 mtspr SPRN_SPRG3,r3
1070
1067 /* 1071 /*
1068 * Reload DEC. HDEC interrupts were disabled when 1072 * Reload DEC. HDEC interrupts were disabled when
1069 * we reloaded the host's LPCR value. 1073 * we reloaded the host's LPCR value.