Skip to content

Commit 176ab02

Browse files
committed
Merge branch 'x86-asmlinkage-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 LTO changes from Peter Anvin: "More infrastructure work in preparation for link-time optimization (LTO). Most of these changes is to make sure symbols accessed from assembly code are properly marked as visible so the linker doesn't remove them. My understanding is that the changes to support LTO are still not upstream in binutils, but are on the way there. This patchset should conclude the x86-specific changes, and remaining patches to actually enable LTO will be fed through the Kbuild tree (other than keeping up with changes to the x86 code base, of course), although not necessarily in this merge window" * 'x86-asmlinkage-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits) Kbuild, lto: Handle basic LTO in modpost Kbuild, lto: Disable LTO for asm-offsets.c Kbuild, lto: Add a gcc-ld script to let run gcc as ld Kbuild, lto: add ld-version and ld-ifversion macros Kbuild, lto: Drop .number postfixes in modpost Kbuild, lto, workaround: Don't warn for initcall_reference in modpost lto: Disable LTO for sys_ni lto: Handle LTO common symbols in module loader lto, workaround: Add workaround for initcall reordering lto: Make asmlinkage __visible x86, lto: Disable LTO for the x86 VDSO initconst, x86: Fix initconst mistake in ts5500 code initconst: Fix initconst mistake in dcdbas asmlinkage: Make trace_hardirqs_on/off_caller visible asmlinkage, x86: Fix 32bit memcpy for LTO asmlinkage Make __stack_chk_failed and memcmp visible asmlinkage: Mark rwsem functions that can be called from assembler asmlinkage asmlinkage: Make main_extable_sort_needed visible asmlinkage, mutex: Mark __visible asmlinkage: Make trace_hardirq visible ...
2 parents e06df6a + ef178f9 commit 176ab02

File tree

27 files changed

+138
-37
lines changed

27 files changed

+138
-37
lines changed

arch/x86/kernel/time.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <asm/time.h>
2424

2525
#ifdef CONFIG_X86_64
26-
DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
26+
__visible DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
2727
#endif
2828

2929
unsigned long profile_pc(struct pt_regs *regs)

arch/x86/lib/memcpy_32.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#undef memcpy
55
#undef memset
66

7-
void *memcpy(void *to, const void *from, size_t n)
7+
__visible void *memcpy(void *to, const void *from, size_t n)
88
{
99
#ifdef CONFIG_X86_USE_3DNOW
1010
return __memcpy3d(to, from, n);
@@ -14,13 +14,13 @@ void *memcpy(void *to, const void *from, size_t n)
1414
}
1515
EXPORT_SYMBOL(memcpy);
1616

17-
void *memset(void *s, int c, size_t count)
17+
__visible void *memset(void *s, int c, size_t count)
1818
{
1919
return __memset(s, c, count);
2020
}
2121
EXPORT_SYMBOL(memset);
2222

23-
void *memmove(void *dest, const void *src, size_t n)
23+
__visible void *memmove(void *dest, const void *src, size_t n)
2424
{
2525
int d0,d1,d2,d3,d4,d5;
2626
char *ret = dest;

arch/x86/platform/ts5500/ts5500.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct ts5500_sbc {
8888
static const struct {
8989
const char * const string;
9090
const ssize_t offset;
91-
} ts5500_signatures[] __initdata = {
91+
} ts5500_signatures[] __initconst = {
9292
{ "TS-5x00 AMD Elan", 0xb14 },
9393
};
9494

arch/x86/vdso/Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Building vDSO images for x86.
33
#
44

5+
KBUILD_CFLAGS += $(DISABLE_LTO)
6+
57
VDSO64-$(CONFIG_X86_64) := y
68
VDSOX32-$(CONFIG_X86_X32_ABI) := y
79
VDSO32-$(CONFIG_X86_32) := y
@@ -35,7 +37,8 @@ export CPPFLAGS_vdso.lds += -P -C
3537

3638
VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
3739
-Wl,--no-undefined \
38-
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
40+
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 \
41+
$(DISABLE_LTO)
3942

4043
$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
4144

@@ -127,7 +130,7 @@ vdso32.so-$(VDSO32-y) += sysenter
127130
vdso32-images = $(vdso32.so-y:%=vdso32-%.so)
128131

129132
CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
130-
VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
133+
VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
131134

132135
# This makes sure the $(obj) subdirectory exists even though vdso32/
133136
# is not a kbuild sub-make subdirectory.
@@ -181,7 +184,8 @@ quiet_cmd_vdso = VDSO $@
181184
-Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
182185
sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
183186

184-
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
187+
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
188+
$(LTO_CFLAGS)
185189
GCOV_PROFILE := n
186190

187191
#

drivers/firmware/dcdbas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ static struct platform_driver dcdbas_driver = {
584584
.remove = dcdbas_remove,
585585
};
586586

587-
static const struct platform_device_info dcdbas_dev_info __initdata = {
587+
static const struct platform_device_info dcdbas_dev_info __initconst = {
588588
.name = DRIVER_NAME,
589589
.id = -1,
590590
.dma_mask = DMA_BIT_MASK(32),

drivers/pnp/pnpbios/bioscalls.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
#include "pnpbios.h"
2323

24-
static struct {
24+
__visible struct {
2525
u16 offset;
2626
u16 segment;
2727
} pnp_bios_callpoint;
@@ -41,6 +41,7 @@ asmlinkage void pnp_bios_callfunc(void);
4141

4242
__asm__(".text \n"
4343
__ALIGN_STR "\n"
44+
".globl pnp_bios_callfunc\n"
4445
"pnp_bios_callfunc:\n"
4546
" pushl %edx \n"
4647
" pushl %ecx \n"
@@ -66,9 +67,9 @@ static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
6667
* after PnP BIOS oopses.
6768
*/
6869

69-
u32 pnp_bios_fault_esp;
70-
u32 pnp_bios_fault_eip;
71-
u32 pnp_bios_is_utter_crap = 0;
70+
__visible u32 pnp_bios_fault_esp;
71+
__visible u32 pnp_bios_fault_eip;
72+
__visible u32 pnp_bios_is_utter_crap = 0;
7273

7374
static spinlock_t pnp_bios_lock;
7475

include/linux/init.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,23 @@ extern bool initcall_debug;
163163

164164
#ifndef __ASSEMBLY__
165165

166+
#ifdef CONFIG_LTO
167+
/* Work around a LTO gcc problem: when there is no reference to a variable
168+
* in a module it will be moved to the end of the program. This causes
169+
* reordering of initcalls which the kernel does not like.
170+
* Add a dummy reference function to avoid this. The function is
171+
* deleted by the linker.
172+
*/
173+
#define LTO_REFERENCE_INITCALL(x) \
174+
; /* yes this is needed */ \
175+
static __used __exit void *reference_##x(void) \
176+
{ \
177+
return &x; \
178+
}
179+
#else
180+
#define LTO_REFERENCE_INITCALL(x)
181+
#endif
182+
166183
/* initcalls are now grouped by functionality into separate
167184
* subsections. Ordering inside the subsections is determined
168185
* by link order.
@@ -175,7 +192,8 @@ extern bool initcall_debug;
175192

176193
#define __define_initcall(fn, id) \
177194
static initcall_t __initcall_##fn##id __used \
178-
__attribute__((__section__(".initcall" #id ".init"))) = fn
195+
__attribute__((__section__(".initcall" #id ".init"))) = fn; \
196+
LTO_REFERENCE_INITCALL(__initcall_##fn##id)
179197

180198
/*
181199
* Early initcalls run before initializing SMP.

include/linux/io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
struct device;
2626

27-
void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
27+
__visible void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
2828
void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
2929

3030
#ifdef CONFIG_MMU

include/linux/linkage.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
#endif
1313

1414
#ifdef __cplusplus
15-
#define CPP_ASMLINKAGE extern "C"
15+
#define CPP_ASMLINKAGE extern "C" __visible
1616
#else
17-
#define CPP_ASMLINKAGE
17+
#define CPP_ASMLINKAGE __visible
1818
#endif
1919

2020
#ifndef asmlinkage

include/linux/lockdep.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ extern void lockdep_info(void);
265265
extern void lockdep_reset(void);
266266
extern void lockdep_reset_lock(struct lockdep_map *lock);
267267
extern void lockdep_free_key_range(void *start, unsigned long size);
268-
extern void lockdep_sys_exit(void);
268+
extern asmlinkage void lockdep_sys_exit(void);
269269

270270
extern void lockdep_off(void);
271271
extern void lockdep_on(void);

kernel/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ CFLAGS_REMOVE_cgroup-debug.o = -pg
1818
CFLAGS_REMOVE_irq_work.o = -pg
1919
endif
2020

21+
# cond_syscall is currently not LTO compatible
22+
CFLAGS_sys_ni.o = $(DISABLE_LTO)
23+
2124
obj-y += sched/
2225
obj-y += locking/
2326
obj-y += power/

kernel/extable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extern struct exception_table_entry __start___ex_table[];
3636
extern struct exception_table_entry __stop___ex_table[];
3737

3838
/* Cleared by build time tools if the table is already sorted. */
39-
u32 __initdata main_extable_sort_needed = 1;
39+
u32 __initdata __visible main_extable_sort_needed = 1;
4040

4141
/* Sort the kernel's built-in exception table */
4242
void __init sort_main_extable(void)

kernel/locking/lockdep.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,7 +2557,7 @@ static void __trace_hardirqs_on_caller(unsigned long ip)
25572557
debug_atomic_inc(hardirqs_on_events);
25582558
}
25592559

2560-
void trace_hardirqs_on_caller(unsigned long ip)
2560+
__visible void trace_hardirqs_on_caller(unsigned long ip)
25612561
{
25622562
time_hardirqs_on(CALLER_ADDR0, ip);
25632563

@@ -2610,7 +2610,7 @@ EXPORT_SYMBOL(trace_hardirqs_on);
26102610
/*
26112611
* Hardirqs were disabled:
26122612
*/
2613-
void trace_hardirqs_off_caller(unsigned long ip)
2613+
__visible void trace_hardirqs_off_caller(unsigned long ip)
26142614
{
26152615
struct task_struct *curr = current;
26162616

@@ -4188,7 +4188,7 @@ void debug_show_held_locks(struct task_struct *task)
41884188
}
41894189
EXPORT_SYMBOL_GPL(debug_show_held_locks);
41904190

4191-
void lockdep_sys_exit(void)
4191+
asmlinkage void lockdep_sys_exit(void)
41924192
{
41934193
struct task_struct *curr = current;
41944194

kernel/locking/mutex.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ EXPORT_SYMBOL(__mutex_init);
7575
* We also put the fastpath first in the kernel image, to make sure the
7676
* branch is predicted by the CPU as default-untaken.
7777
*/
78-
static __used noinline void __sched
79-
__mutex_lock_slowpath(atomic_t *lock_count);
78+
__visible void __sched __mutex_lock_slowpath(atomic_t *lock_count);
8079

8180
/**
8281
* mutex_lock - acquire the mutex
@@ -189,7 +188,8 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
189188
}
190189
#endif
191190

192-
static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
191+
__visible __used noinline
192+
void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
193193

194194
/**
195195
* mutex_unlock - release the mutex
@@ -716,7 +716,7 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
716716
/*
717717
* Release the lock, slowpath:
718718
*/
719-
static __used noinline void
719+
__visible void
720720
__mutex_unlock_slowpath(atomic_t *lock_count)
721721
{
722722
__mutex_unlock_common_slowpath(lock_count, 1);
@@ -773,7 +773,7 @@ int __sched mutex_lock_killable(struct mutex *lock)
773773
}
774774
EXPORT_SYMBOL(mutex_lock_killable);
775775

776-
static __used noinline void __sched
776+
__visible void __sched
777777
__mutex_lock_slowpath(atomic_t *lock_count)
778778
{
779779
struct mutex *lock = container_of(lock_count, struct mutex, count);

kernel/locking/rwsem-xadd.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, enum rwsem_wake_type wake_type)
143143
/*
144144
* wait for the read lock to be granted
145145
*/
146+
__visible
146147
struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
147148
{
148149
long count, adjustment = -RWSEM_ACTIVE_READ_BIAS;
@@ -190,6 +191,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
190191
/*
191192
* wait until we successfully acquire the write lock
192193
*/
194+
__visible
193195
struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
194196
{
195197
long count, adjustment = -RWSEM_ACTIVE_WRITE_BIAS;
@@ -252,6 +254,7 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
252254
* handle waking up a waiter on the semaphore
253255
* - up_read/up_write has decremented the active part of count if we come here
254256
*/
257+
__visible
255258
struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
256259
{
257260
unsigned long flags;
@@ -272,6 +275,7 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
272275
* - caller incremented waiting part of count and discovered it still negative
273276
* - just wake up any readers at the front of the queue
274277
*/
278+
__visible
275279
struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
276280
{
277281
unsigned long flags;

kernel/module.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,6 +1948,10 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
19481948

19491949
switch (sym[i].st_shndx) {
19501950
case SHN_COMMON:
1951+
/* Ignore common symbols */
1952+
if (!strncmp(name, "__gnu_lto", 9))
1953+
break;
1954+
19511955
/* We compiled with -fno-common. These are not
19521956
supposed to happen. */
19531957
pr_debug("Common symbol: %s\n", name);

kernel/panic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ EXPORT_SYMBOL(warn_slowpath_null);
459459
* Called when gcc's -fstack-protector feature is used, and
460460
* gcc detects corruption of the on-stack canary value
461461
*/
462-
void __stack_chk_fail(void)
462+
__visible void __stack_chk_fail(void)
463463
{
464464
panic("stack-protector: Kernel stack is corrupted in: %p\n",
465465
__builtin_return_address(0));

kernel/timer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
#define CREATE_TRACE_POINTS
5353
#include <trace/events/timer.h>
5454

55-
u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
55+
__visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
5656

5757
EXPORT_SYMBOL(jiffies_64);
5858

kernel/trace/trace_irqsoff.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,14 @@ void trace_hardirqs_off(void)
498498
}
499499
EXPORT_SYMBOL(trace_hardirqs_off);
500500

501-
void trace_hardirqs_on_caller(unsigned long caller_addr)
501+
__visible void trace_hardirqs_on_caller(unsigned long caller_addr)
502502
{
503503
if (!preempt_trace() && irq_trace())
504504
stop_critical_timing(CALLER_ADDR0, caller_addr);
505505
}
506506
EXPORT_SYMBOL(trace_hardirqs_on_caller);
507507

508-
void trace_hardirqs_off_caller(unsigned long caller_addr)
508+
__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
509509
{
510510
if (!preempt_trace() && irq_trace())
511511
start_critical_timing(CALLER_ADDR0, caller_addr);

lib/string.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ EXPORT_SYMBOL(memmove);
648648
* @count: The size of the area.
649649
*/
650650
#undef memcmp
651-
int memcmp(const void *cs, const void *ct, size_t count)
651+
__visible int memcmp(const void *cs, const void *ct, size_t count)
652652
{
653653
const unsigned char *su1, *su2;
654654
int res = 0;

scripts/Kbuild.include

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ ld-option = $(call try-run,\
155155
# Important: no spaces around options
156156
ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
157157

158+
# ld-version
159+
# Usage: $(call ld-version)
160+
# Note this is mainly for HJ Lu's 3 number binutil versions
161+
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
162+
163+
# ld-ifversion
164+
# Usage: $(call ld-ifversion, -ge, 22252, y)
165+
ld-ifversion = $(shell [ $(call ld-version) $(1) $(2) ] && echo $(3))
166+
158167
######
159168

160169
###

scripts/Makefile.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ $(multi-objs-y:.o=.s) : modname = $(modname-multi)
198198
$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
199199

200200
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
201-
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
201+
cmd_cc_s_c = $(CC) $(c_flags) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
202202

203203
$(obj)/%.s: $(src)/%.c FORCE
204204
$(call if_changed_dep,cc_s_c)

0 commit comments

Comments
 (0)