Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a52e4b1 authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Ingo Molnar
Browse files

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: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent 71415c6a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
	if (c->x86_power & (1<<8))
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);

	set_cpu_cap(c, X86_FEATURE_SYSCALL32);
}

static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+0 −3
Original line number Diff line number Diff line
@@ -317,9 +317,6 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
		c->x86_phys_bits = eax & 0xff;
	}

	/* Assume all 64-bit CPUs support 32-bit syscall */
	set_cpu_cap(c, X86_FEATURE_SYSCALL32);

	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
	    cpu_devs[c->x86_vendor]->c_early_init)
		cpu_devs[c->x86_vendor]->c_early_init(c);
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ $(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
# Build multiple 32-bit vDSO images to choose from at boot time.
#
obj-$(VDSO32-y)			+= vdso32-syms.lds
vdso32.so-$(CONFIG_X86_32)	+= int80
vdso32.so-$(VDSO32-y)		+= int80
vdso32.so-$(CONFIG_COMPAT)	+= syscall
vdso32.so-$(VDSO32-y)		+= sysenter

+9 −10
Original line number Diff line number Diff line
@@ -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);
+8 −5
Original line number Diff line number Diff line
@@ -2,14 +2,17 @@

__INITDATA

	.globl vdso32_default_start, vdso32_default_end
vdso32_default_start:
#ifdef CONFIG_X86_32
	.globl vdso32_int80_start, vdso32_int80_end
vdso32_int80_start:
	.incbin "arch/x86/vdso/vdso32-int80.so"
#else
vdso32_int80_end:

	.globl vdso32_syscall_start, vdso32_syscall_end
vdso32_syscall_start:
#ifdef CONFIG_COMPAT
	.incbin "arch/x86/vdso/vdso32-syscall.so"
#endif
vdso32_default_end:
vdso32_syscall_end:

	.globl vdso32_sysenter_start, vdso32_sysenter_end
vdso32_sysenter_start:
Loading