From 46b8306480fb424abd525acc1763da1c63a27d8a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Oct 2018 10:52:52 -0700 Subject: sparc: Fix parport build warnings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If PARPORT_PC_FIFO is not enabled, do not provide the dma lock macros and lock definition. Otherwise: ./arch/sparc/include/asm/parport.h:24:24: warning: ‘dma_spin_lock’ defined but not used [-Wunused-variable] static DEFINE_SPINLOCK(dma_spin_lock); ^~~~~~~~~~~~~ ./include/linux/spinlock_types.h:81:39: note: in definition of macro ‘DEFINE_SPINLOCK’ #define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x) Signed-off-by: David S. Miller --- arch/sparc/include/asm/parport.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/sparc') 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 @@ */ #define HAS_DMA +#ifdef CONFIG_PARPORT_PC_FIFO static DEFINE_SPINLOCK(dma_spin_lock); #define claim_dma_lock() \ @@ -31,6 +32,7 @@ static DEFINE_SPINLOCK(dma_spin_lock); #define release_dma_lock(__flags) \ spin_unlock_irqrestore(&dma_spin_lock, __flags); +#endif static struct sparc_ebus_info { struct ebus_dma_info info; -- cgit v1.2.3-58-ga151 From 2f6c9bf31a0b16aeccb42b73f8d0ddf9bea88f3f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 21:44:33 -0700 Subject: sparc: Improve VDSO instruction patching. The current VDSO patch mechanism has several problems: 1) It assumes how gcc will emit a function, with a register window, an initial save instruction and then immediately the %tick read when compiling vread_tick(). There is no such guarantees, code generation could change at any time, gcc could put a nop between the save and the %tick read, etc. So this is extremely fragile and would fail some day. 2) It disallows us to properly inline vread_tick() into the callers and thus get the best possible code sequences. So fix this to patch properly, with location based annotations. We have to be careful because we cannot do it the way we do patches elsewhere in the kernel. Those use a sequence like: 1: insn .section .whatever_patch, "ax" .word 1b replacement_insn .previous This is a dynamic shared object, so that .word cannot be resolved at build time, and thus cannot be used to execute the patches when the kernel initializes the images. Even trying to use label difference equations doesn't work in the above kind of scheme: 1: insn .section .whatever_patch, "ax" .word . - 1b replacement_insn .previous The assembler complains that it cannot resolve that computation. The issue is that this is contained in an executable section. Borrow the sequence used by x86 alternatives, which is: 1: insn .pushsection .whatever_patch, "a" .word . - 1b, . - 1f .popsection .pushsection .whatever_patch_replacements, "ax" 1: replacement_insn .previous This works, allows us to inline vread_tick() as much as we like, and can be used for arbitrary kinds of VDSO patching in the future. Also, reverse the condition for patching. Most systems are %stick based, so if we only patch on %tick systems the patching code will get little or no testing. Signed-off-by: David S. Miller --- arch/sparc/include/asm/vdso.h | 6 +++--- arch/sparc/kernel/time_64.c | 3 --- arch/sparc/vdso/vclock_gettime.c | 41 +++++++++++++++++++++++---------------- arch/sparc/vdso/vdso-layout.lds.S | 7 ++----- arch/sparc/vdso/vdso2c.c | 6 ------ arch/sparc/vdso/vdso2c.h | 18 +++++++++++++++-- arch/sparc/vdso/vma.c | 39 ++++++++++++++++++++++--------------- 7 files changed, 68 insertions(+), 52 deletions(-) (limited to 'arch/sparc') 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 @@ struct vdso_image { void *data; unsigned long size; /* Always a multiple of PAGE_SIZE */ + + unsigned long tick_patch, tick_patch_len; + long sym_vvar_start; /* Negative offset to the vvar area */ - long sym_vread_tick; /* Start of vread_tick section */ - long sym_vread_tick_patch_start; /* Start of tick read */ - long sym_vread_tick_patch_end; /* End of tick read */ }; #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 @@ DEFINE_SPINLOCK(rtc_lock); -unsigned int __read_mostly vdso_fix_stick; - #ifdef CONFIG_SMP unsigned long profile_pc(struct pt_regs *regs) { @@ -838,7 +836,6 @@ void __init time_init_early(void) } else { init_tick_ops(&tick_operations); clocksource_tick.archdata.vclock_mode = VCLOCK_TICK; - vdso_fix_stick = 1; } } else { init_tick_ops(&stick_operations); diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 75dca9aab737..a0c8a4b008d5 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -105,29 +105,36 @@ static notrace noinline u64 vread_tick(void) { u64 ret; - __asm__ __volatile__("rd %%asr24, %0 \n" - ".section .vread_tick_patch, \"ax\" \n" - "rd %%tick, %0 \n" - ".previous \n" - : "=&r" (ret)); + __asm__ __volatile__("1:\n\t" + "rd %%tick, %0\n\t" + ".pushsection .tick_patch, \"a\"\n\t" + ".word 1b - ., 1f - .\n\t" + ".popsection\n\t" + ".pushsection .tick_patch_replacement, \"ax\"\n\t" + "1:\n\t" + "rd %%asr24, %0\n\t" + ".popsection\n" + : "=r" (ret)); return ret & ~TICK_PRIV_BIT; } #else static notrace noinline u64 vread_tick(void) { - unsigned int lo, hi; - - __asm__ __volatile__("rd %%asr24, %%g1\n\t" - "srlx %%g1, 32, %1\n\t" - "srl %%g1, 0, %0\n" - ".section .vread_tick_patch, \"ax\" \n" - "rd %%tick, %%g1\n" - ".previous \n" - : "=&r" (lo), "=&r" (hi) - : - : "g1"); - return lo | ((u64)hi << 32); + register unsigned long long ret asm("o4"); + + __asm__ __volatile__("1:\n\t" + "rd %%tick, %L0\n\t" + "srlx %L0, 32, %H0\n\t" + ".pushsection .tick_patch, \"a\"\n\t" + ".word 1b - ., 1f - .\n\t" + ".popsection\n\t" + ".pushsection .tick_patch_replacement, \"ax\"\n\t" + "1:\n\t" + "rd %%asr24, %L0\n\t" + ".popsection\n" + : "=r" (ret)); + return ret; } #endif 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 .text : { *(.text*) } :text =0x90909090, - .vread_tick_patch : { - vread_tick_patch_start = .; - *(.vread_tick_patch) - vread_tick_patch_end = .; - } + .tick_patch : { *(.tick_patch) } :text + .tick_patch_insns : { *(.tick_patch_insns) } :text /DISCARD/ : { *(.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 { sym_vvar_start, sym_VDSO_FAKE_SECTION_TABLE_START, sym_VDSO_FAKE_SECTION_TABLE_END, - sym_vread_tick, - sym_vread_tick_patch_start, - sym_vread_tick_patch_end }; struct vdso_sym { @@ -81,9 +78,6 @@ struct vdso_sym required_syms[] = { [sym_VDSO_FAKE_SECTION_TABLE_END] = { "VDSO_FAKE_SECTION_TABLE_END", 0 }, - [sym_vread_tick] = {"vread_tick", 1}, - [sym_vread_tick_patch_start] = {"vread_tick_patch_start", 1}, - [sym_vread_tick_patch_end] = {"vread_tick_patch_end", 1} }; __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, unsigned long mapping_size; int i; unsigned long j; - - ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr; + ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr, + *patch_sec = NULL; ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; ELF(Dyn) *dyn = 0, *dyn_end = 0; + const char *secstrings; INT_BITS syms[NSYMS] = {}; 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, } /* Walk the section table */ + secstrings_hdr = raw_addr + GET_BE(&hdr->e_shoff) + + GET_BE(&hdr->e_shentsize)*GET_BE(&hdr->e_shstrndx); + secstrings = raw_addr + GET_BE(&secstrings_hdr->sh_offset); for (i = 0; i < GET_BE(&hdr->e_shnum); i++) { ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) + GET_BE(&hdr->e_shentsize) * i; if (GET_BE(&sh->sh_type) == SHT_SYMTAB) symtab_hdr = sh; + + if (!strcmp(secstrings + GET_BE(&sh->sh_name), + ".tick_patch")) + patch_sec = sh; } if (!symtab_hdr) @@ -134,6 +142,12 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name); fprintf(outfile, "\t.data = raw_data,\n"); fprintf(outfile, "\t.size = %lu,\n", mapping_size); + if (patch_sec) { + fprintf(outfile, "\t.tick_patch = %lu,\n", + (unsigned long)GET_BE(&patch_sec->sh_offset)); + fprintf(outfile, "\t.tick_patch_len = %lu,\n", + (unsigned long)GET_BE(&patch_sec->sh_size)); + } for (i = 0; i < NSYMS; i++) { if (required_syms[i].export && syms[i]) 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 @@ #include #include #include +#include +#include #include #include #include @@ -40,7 +42,25 @@ static struct vm_special_mapping vdso_mapping32 = { struct vvar_data *vvar_data; -#define SAVE_INSTR_SIZE 4 +struct tick_patch_entry { + s32 orig, repl; +}; + +static void stick_patch(const struct vdso_image *image) +{ + struct tick_patch_entry *p, *p_end; + + p = image->data + image->tick_patch; + p_end = (void *)p + image->tick_patch_len; + while (p < p_end) { + u32 *instr = (void *)&p->orig + p->orig; + u32 *repl = (void *)&p->repl + p->repl; + + *instr = *repl; + flushi(instr); + p++; + } +} /* * 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, if (!cpp) goto oom; - if (vdso_fix_stick) { - /* - * If the system uses %tick instead of %stick, patch the VDSO - * with instruction reading %tick instead of %stick. - */ - unsigned int j, k = SAVE_INSTR_SIZE; - unsigned char *data = image->data; - - for (j = image->sym_vread_tick_patch_start; - j < image->sym_vread_tick_patch_end; j++) { - - data[image->sym_vread_tick + k] = data[j]; - k++; - } - } + if (tlb_type != spitfire) + stick_patch(image); for (i = 0; i < cnpages; i++) { cp = alloc_page(GFP_KERNEL); -- cgit v1.2.3-58-ga151 From 794b88e047588965ad8f716245857b452f118e13 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:09:40 -0700 Subject: sparc: Inline VDSO gettime code aggressively. One interesting thing we need to do is stop using __builtin_return_address() in get_vvar_data(). Simply read the %pc register instead. Signed-off-by: David S. Miller --- arch/sparc/vdso/vclock_gettime.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index a0c8a4b008d5..75c49fcb57aa 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -60,24 +60,22 @@ * Compute the vvar page's address in the process address space, and return it * as a pointer to the vvar_data. */ -static notrace noinline struct vvar_data * -get_vvar_data(void) +notrace static __always_inline struct vvar_data *get_vvar_data(void) { unsigned long ret; /* - * vdso data page is the first vDSO page so grab the return address + * vdso data page is the first vDSO page so grab the PC * and move up a page to get to the data page. */ - ret = (unsigned long)__builtin_return_address(0); + __asm__("rd %%pc, %0" : "=r" (ret)); ret &= ~(8192 - 1); ret -= 8192; return (struct vvar_data *) ret; } -static notrace long -vdso_fallback_gettime(long clock, struct timespec *ts) +notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) { register long num __asm__("g1") = __NR_clock_gettime; register long o0 __asm__("o0") = clock; @@ -88,8 +86,7 @@ vdso_fallback_gettime(long clock, struct timespec *ts) return o0; } -static notrace __always_inline long -vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz) +notrace static long vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz) { register long num __asm__("g1") = __NR_gettimeofday; register long o0 __asm__("o0") = (long) tv; @@ -101,8 +98,8 @@ vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz) } #ifdef CONFIG_SPARC64 -static notrace noinline u64 -vread_tick(void) { +notrace static __always_inline u64 vread_tick(void) +{ u64 ret; __asm__ __volatile__("1:\n\t" @@ -118,8 +115,7 @@ vread_tick(void) { return ret & ~TICK_PRIV_BIT; } #else -static notrace noinline u64 -vread_tick(void) +notrace static __always_inline u64 vread_tick(void) { register unsigned long long ret asm("o4"); @@ -138,8 +134,7 @@ vread_tick(void) } #endif -static notrace inline u64 -vgetsns(struct vvar_data *vvar) +notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) { u64 v; u64 cycles; @@ -149,8 +144,8 @@ vgetsns(struct vvar_data *vvar) return v * vvar->clock.mult; } -static notrace noinline int -do_realtime(struct vvar_data *vvar, struct timespec *ts) +notrace static __always_inline int do_realtime(struct vvar_data *vvar, + struct timespec *ts) { unsigned long seq; u64 ns; @@ -169,8 +164,8 @@ do_realtime(struct vvar_data *vvar, struct timespec *ts) return 0; } -static notrace noinline int -do_monotonic(struct vvar_data *vvar, struct timespec *ts) +notrace static __always_inline int do_monotonic(struct vvar_data *vvar, + struct timespec *ts) { unsigned long seq; u64 ns; @@ -189,8 +184,8 @@ do_monotonic(struct vvar_data *vvar, struct timespec *ts) return 0; } -static notrace noinline int -do_realtime_coarse(struct vvar_data *vvar, struct timespec *ts) +notrace static int do_realtime_coarse(struct vvar_data *vvar, + struct timespec *ts) { unsigned long seq; @@ -202,8 +197,8 @@ do_realtime_coarse(struct vvar_data *vvar, struct timespec *ts) return 0; } -static notrace noinline int -do_monotonic_coarse(struct vvar_data *vvar, struct timespec *ts) +notrace static int do_monotonic_coarse(struct vvar_data *vvar, + struct timespec *ts) { unsigned long seq; -- cgit v1.2.3-58-ga151 From 3fe5d7e861286c0b80573f094e32dd9736370d69 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:10:51 -0700 Subject: sparc: Don't bother masking out TICK_PRIV_BIT in VDSO code. If the TICK_PRIV_BIT was set, we would not be able to read the tick register in user space, which is where this code runs. Signed-off-by: David S. Miller --- arch/sparc/vdso/vclock_gettime.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 75c49fcb57aa..4e853d1582c7 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -26,13 +26,6 @@ #include #include -#undef TICK_PRIV_BIT -#ifdef CONFIG_SPARC64 -#define TICK_PRIV_BIT (1UL << 63) -#else -#define TICK_PRIV_BIT (1ULL << 63) -#endif - #ifdef CONFIG_SPARC64 #define SYSCALL_STRING \ "ta 0x6d;" \ @@ -112,7 +105,7 @@ notrace static __always_inline u64 vread_tick(void) "rd %%asr24, %0\n\t" ".popsection\n" : "=r" (ret)); - return ret & ~TICK_PRIV_BIT; + return ret; } #else notrace static __always_inline u64 vread_tick(void) -- cgit v1.2.3-58-ga151 From 44231b7fee3f086cf367588c7c79ec3b5d7619b2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:14:01 -0700 Subject: sparc: Set DISABLE_BRANCH_PROFILING in VDSO CFLAGS. Not in vclock_gettime.c itself. Signed-off-by: David S. Miller --- arch/sparc/vdso/Makefile | 3 ++- arch/sparc/vdso/vclock_gettime.c | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile index dc85570d8839..7ea03dd2bd62 100644 --- a/arch/sparc/vdso/Makefile +++ b/arch/sparc/vdso/Makefile @@ -58,7 +58,8 @@ CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables \ -m64 -ffixed-g2 -ffixed-g3 -fcall-used-g4 -fcall-used-g5 -ffixed-g6 \ -ffixed-g7 $(filter -g%,$(KBUILD_CFLAGS)) \ $(call cc-option, -fno-stack-protector) -fno-omit-frame-pointer \ - -foptimize-sibling-calls -DBUILD_VDSO + -foptimize-sibling-calls \ + -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO $(vobjs): KBUILD_CFLAGS += $(CFL) diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 4e853d1582c7..7b5bf63fc0f5 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -12,11 +12,6 @@ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. */ -/* Disable profiling for userspace code: */ -#ifndef DISABLE_BRANCH_PROFILING -#define DISABLE_BRANCH_PROFILING -#endif - #include #include #include -- cgit v1.2.3-58-ga151 From 5615edcca99a0ceb47940fb8e89d1f72bc35398b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:22:54 -0700 Subject: sparc: Improve VDSO CFLAGS. Do not set any special register usage options, use the default which is exactly what we should use for userspace code. Make sure we remove the gcc plugin options from the 64-bit build. The 32-bit cflags got it right already. Signed-off-by: David S. Miller --- arch/sparc/vdso/Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile index 7ea03dd2bd62..3b0d287311c2 100644 --- a/arch/sparc/vdso/Makefile +++ b/arch/sparc/vdso/Makefile @@ -54,14 +54,14 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE # Don't omit frame pointers for ease of userspace debugging, but do # optimize sibling calls. # -CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables \ - -m64 -ffixed-g2 -ffixed-g3 -fcall-used-g4 -fcall-used-g5 -ffixed-g6 \ - -ffixed-g7 $(filter -g%,$(KBUILD_CFLAGS)) \ - $(call cc-option, -fno-stack-protector) -fno-omit-frame-pointer \ - -foptimize-sibling-calls \ +CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables -m64 \ + $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \ + -fno-omit-frame-pointer -foptimize-sibling-calls \ -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO -$(vobjs): KBUILD_CFLAGS += $(CFL) +SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 -fcall-used-g5 -fcall-used-g7 + +$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS)) $(CFL) # # vDSO code runs in userspace and -pg doesn't help with profiling anyway. @@ -92,7 +92,8 @@ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS)) KBUILD_CFLAGS_32 := $(filter-out -mcmodel=medlow,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32)) KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32)) -KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic -mno-app-regs -ffixed-g7 +KBUILD_CFLAGS_32 := $(filter-out $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS_32)) +KBUILD_CFLAGS_32 += -m32 -msoft-float -fpic KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector) KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) KBUILD_CFLAGS_32 += -fno-omit-frame-pointer -- cgit v1.2.3-58-ga151 From 3c2b2d9408b11022614bf656ae56c8fc12001ecc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:33:07 -0700 Subject: sparc: Really use linker with LDFLAGS. Rather than funneling through CC. Also, use --hash-style=both just like other VDSO architectures and glibc do. Signed-off-by: David S. Miller --- arch/sparc/vdso/Makefile | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile index 3b0d287311c2..a9e3a4f633a7 100644 --- a/arch/sparc/vdso/Makefile +++ b/arch/sparc/vdso/Makefile @@ -33,10 +33,8 @@ targets += $(vdso_img_sodbg) $(vdso_img-y:%=vdso%.so) CPPFLAGS_vdso.lds += -P -C -VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ - -Wl,--no-undefined \ - -Wl,-z,max-page-size=8192 -Wl,-z,common-page-size=8192 \ - $(DISABLE_LTO) +VDSO_LDFLAGS_vdso.lds = -m elf64_sparc -soname linux-vdso.so.1 --no-undefined \ + -z max-page-size=8192 -z common-page-size=8192 $(obj)/vdso64.so.dbg: $(obj)/vdso.lds $(vobjs) FORCE $(call if_changed,vdso) @@ -74,7 +72,7 @@ $(obj)/%.so: $(obj)/%.so.dbg $(call if_changed,objcopy) CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) -VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf32_sparc,-soname=linux-gate.so.1 +VDSO_LDFLAGS_vdso32.lds = -m elf32_sparc -soname linux-gate.so.1 #This makes sure the $(obj) subdirectory exists even though vdso32/ #is not a kbuild sub-make subdirectory @@ -111,12 +109,12 @@ $(obj)/vdso32.so.dbg: FORCE \ # The DSO images are built using a special linker script. # quiet_cmd_vdso = VDSO $@ - cmd_vdso = $(CC) -nostdlib -o $@ \ + cmd_vdso = $(LD) -nostdlib -o $@ \ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ - -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) + -T $(filter %.lds,$^) $(filter %.o,$^) -VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \ - $(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic +VDSO_LDFLAGS = -shared $(call ld-option, --hash-style=both) \ + $(call ld-option, --build-id) -Bsymbolic GCOV_PROFILE := n # -- cgit v1.2.3-58-ga151 From ecd4c19f3df7f3687867a2183934efb54a7d3c14 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:36:17 -0700 Subject: sparc: Validate VDSO for undefined symbols. There should be no undefined symbols in the resulting VDSO image(s). On sparc, fixed register usage can result in undefined symbols ending up in the image. To combat this, we do two things: 1) Define current_thread_info() specially when BUILD_DSO. 2) Ignore "#scratch" register undefined symbols in the output. Signed-off-by: David S. Miller --- arch/sparc/include/asm/thread_info_64.h | 4 ++++ arch/sparc/vdso/Makefile | 3 ++- arch/sparc/vdso/checkundef.sh | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 arch/sparc/vdso/checkundef.sh (limited to 'arch/sparc') 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 { } /* how to get the thread information struct from C */ +#ifndef BUILD_VDSO register struct thread_info *current_thread_info_reg asm("g6"); #define current_thread_info() (current_thread_info_reg) +#else +extern struct thread_info *current_thread_info(void); +#endif /* thread information allocation */ #if PAGE_SHIFT == 13 diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile index a9e3a4f633a7..a6e18ca4cc18 100644 --- a/arch/sparc/vdso/Makefile +++ b/arch/sparc/vdso/Makefile @@ -111,7 +111,8 @@ $(obj)/vdso32.so.dbg: FORCE \ quiet_cmd_vdso = VDSO $@ cmd_vdso = $(LD) -nostdlib -o $@ \ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ - -T $(filter %.lds,$^) $(filter %.o,$^) + -T $(filter %.lds,$^) $(filter %.o,$^) && \ + sh $(srctree)/$(src)/checkundef.sh '$(OBJDUMP)' '$@' VDSO_LDFLAGS = -shared $(call ld-option, --hash-style=both) \ $(call ld-option, --build-id) -Bsymbolic 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 @@ +#!/bin/sh +objdump="$1" +file="$2" +$objdump -t "$file" | grep '*UUND*' | grep -v '#scratch' > /dev/null 2>&1 +if [ $? -eq 1 ]; then + exit 0 +else + echo "$file: undefined symbols found" >&2 + exit 1 +fi -- cgit v1.2.3-58-ga151 From 19832d244954189c851d8492718607a14734679c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 Oct 2018 22:38:56 -0700 Subject: sparc: Several small VDSO vclock_gettime.c improvements. Almost entirely borrowed from the x86 code. Main improvement is to avoid having to initialize ts->tv_nsec to zero before the sequence loops, by expanding timespec_add_ns(). Signed-off-by: David S. Miller --- arch/sparc/vdso/vclock_gettime.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c index 7b5bf63fc0f5..7b539ceebe13 100644 --- a/arch/sparc/vdso/vclock_gettime.c +++ b/arch/sparc/vdso/vclock_gettime.c @@ -138,7 +138,6 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar, unsigned long seq; u64 ns; - ts->tv_nsec = 0; do { seq = vvar_read_begin(vvar); ts->tv_sec = vvar->wall_time_sec; @@ -147,7 +146,8 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar, ns >>= vvar->clock.shift; } while (unlikely(vvar_read_retry(vvar, seq))); - timespec_add_ns(ts, ns); + ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); + ts->tv_nsec = ns; return 0; } @@ -158,7 +158,6 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar, unsigned long seq; u64 ns; - ts->tv_nsec = 0; do { seq = vvar_read_begin(vvar); ts->tv_sec = vvar->monotonic_time_sec; @@ -167,7 +166,8 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar, ns >>= vvar->clock.shift; } while (unlikely(vvar_read_retry(vvar, seq))); - timespec_add_ns(ts, ns); + ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); + ts->tv_nsec = ns; return 0; } -- cgit v1.2.3-58-ga151