diff options
-rw-r--r-- | arch/sparc/include/asm/parport.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/thread_info_64.h | 4 | ||||
-rw-r--r-- | arch/sparc/include/asm/vdso.h | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/time_64.c | 3 | ||||
-rw-r--r-- | arch/sparc/vdso/Makefile | 33 | ||||
-rw-r--r-- | arch/sparc/vdso/checkundef.sh | 10 | ||||
-rw-r--r-- | arch/sparc/vdso/vclock_gettime.c | 102 | ||||
-rw-r--r-- | arch/sparc/vdso/vdso-layout.lds.S | 7 | ||||
-rw-r--r-- | arch/sparc/vdso/vdso2c.c | 6 | ||||
-rw-r--r-- | arch/sparc/vdso/vdso2c.h | 18 | ||||
-rw-r--r-- | arch/sparc/vdso/vma.c | 39 |
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 | ||
24 | static DEFINE_SPINLOCK(dma_spin_lock); | 25 | static 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 | ||
35 | static struct sparc_ebus_info { | 37 | static 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 | ||
124 | register struct thread_info *current_thread_info_reg asm("g6"); | 125 | register 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 | ||
128 | extern 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 @@ | |||
8 | struct vdso_image { | 8 | struct 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 | ||
54 | DEFINE_SPINLOCK(rtc_lock); | 54 | DEFINE_SPINLOCK(rtc_lock); |
55 | 55 | ||
56 | unsigned int __read_mostly vdso_fix_stick; | ||
57 | |||
58 | #ifdef CONFIG_SMP | 56 | #ifdef CONFIG_SMP |
59 | unsigned long profile_pc(struct pt_regs *regs) | 57 | unsigned 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 | ||
34 | CPPFLAGS_vdso.lds += -P -C | 34 | CPPFLAGS_vdso.lds += -P -C |
35 | 35 | ||
36 | VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ | 36 | VDSO_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 | # |
57 | CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables \ | 55 | CFL := $(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) | 60 | SPARC_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 | ||
75 | CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) | 74 | CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) |
76 | VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf32_sparc,-soname=linux-gate.so.1 | 75 | VDSO_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)) | |||
91 | KBUILD_CFLAGS_32 := $(filter-out -mcmodel=medlow,$(KBUILD_CFLAGS_32)) | 90 | KBUILD_CFLAGS_32 := $(filter-out -mcmodel=medlow,$(KBUILD_CFLAGS_32)) |
92 | KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32)) | 91 | KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32)) |
93 | KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32)) | 92 | KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32)) |
94 | KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic -mno-app-regs -ffixed-g7 | 93 | KBUILD_CFLAGS_32 := $(filter-out $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS_32)) |
94 | KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic | ||
95 | KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) | 95 | KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) |
96 | KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) | 96 | KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) |
97 | KBUILD_CFLAGS_32 += -fno-omit-frame-pointer | 97 | KBUILD_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 | # |
111 | quiet_cmd_vdso = VDSO $@ | 111 | quiet_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 | ||
116 | VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \ | 117 | VDSO_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 |
118 | GCOV_PROFILE := n | 119 | GCOV_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 | ||
2 | objdump="$1" | ||
3 | file="$2" | ||
4 | $objdump -t "$file" | grep '*UUND*' | grep -v '#scratch' > /dev/null 2>&1 | ||
5 | if [ $? -eq 1 ]; then | ||
6 | exit 0 | ||
7 | else | ||
8 | echo "$file: undefined symbols found" >&2 | ||
9 | exit 1 | ||
10 | fi | ||
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 | */ |
63 | static notrace noinline struct vvar_data * | 51 | notrace static __always_inline struct vvar_data *get_vvar_data(void) |
64 | get_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 | ||
79 | static notrace long | 66 | notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) |
80 | vdso_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 | ||
91 | static notrace __always_inline long | 77 | notrace static long vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz) |
92 | vdso_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 |
104 | static notrace noinline u64 | 89 | notrace static __always_inline u64 vread_tick(void) |
105 | vread_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 |
116 | static notrace noinline u64 | 106 | notrace static __always_inline u64 vread_tick(void) |
117 | vread_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 | ||
134 | static notrace inline u64 | 125 | notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) |
135 | vgetsns(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 | ||
145 | static notrace noinline int | 135 | notrace static __always_inline int do_realtime(struct vvar_data *vvar, |
146 | do_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 | ||
165 | static notrace noinline int | 155 | notrace static __always_inline int do_monotonic(struct vvar_data *vvar, |
166 | do_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 | ||
185 | static notrace noinline int | 175 | notrace static int do_realtime_coarse(struct vvar_data *vvar, |
186 | do_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 | ||
198 | static notrace noinline int | 188 | notrace static int do_monotonic_coarse(struct vvar_data *vvar, |
199 | do_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 | ||
71 | struct vdso_sym { | 68 | struct 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 | ||
41 | struct vvar_data *vvar_data; | 43 | struct vvar_data *vvar_data; |
42 | 44 | ||
43 | #define SAVE_INSTR_SIZE 4 | 45 | struct tick_patch_entry { |
46 | s32 orig, repl; | ||
47 | }; | ||
48 | |||
49 | static 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); |