diff options
author | Roland McGrath <roland@redhat.com> | 2007-07-20 03:31:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 11:44:19 -0400 |
commit | d2eea68e7db759ce67807b42b7407236cccfde71 (patch) | |
tree | 41521fcbce645a492c83e45b4b73be829a4cc8b1 | |
parent | 5ac12c6fe1b5fbda0d0caedb8214cde545a5737c (diff) |
xen: disable vdso "nosegneg" on native boot
One of the nice ideas behind paravirt is that CONFIG_XEN=y can be included
in a standard configuration and be no worse for native booting than as a
Xen guest. The glibc feature that supports the vDSO "nosegneg" note is
designed specifically to make this easy. You just have to flip one bit at
boot time. This patch makes Xen flip the bit, so a CONFIG_XEN=y kernel on
bare hardware does not make glibc use the less-optimized library builds.
Signed-off-by: Roland McGrath <roland@redhat.com>
Acked-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/i386/boot/compressed/relocs.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/vsyscall-note.S | 15 | ||||
-rw-r--r-- | arch/i386/xen/setup.c | 15 | ||||
-rw-r--r-- | arch/i386/xen/vdso.h | 4 |
4 files changed, 29 insertions, 6 deletions
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c index b0e21c3cee5c..2d77ee728f92 100644 --- a/arch/i386/boot/compressed/relocs.c +++ b/arch/i386/boot/compressed/relocs.c | |||
@@ -31,6 +31,7 @@ static const char* safe_abs_relocs[] = { | |||
31 | "__kernel_rt_sigreturn", | 31 | "__kernel_rt_sigreturn", |
32 | "__kernel_sigreturn", | 32 | "__kernel_sigreturn", |
33 | "SYSENTER_RETURN", | 33 | "SYSENTER_RETURN", |
34 | "VDSO_NOTE_MASK", | ||
34 | "xen_irq_disable_direct_reloc", | 35 | "xen_irq_disable_direct_reloc", |
35 | "xen_save_fl_direct_reloc", | 36 | "xen_save_fl_direct_reloc", |
36 | }; | 37 | }; |
diff --git a/arch/i386/kernel/vsyscall-note.S b/arch/i386/kernel/vsyscall-note.S index 271f16a8ca01..07c0daf78237 100644 --- a/arch/i386/kernel/vsyscall-note.S +++ b/arch/i386/kernel/vsyscall-note.S | |||
@@ -14,7 +14,6 @@ ELFNOTE_START(Linux, 0, "a") | |||
14 | ELFNOTE_END | 14 | ELFNOTE_END |
15 | 15 | ||
16 | #ifdef CONFIG_XEN | 16 | #ifdef CONFIG_XEN |
17 | |||
18 | /* | 17 | /* |
19 | * Add a special note telling glibc's dynamic linker a fake hardware | 18 | * Add a special note telling glibc's dynamic linker a fake hardware |
20 | * flavor that it will use to choose the search path for libraries in the | 19 | * flavor that it will use to choose the search path for libraries in the |
@@ -28,15 +27,19 @@ ELFNOTE_END | |||
28 | * It should contain: | 27 | * It should contain: |
29 | * hwcap 1 nosegneg | 28 | * hwcap 1 nosegneg |
30 | * to match the mapping of bit to name that we give here. | 29 | * to match the mapping of bit to name that we give here. |
30 | * | ||
31 | * At runtime, the fake hardware feature will be considered to be present | ||
32 | * if its bit is set in the mask word. So, we start with the mask 0, and | ||
33 | * at boot time we set VDSO_NOTE_NONEGSEG_BIT if running under Xen. | ||
31 | */ | 34 | */ |
32 | 35 | ||
33 | /* Bit used for the pseudo-hwcap for non-negative segments. We use | 36 | #include "../xen/vdso.h" /* Defines VDSO_NOTE_NONEGSEG_BIT. */ |
34 | bit 1 to avoid bugs in some versions of glibc when bit 0 is | ||
35 | used; the choice is otherwise arbitrary. */ | ||
36 | #define VDSO_NOTE_NONEGSEG_BIT 1 | ||
37 | 37 | ||
38 | .globl VDSO_NOTE_MASK | ||
38 | ELFNOTE_START(GNU, 2, "a") | 39 | ELFNOTE_START(GNU, 2, "a") |
39 | .long 1, 1<<VDSO_NOTE_NONEGSEG_BIT /* ncaps, mask */ | 40 | .long 1 /* ncaps */ |
41 | VDSO_NOTE_MASK: | ||
42 | .long 0 /* mask */ | ||
40 | .byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg" /* bit, name */ | 43 | .byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg" /* bit, name */ |
41 | ELFNOTE_END | 44 | ELFNOTE_END |
42 | #endif | 45 | #endif |
diff --git a/arch/i386/xen/setup.c b/arch/i386/xen/setup.c index 2fe6eac510f0..f84e77226646 100644 --- a/arch/i386/xen/setup.c +++ b/arch/i386/xen/setup.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <xen/features.h> | 19 | #include <xen/features.h> |
20 | 20 | ||
21 | #include "xen-ops.h" | 21 | #include "xen-ops.h" |
22 | #include "vdso.h" | ||
22 | 23 | ||
23 | /* These are code, but not functions. Defined in entry.S */ | 24 | /* These are code, but not functions. Defined in entry.S */ |
24 | extern const char xen_hypervisor_callback[]; | 25 | extern const char xen_hypervisor_callback[]; |
@@ -55,6 +56,18 @@ static void xen_idle(void) | |||
55 | } | 56 | } |
56 | } | 57 | } |
57 | 58 | ||
59 | /* | ||
60 | * Set the bit indicating "nosegneg" library variants should be used. | ||
61 | */ | ||
62 | static void fiddle_vdso(void) | ||
63 | { | ||
64 | extern u32 VDSO_NOTE_MASK; /* See ../kernel/vsyscall-note.S. */ | ||
65 | extern char vsyscall_int80_start; | ||
66 | u32 *mask = (u32 *) ((unsigned long) &VDSO_NOTE_MASK - VDSO_PRELINK + | ||
67 | &vsyscall_int80_start); | ||
68 | *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT; | ||
69 | } | ||
70 | |||
58 | void __init xen_arch_setup(void) | 71 | void __init xen_arch_setup(void) |
59 | { | 72 | { |
60 | struct physdev_set_iopl set_iopl; | 73 | struct physdev_set_iopl set_iopl; |
@@ -93,4 +106,6 @@ void __init xen_arch_setup(void) | |||
93 | #endif | 106 | #endif |
94 | 107 | ||
95 | paravirt_disable_iospace(); | 108 | paravirt_disable_iospace(); |
109 | |||
110 | fiddle_vdso(); | ||
96 | } | 111 | } |
diff --git a/arch/i386/xen/vdso.h b/arch/i386/xen/vdso.h new file mode 100644 index 000000000000..861fedfe5230 --- /dev/null +++ b/arch/i386/xen/vdso.h | |||
@@ -0,0 +1,4 @@ | |||
1 | /* Bit used for the pseudo-hwcap for non-negative segments. We use | ||
2 | bit 1 to avoid bugs in some versions of glibc when bit 0 is | ||
3 | used; the choice is otherwise arbitrary. */ | ||
4 | #define VDSO_NOTE_NONEGSEG_BIT 1 | ||