aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/include/asm/parport.h2
-rw-r--r--arch/sparc/include/asm/thread_info_64.h4
-rw-r--r--arch/sparc/include/asm/vdso.h6
-rw-r--r--arch/sparc/kernel/time_64.c3
-rw-r--r--arch/sparc/vdso/Makefile33
-rw-r--r--arch/sparc/vdso/checkundef.sh10
-rw-r--r--arch/sparc/vdso/vclock_gettime.c102
-rw-r--r--arch/sparc/vdso/vdso-layout.lds.S7
-rw-r--r--arch/sparc/vdso/vdso2c.c6
-rw-r--r--arch/sparc/vdso/vdso2c.h18
-rw-r--r--arch/sparc/vdso/vma.c39
11 files changed, 123 insertions, 107 deletions
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
index 05df5f043053..3c5a1c620f0f 100644
--- a/arch/sparc/include/asm/parport.h
+++ b/arch/sparc/include/asm/parport.h
@@ -21,6 +21,7 @@
21 */ 21 */
22#define HAS_DMA 22#define HAS_DMA
23 23
24#ifdef CONFIG_PARPORT_PC_FIFO
24static DEFINE_SPINLOCK(dma_spin_lock); 25static DEFINE_SPINLOCK(dma_spin_lock);
25 26
26#define claim_dma_lock() \ 27#define claim_dma_lock() \
@@ -31,6 +32,7 @@ static DEFINE_SPINLOCK(dma_spin_lock);
31 32
32#define release_dma_lock(__flags) \ 33#define release_dma_lock(__flags) \
33 spin_unlock_irqrestore(&dma_spin_lock, __flags); 34 spin_unlock_irqrestore(&dma_spin_lock, __flags);
35#endif
34 36
35static struct sparc_ebus_info { 37static struct sparc_ebus_info {
36 struct ebus_dma_info info; 38 struct ebus_dma_info info;
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 7fb676360928..20255471e653 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -121,8 +121,12 @@ struct thread_info {
121} 121}
122 122
123/* how to get the thread information struct from C */ 123/* how to get the thread information struct from C */
124#ifndef BUILD_VDSO
124register struct thread_info *current_thread_info_reg asm("g6"); 125register struct thread_info *current_thread_info_reg asm("g6");
125#define current_thread_info() (current_thread_info_reg) 126#define current_thread_info() (current_thread_info_reg)
127#else
128extern struct thread_info *current_thread_info(void);
129#endif
126 130
127/* thread information allocation */ 131/* thread information allocation */
128#if PAGE_SHIFT == 13 132#if PAGE_SHIFT == 13
diff --git a/arch/sparc/include/asm/vdso.h b/arch/sparc/include/asm/vdso.h
index 93b628731a5e..56836eb01787 100644
--- a/arch/sparc/include/asm/vdso.h
+++ b/arch/sparc/include/asm/vdso.h
@@ -8,10 +8,10 @@
8struct vdso_image { 8struct vdso_image {
9 void *data; 9 void *data;
10 unsigned long size; /* Always a multiple of PAGE_SIZE */ 10 unsigned long size; /* Always a multiple of PAGE_SIZE */
11
12 unsigned long tick_patch, tick_patch_len;
13
11 long sym_vvar_start; /* Negative offset to the vvar area */ 14 long sym_vvar_start; /* Negative offset to the vvar area */
12 long sym_vread_tick; /* Start of vread_tick section */
13 long sym_vread_tick_patch_start; /* Start of tick read */
14 long sym_vread_tick_patch_end; /* End of tick read */
15}; 15};
16 16
17#ifdef CONFIG_SPARC64 17#ifdef CONFIG_SPARC64
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index f0eba72aa1ad..5f356dc8e178 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -53,8 +53,6 @@
53 53
54DEFINE_SPINLOCK(rtc_lock); 54DEFINE_SPINLOCK(rtc_lock);
55 55
56unsigned int __read_mostly vdso_fix_stick;
57
58#ifdef CONFIG_SMP 56#ifdef CONFIG_SMP
59unsigned long profile_pc(struct pt_regs *regs) 57unsigned long profile_pc(struct pt_regs *regs)
60{ 58{
@@ -838,7 +836,6 @@ void __init time_init_early(void)
838 } else { 836 } else {
839 init_tick_ops(&tick_operations); 837 init_tick_ops(&tick_operations);
840 clocksource_tick.archdata.vclock_mode = VCLOCK_TICK; 838 clocksource_tick.archdata.vclock_mode = VCLOCK_TICK;
841 vdso_fix_stick = 1;
842 } 839 }
843 } else { 840 } else {
844 init_tick_ops(&stick_operations); 841 init_tick_ops(&stick_operations);
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index dc85570d8839..a6e18ca4cc18 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -33,10 +33,8 @@ targets += $(vdso_img_sodbg) $(vdso_img-y:%=vdso%.so)
33 33
34CPPFLAGS_vdso.lds += -P -C 34CPPFLAGS_vdso.lds += -P -C
35 35
36VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ 36VDSO_LDFLAGS_vdso.lds = -m elf64_sparc -soname linux-vdso.so.1 --no-undefined \
37 -Wl,--no-undefined \ 37 -z max-page-size=8192 -z common-page-size=8192
38 -Wl,-z,max-page-size=8192 -Wl,-z,common-page-size=8192 \
39 $(DISABLE_LTO)
40 38
41$(obj)/vdso64.so.dbg: $(obj)/vdso.lds $(vobjs) FORCE 39$(obj)/vdso64.so.dbg: $(obj)/vdso.lds $(vobjs) FORCE
42 $(call if_changed,vdso) 40 $(call if_changed,vdso)
@@ -54,13 +52,14 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE
54# Don't omit frame pointers for ease of userspace debugging, but do 52# Don't omit frame pointers for ease of userspace debugging, but do
55# optimize sibling calls. 53# optimize sibling calls.
56# 54#
57CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables \ 55CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables -m64 \
58 -m64 -ffixed-g2 -ffixed-g3 -fcall-used-g4 -fcall-used-g5 -ffixed-g6 \ 56 $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
59 -ffixed-g7 $(filter -g%,$(KBUILD_CFLAGS)) \ 57 -fno-omit-frame-pointer -foptimize-sibling-calls \
60 $(call cc-option, -fno-stack-protector) -fno-omit-frame-pointer \ 58 -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
61 -foptimize-sibling-calls -DBUILD_VDSO
62 59
63$(vobjs): KBUILD_CFLAGS += $(CFL) 60SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 -fcall-used-g5 -fcall-used-g7
61
62$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
64 63
65# 64#
66# vDSO code runs in userspace and -pg doesn't help with profiling anyway. 65# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
@@ -73,7 +72,7 @@ $(obj)/%.so: $(obj)/%.so.dbg
73 $(call if_changed,objcopy) 72 $(call if_changed,objcopy)
74 73
75CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) 74CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
76VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf32_sparc,-soname=linux-gate.so.1 75VDSO_LDFLAGS_vdso32.lds = -m elf32_sparc -soname linux-gate.so.1
77 76
78#This makes sure the $(obj) subdirectory exists even though vdso32/ 77#This makes sure the $(obj) subdirectory exists even though vdso32/
79#is not a kbuild sub-make subdirectory 78#is not a kbuild sub-make subdirectory
@@ -91,7 +90,8 @@ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
91KBUILD_CFLAGS_32 := $(filter-out -mcmodel=medlow,$(KBUILD_CFLAGS_32)) 90KBUILD_CFLAGS_32 := $(filter-out -mcmodel=medlow,$(KBUILD_CFLAGS_32))
92KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32)) 91KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32))
93KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32)) 92KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32))
94KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic -mno-app-regs -ffixed-g7 93KBUILD_CFLAGS_32 := $(filter-out $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS_32))
94KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic
95KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) 95KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
96KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) 96KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
97KBUILD_CFLAGS_32 += -fno-omit-frame-pointer 97KBUILD_CFLAGS_32 += -fno-omit-frame-pointer
@@ -109,12 +109,13 @@ $(obj)/vdso32.so.dbg: FORCE \
109# The DSO images are built using a special linker script. 109# The DSO images are built using a special linker script.
110# 110#
111quiet_cmd_vdso = VDSO $@ 111quiet_cmd_vdso = VDSO $@
112 cmd_vdso = $(CC) -nostdlib -o $@ \ 112 cmd_vdso = $(LD) -nostdlib -o $@ \
113 $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ 113 $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
114 -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) 114 -T $(filter %.lds,$^) $(filter %.o,$^) && \
115 sh $(srctree)/$(src)/checkundef.sh '$(OBJDUMP)' '$@'
115 116
116VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \ 117VDSO_LDFLAGS = -shared $(call ld-option, --hash-style=both) \
117 $(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic 118 $(call ld-option, --build-id) -Bsymbolic
118GCOV_PROFILE := n 119GCOV_PROFILE := n
119 120
120# 121#
diff --git a/arch/sparc/vdso/checkundef.sh b/arch/sparc/vdso/checkundef.sh
new file mode 100644
index 000000000000..2d85876ffc32
--- /dev/null
+++ b/arch/sparc/vdso/checkundef.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2objdump="$1"
3file="$2"
4$objdump -t "$file" | grep '*UUND*' | grep -v '#scratch' > /dev/null 2>&1
5if [ $? -eq 1 ]; then
6 exit 0
7else
8 echo "$file: undefined symbols found" >&2
9 exit 1
10fi
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index 75dca9aab737..7b539ceebe13 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -12,11 +12,6 @@
12 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. 12 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
13 */ 13 */
14 14
15/* Disable profiling for userspace code: */
16#ifndef DISABLE_BRANCH_PROFILING
17#define DISABLE_BRANCH_PROFILING
18#endif
19
20#include <linux/kernel.h> 15#include <linux/kernel.h>
21#include <linux/time.h> 16#include <linux/time.h>
22#include <linux/string.h> 17#include <linux/string.h>
@@ -26,13 +21,6 @@
26#include <asm/clocksource.h> 21#include <asm/clocksource.h>
27#include <asm/vvar.h> 22#include <asm/vvar.h>
28 23
29#undef TICK_PRIV_BIT
30#ifdef CONFIG_SPARC64
31#define TICK_PRIV_BIT (1UL << 63)
32#else
33#define TICK_PRIV_BIT (1ULL << 63)
34#endif
35
36#ifdef CONFIG_SPARC64 24#ifdef CONFIG_SPARC64
37#define SYSCALL_STRING \ 25#define SYSCALL_STRING \
38 "ta 0x6d;" \ 26 "ta 0x6d;" \
@@ -60,24 +48,22 @@
60 * Compute the vvar page's address in the process address space, and return it 48 * Compute the vvar page's address in the process address space, and return it
61 * as a pointer to the vvar_data. 49 * as a pointer to the vvar_data.
62 */ 50 */
63static notrace noinline struct vvar_data * 51notrace static __always_inline struct vvar_data *get_vvar_data(void)
64get_vvar_data(void)
65{ 52{
66 unsigned long ret; 53 unsigned long ret;
67 54
68 /* 55 /*
69 * vdso data page is the first vDSO page so grab the return address 56 * vdso data page is the first vDSO page so grab the PC
70 * and move up a page to get to the data page. 57 * and move up a page to get to the data page.
71 */ 58 */
72 ret = (unsigned long)__builtin_return_address(0); 59 __asm__("rd %%pc, %0" : "=r" (ret));
73 ret &= ~(8192 - 1); 60 ret &= ~(8192 - 1);
74 ret -= 8192; 61 ret -= 8192;
75 62
76 return (struct vvar_data *) ret; 63 return (struct vvar_data *) ret;
77} 64}
78 65
79static notrace long 66notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
80vdso_fallback_gettime(long clock, struct timespec *ts)
81{ 67{
82 register long num __asm__("g1") = __NR_clock_gettime; 68 register long num __asm__("g1") = __NR_clock_gettime;
83 register long o0 __asm__("o0") = clock; 69 register long o0 __asm__("o0") = clock;
@@ -88,8 +74,7 @@ vdso_fallback_gettime(long clock, struct timespec *ts)
88 return o0; 74 return o0;
89} 75}
90 76
91static notrace __always_inline long 77notrace static long vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz)
92vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz)
93{ 78{
94 register long num __asm__("g1") = __NR_gettimeofday; 79 register long num __asm__("g1") = __NR_gettimeofday;
95 register long o0 __asm__("o0") = (long) tv; 80 register long o0 __asm__("o0") = (long) tv;
@@ -101,38 +86,43 @@ vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz)
101} 86}
102 87
103#ifdef CONFIG_SPARC64 88#ifdef CONFIG_SPARC64
104static notrace noinline u64 89notrace static __always_inline u64 vread_tick(void)
105vread_tick(void) { 90{
106 u64 ret; 91 u64 ret;
107 92
108 __asm__ __volatile__("rd %%asr24, %0 \n" 93 __asm__ __volatile__("1:\n\t"
109 ".section .vread_tick_patch, \"ax\" \n" 94 "rd %%tick, %0\n\t"
110 "rd %%tick, %0 \n" 95 ".pushsection .tick_patch, \"a\"\n\t"
111 ".previous \n" 96 ".word 1b - ., 1f - .\n\t"
112 : "=&r" (ret)); 97 ".popsection\n\t"
113 return ret & ~TICK_PRIV_BIT; 98 ".pushsection .tick_patch_replacement, \"ax\"\n\t"
99 "1:\n\t"
100 "rd %%asr24, %0\n\t"
101 ".popsection\n"
102 : "=r" (ret));
103 return ret;
114} 104}
115#else 105#else
116static notrace noinline u64 106notrace static __always_inline u64 vread_tick(void)
117vread_tick(void)
118{ 107{
119 unsigned int lo, hi; 108 register unsigned long long ret asm("o4");
120 109
121 __asm__ __volatile__("rd %%asr24, %%g1\n\t" 110 __asm__ __volatile__("1:\n\t"
122 "srlx %%g1, 32, %1\n\t" 111 "rd %%tick, %L0\n\t"
123 "srl %%g1, 0, %0\n" 112 "srlx %L0, 32, %H0\n\t"
124 ".section .vread_tick_patch, \"ax\" \n" 113 ".pushsection .tick_patch, \"a\"\n\t"
125 "rd %%tick, %%g1\n" 114 ".word 1b - ., 1f - .\n\t"
126 ".previous \n" 115 ".popsection\n\t"
127 : "=&r" (lo), "=&r" (hi) 116 ".pushsection .tick_patch_replacement, \"ax\"\n\t"
128 : 117 "1:\n\t"
129 : "g1"); 118 "rd %%asr24, %L0\n\t"
130 return lo | ((u64)hi << 32); 119 ".popsection\n"
120 : "=r" (ret));
121 return ret;
131} 122}
132#endif 123#endif
133 124
134static notrace inline u64 125notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
135vgetsns(struct vvar_data *vvar)
136{ 126{
137 u64 v; 127 u64 v;
138 u64 cycles; 128 u64 cycles;
@@ -142,13 +132,12 @@ vgetsns(struct vvar_data *vvar)
142 return v * vvar->clock.mult; 132 return v * vvar->clock.mult;
143} 133}
144 134
145static notrace noinline int 135notrace static __always_inline int do_realtime(struct vvar_data *vvar,
146do_realtime(struct vvar_data *vvar, struct timespec *ts) 136 struct timespec *ts)
147{ 137{
148 unsigned long seq; 138 unsigned long seq;
149 u64 ns; 139 u64 ns;
150 140
151 ts->tv_nsec = 0;
152 do { 141 do {
153 seq = vvar_read_begin(vvar); 142 seq = vvar_read_begin(vvar);
154 ts->tv_sec = vvar->wall_time_sec; 143 ts->tv_sec = vvar->wall_time_sec;
@@ -157,18 +146,18 @@ do_realtime(struct vvar_data *vvar, struct timespec *ts)
157 ns >>= vvar->clock.shift; 146 ns >>= vvar->clock.shift;
158 } while (unlikely(vvar_read_retry(vvar, seq))); 147 } while (unlikely(vvar_read_retry(vvar, seq)));
159 148
160 timespec_add_ns(ts, ns); 149 ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
150 ts->tv_nsec = ns;
161 151
162 return 0; 152 return 0;
163} 153}
164 154
165static notrace noinline int 155notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
166do_monotonic(struct vvar_data *vvar, struct timespec *ts) 156 struct timespec *ts)
167{ 157{
168 unsigned long seq; 158 unsigned long seq;
169 u64 ns; 159 u64 ns;
170 160
171 ts->tv_nsec = 0;
172 do { 161 do {
173 seq = vvar_read_begin(vvar); 162 seq = vvar_read_begin(vvar);
174 ts->tv_sec = vvar->monotonic_time_sec; 163 ts->tv_sec = vvar->monotonic_time_sec;
@@ -177,13 +166,14 @@ do_monotonic(struct vvar_data *vvar, struct timespec *ts)
177 ns >>= vvar->clock.shift; 166 ns >>= vvar->clock.shift;
178 } while (unlikely(vvar_read_retry(vvar, seq))); 167 } while (unlikely(vvar_read_retry(vvar, seq)));
179 168
180 timespec_add_ns(ts, ns); 169 ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
170 ts->tv_nsec = ns;
181 171
182 return 0; 172 return 0;
183} 173}
184 174
185static notrace noinline int 175notrace static int do_realtime_coarse(struct vvar_data *vvar,
186do_realtime_coarse(struct vvar_data *vvar, struct timespec *ts) 176 struct timespec *ts)
187{ 177{
188 unsigned long seq; 178 unsigned long seq;
189 179
@@ -195,8 +185,8 @@ do_realtime_coarse(struct vvar_data *vvar, struct timespec *ts)
195 return 0; 185 return 0;
196} 186}
197 187
198static notrace noinline int 188notrace static int do_monotonic_coarse(struct vvar_data *vvar,
199do_monotonic_coarse(struct vvar_data *vvar, struct timespec *ts) 189 struct timespec *ts)
200{ 190{
201 unsigned long seq; 191 unsigned long seq;
202 192
diff --git a/arch/sparc/vdso/vdso-layout.lds.S b/arch/sparc/vdso/vdso-layout.lds.S
index f2c83abaca12..ed36d49e1617 100644
--- a/arch/sparc/vdso/vdso-layout.lds.S
+++ b/arch/sparc/vdso/vdso-layout.lds.S
@@ -73,11 +73,8 @@ SECTIONS
73 73
74 .text : { *(.text*) } :text =0x90909090, 74 .text : { *(.text*) } :text =0x90909090,
75 75
76 .vread_tick_patch : { 76 .tick_patch : { *(.tick_patch) } :text
77 vread_tick_patch_start = .; 77 .tick_patch_insns : { *(.tick_patch_insns) } :text
78 *(.vread_tick_patch)
79 vread_tick_patch_end = .;
80 }
81 78
82 /DISCARD/ : { 79 /DISCARD/ : {
83 *(.discard) 80 *(.discard)
diff --git a/arch/sparc/vdso/vdso2c.c b/arch/sparc/vdso/vdso2c.c
index 9f5b1cd6d51d..ab7504176a7f 100644
--- a/arch/sparc/vdso/vdso2c.c
+++ b/arch/sparc/vdso/vdso2c.c
@@ -63,9 +63,6 @@ enum {
63 sym_vvar_start, 63 sym_vvar_start,
64 sym_VDSO_FAKE_SECTION_TABLE_START, 64 sym_VDSO_FAKE_SECTION_TABLE_START,
65 sym_VDSO_FAKE_SECTION_TABLE_END, 65 sym_VDSO_FAKE_SECTION_TABLE_END,
66 sym_vread_tick,
67 sym_vread_tick_patch_start,
68 sym_vread_tick_patch_end
69}; 66};
70 67
71struct vdso_sym { 68struct vdso_sym {
@@ -81,9 +78,6 @@ struct vdso_sym required_syms[] = {
81 [sym_VDSO_FAKE_SECTION_TABLE_END] = { 78 [sym_VDSO_FAKE_SECTION_TABLE_END] = {
82 "VDSO_FAKE_SECTION_TABLE_END", 0 79 "VDSO_FAKE_SECTION_TABLE_END", 0
83 }, 80 },
84 [sym_vread_tick] = {"vread_tick", 1},
85 [sym_vread_tick_patch_start] = {"vread_tick_patch_start", 1},
86 [sym_vread_tick_patch_end] = {"vread_tick_patch_end", 1}
87}; 81};
88 82
89__attribute__((format(printf, 1, 2))) __attribute__((noreturn)) 83__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
diff --git a/arch/sparc/vdso/vdso2c.h b/arch/sparc/vdso/vdso2c.h
index 808decb0f7be..4df005cf98c0 100644
--- a/arch/sparc/vdso/vdso2c.h
+++ b/arch/sparc/vdso/vdso2c.h
@@ -17,10 +17,11 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
17 unsigned long mapping_size; 17 unsigned long mapping_size;
18 int i; 18 int i;
19 unsigned long j; 19 unsigned long j;
20 20 ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
21 ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr; 21 *patch_sec = NULL;
22 ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; 22 ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
23 ELF(Dyn) *dyn = 0, *dyn_end = 0; 23 ELF(Dyn) *dyn = 0, *dyn_end = 0;
24 const char *secstrings;
24 INT_BITS syms[NSYMS] = {}; 25 INT_BITS syms[NSYMS] = {};
25 26
26 ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff)); 27 ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff));
@@ -63,11 +64,18 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
63 } 64 }
64 65
65 /* Walk the section table */ 66 /* Walk the section table */
67 secstrings_hdr = raw_addr + GET_BE(&hdr->e_shoff) +
68 GET_BE(&hdr->e_shentsize)*GET_BE(&hdr->e_shstrndx);
69 secstrings = raw_addr + GET_BE(&secstrings_hdr->sh_offset);
66 for (i = 0; i < GET_BE(&hdr->e_shnum); i++) { 70 for (i = 0; i < GET_BE(&hdr->e_shnum); i++) {
67 ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) + 71 ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) +
68 GET_BE(&hdr->e_shentsize) * i; 72 GET_BE(&hdr->e_shentsize) * i;
69 if (GET_BE(&sh->sh_type) == SHT_SYMTAB) 73 if (GET_BE(&sh->sh_type) == SHT_SYMTAB)
70 symtab_hdr = sh; 74 symtab_hdr = sh;
75
76 if (!strcmp(secstrings + GET_BE(&sh->sh_name),
77 ".tick_patch"))
78 patch_sec = sh;
71 } 79 }
72 80
73 if (!symtab_hdr) 81 if (!symtab_hdr)
@@ -134,6 +142,12 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
134 fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name); 142 fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name);
135 fprintf(outfile, "\t.data = raw_data,\n"); 143 fprintf(outfile, "\t.data = raw_data,\n");
136 fprintf(outfile, "\t.size = %lu,\n", mapping_size); 144 fprintf(outfile, "\t.size = %lu,\n", mapping_size);
145 if (patch_sec) {
146 fprintf(outfile, "\t.tick_patch = %lu,\n",
147 (unsigned long)GET_BE(&patch_sec->sh_offset));
148 fprintf(outfile, "\t.tick_patch_len = %lu,\n",
149 (unsigned long)GET_BE(&patch_sec->sh_size));
150 }
137 for (i = 0; i < NSYMS; i++) { 151 for (i = 0; i < NSYMS; i++) {
138 if (required_syms[i].export && syms[i]) 152 if (required_syms[i].export && syms[i])
139 fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n", 153 fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c
index 5eaff3c1aa0c..8874a27d8adc 100644
--- a/arch/sparc/vdso/vma.c
+++ b/arch/sparc/vdso/vma.c
@@ -16,6 +16,8 @@
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17#include <linux/random.h> 17#include <linux/random.h>
18#include <linux/elf.h> 18#include <linux/elf.h>
19#include <asm/cacheflush.h>
20#include <asm/spitfire.h>
19#include <asm/vdso.h> 21#include <asm/vdso.h>
20#include <asm/vvar.h> 22#include <asm/vvar.h>
21#include <asm/page.h> 23#include <asm/page.h>
@@ -40,7 +42,25 @@ static struct vm_special_mapping vdso_mapping32 = {
40 42
41struct vvar_data *vvar_data; 43struct vvar_data *vvar_data;
42 44
43#define SAVE_INSTR_SIZE 4 45struct tick_patch_entry {
46 s32 orig, repl;
47};
48
49static void stick_patch(const struct vdso_image *image)
50{
51 struct tick_patch_entry *p, *p_end;
52
53 p = image->data + image->tick_patch;
54 p_end = (void *)p + image->tick_patch_len;
55 while (p < p_end) {
56 u32 *instr = (void *)&p->orig + p->orig;
57 u32 *repl = (void *)&p->repl + p->repl;
58
59 *instr = *repl;
60 flushi(instr);
61 p++;
62 }
63}
44 64
45/* 65/*
46 * Allocate pages for the vdso and vvar, and copy in the vdso text from the 66 * Allocate pages for the vdso and vvar, and copy in the vdso text from the
@@ -68,21 +88,8 @@ int __init init_vdso_image(const struct vdso_image *image,
68 if (!cpp) 88 if (!cpp)
69 goto oom; 89 goto oom;
70 90
71 if (vdso_fix_stick) { 91 if (tlb_type != spitfire)
72 /* 92 stick_patch(image);
73 * If the system uses %tick instead of %stick, patch the VDSO
74 * with instruction reading %tick instead of %stick.
75 */
76 unsigned int j, k = SAVE_INSTR_SIZE;
77 unsigned char *data = image->data;
78
79 for (j = image->sym_vread_tick_patch_start;
80 j < image->sym_vread_tick_patch_end; j++) {
81
82 data[image->sym_vread_tick + k] = data[j];
83 k++;
84 }
85 }
86 93
87 for (i = 0; i < cnpages; i++) { 94 for (i = 0; i < cnpages; i++) {
88 cp = alloc_page(GFP_KERNEL); 95 cp = alloc_page(GFP_KERNEL);