aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-07-10 19:24:08 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-16 05:07:44 -0400
commit62541c376668042e20122864a044360707b2fb82 (patch)
tree965d05ac3bed88bacd5d7869091d38e78130705f /arch
parent6596f2422306a05be2170efc114da49f26a047dd (diff)
xen64: disable 32-bit syscall/sysenter if not supported.
Old versions of Xen (3.1 and before) don't support sysenter or syscall from 32-bit compat userspaces. If we can't set the appropriate syscall callback, then disable the corresponding feature bit, which will cause the vdso32 setup to fall back appropriately. Linux assumes that syscall is always available to 32-bit userspace, and installs it by default if sysenter isn't available. In that case, we just disable vdso altogether, forcing userspace libc to fall back to int $0x80. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/xen/setup.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 9d7a14402895..9cce4a92aac0 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -106,46 +106,46 @@ static __cpuinit int register_callback(unsigned type, const void *func)
106 106
107void __cpuinit xen_enable_sysenter(void) 107void __cpuinit xen_enable_sysenter(void)
108{ 108{
109 int cpu = smp_processor_id();
110 extern void xen_sysenter_target(void); 109 extern void xen_sysenter_target(void);
111 int ret; 110 int ret;
111 unsigned sysenter_feature;
112 112
113#ifdef CONFIG_X86_32 113#ifdef CONFIG_X86_32
114 if (!boot_cpu_has(X86_FEATURE_SEP)) { 114 sysenter_feature = X86_FEATURE_SEP;
115 return;
116 }
117#else 115#else
118 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL && 116 sysenter_feature = X86_FEATURE_SYSENTER32;
119 boot_cpu_data.x86_vendor != X86_VENDOR_CENTAUR) {
120 return;
121 }
122#endif 117#endif
123 118
119 if (!boot_cpu_has(sysenter_feature))
120 return;
121
124 ret = register_callback(CALLBACKTYPE_sysenter, xen_sysenter_target); 122 ret = register_callback(CALLBACKTYPE_sysenter, xen_sysenter_target);
125 if(ret != 0) { 123 if(ret != 0)
126 clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SEP); 124 setup_clear_cpu_cap(sysenter_feature);
127 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
128 }
129} 125}
130 126
131void __cpuinit xen_enable_syscall(void) 127void __cpuinit xen_enable_syscall(void)
132{ 128{
133#ifdef CONFIG_X86_64 129#ifdef CONFIG_X86_64
134 int cpu = smp_processor_id();
135 int ret; 130 int ret;
136 extern void xen_syscall_target(void); 131 extern void xen_syscall_target(void);
137 extern void xen_syscall32_target(void); 132 extern void xen_syscall32_target(void);
138 133
139 ret = register_callback(CALLBACKTYPE_syscall, xen_syscall_target); 134 ret = register_callback(CALLBACKTYPE_syscall, xen_syscall_target);
140 if (ret != 0) { 135 if (ret != 0) {
141 printk("failed to set syscall: %d\n", ret); 136 printk(KERN_ERR "Failed to set syscall: %d\n", ret);
142 clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SYSCALL); 137 /* Pretty fatal; 64-bit userspace has no other
143 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SYSCALL); 138 mechanism for syscalls. */
144 } else { 139 }
140
141 if (boot_cpu_has(X86_FEATURE_SYSCALL32)) {
145 ret = register_callback(CALLBACKTYPE_syscall32, 142 ret = register_callback(CALLBACKTYPE_syscall32,
146 xen_syscall32_target); 143 xen_syscall32_target);
147 if (ret != 0) 144 if (ret != 0) {
148 printk("failed to set 32-bit syscall: %d\n", ret); 145 printk(KERN_INFO "Xen: 32-bit syscall not supported: disabling vdso\n");
146 setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
147 sysctl_vsyscall32 = 0;
148 }
149 } 149 }
150#endif /* CONFIG_X86_64 */ 150#endif /* CONFIG_X86_64 */
151} 151}