x86_64: further cleanup of 32-bit compat syscall mechanisms
AMD only supports "syscall" from 32-bit compat usermode. Intel and Centaur(?) only support "sysenter" from 32-bit compat usermode. Set the X86 feature bits accordingly, and set up the vdso in accordance with those bits. On the offchance we run on in a 64-bit environment which supports neither syscall nor sysenter from 32-bit mode, then fall back to the int $0x80 vdso. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:

committed by
Ingo Molnar

parent
71415c6a08
commit
6a52e4b1cd
@@ -193,17 +193,12 @@ static __init void relocate_vdso(Elf32_Ehdr *ehdr)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* These symbols are defined by vdso32.S to mark the bounds
|
||||
* of the ELF DSO images included therein.
|
||||
*/
|
||||
extern const char vdso32_default_start, vdso32_default_end;
|
||||
extern const char vdso32_sysenter_start, vdso32_sysenter_end;
|
||||
static struct page *vdso32_pages[1];
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
#define vdso32_sysenter() (boot_cpu_has(X86_FEATURE_SYSENTER32))
|
||||
#define vdso32_syscall() (boot_cpu_has(X86_FEATURE_SYSCALL32))
|
||||
|
||||
/* May not be __init: called during resume */
|
||||
void syscall32_cpu_init(void)
|
||||
@@ -226,6 +221,7 @@ static inline void map_compat_vdso(int map)
|
||||
#else /* CONFIG_X86_32 */
|
||||
|
||||
#define vdso32_sysenter() (boot_cpu_has(X86_FEATURE_SEP))
|
||||
#define vdso32_syscall() (0)
|
||||
|
||||
void enable_sep_cpu(void)
|
||||
{
|
||||
@@ -296,12 +292,15 @@ int __init sysenter_setup(void)
|
||||
gate_vma_init();
|
||||
#endif
|
||||
|
||||
if (!vdso32_sysenter()) {
|
||||
vsyscall = &vdso32_default_start;
|
||||
vsyscall_len = &vdso32_default_end - &vdso32_default_start;
|
||||
} else {
|
||||
if (vdso32_syscall()) {
|
||||
vsyscall = &vdso32_syscall_start;
|
||||
vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
|
||||
} else if (vdso32_sysenter()){
|
||||
vsyscall = &vdso32_sysenter_start;
|
||||
vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
|
||||
} else {
|
||||
vsyscall = &vdso32_int80_start;
|
||||
vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
|
||||
}
|
||||
|
||||
memcpy(syscall_page, vsyscall, vsyscall_len);
|
||||
|
Reference in New Issue
Block a user