diff options
-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 | ||