aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2007-07-20 03:31:43 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-20 11:44:19 -0400
commitd2eea68e7db759ce67807b42b7407236cccfde71 (patch)
tree41521fcbce645a492c83e45b4b73be829a4cc8b1 /arch/i386
parent5ac12c6fe1b5fbda0d0caedb8214cde545a5737c (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>
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/boot/compressed/relocs.c1
-rw-r--r--arch/i386/kernel/vsyscall-note.S15
-rw-r--r--arch/i386/xen/setup.c15
-rw-r--r--arch/i386/xen/vdso.h4
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")
14ELFNOTE_END 14ELFNOTE_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
38ELFNOTE_START(GNU, 2, "a") 39ELFNOTE_START(GNU, 2, "a")
39 .long 1, 1<<VDSO_NOTE_NONEGSEG_BIT /* ncaps, mask */ 40 .long 1 /* ncaps */
41VDSO_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 */
41ELFNOTE_END 44ELFNOTE_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 */
24extern const char xen_hypervisor_callback[]; 25extern 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 */
62static 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
58void __init xen_arch_setup(void) 71void __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