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

Commit b4b541a6 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by H. Peter Anvin
Browse files

x86, vdso: Patch alternatives in the 32-bit VDSO



We need the alternatives mechanism for rdtsc_barrier() to work.

Signed-off-by: default avatarStefani Seibold <stefani@seibold.net>
Link: http://lkml.kernel.org/r/1395094933-14252-9-git-send-email-stefani@seibold.net


Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent ef721987
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -28,4 +28,6 @@ extern const char vdso32_int80_start, vdso32_int80_end;
extern const char vdso32_syscall_start, vdso32_syscall_end;
extern const char vdso32_sysenter_start, vdso32_sysenter_end;

void __init patch_vdso32(void *vdso, size_t len);

#endif /* _ASM_X86_VDSO_H */
+2 −1
Original line number Diff line number Diff line
@@ -21,7 +21,8 @@ vobjs-$(VDSOX32-y) += $(vobjx32s-compat)
vobj64s := $(filter-out $(vobjx32s-compat),$(vobjs-y))

# files to link into kernel
obj-$(VDSO64-y)			+= vma.o vdso.o
obj-y				+= vma.o
obj-$(VDSO64-y)			+= vdso.o
obj-$(VDSOX32-y)		+= vdsox32.o
obj-$(VDSO32-y)			+= vdso32.o vdso32-setup.o

+12 −11
Original line number Diff line number Diff line
@@ -112,24 +112,25 @@ void enable_sep_cpu(void)

int __init sysenter_setup(void)
{
	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
	const void *vsyscall;
	size_t vsyscall_len;
	void *vdso_page = (void *)get_zeroed_page(GFP_ATOMIC);
	const void *vdso;
	size_t vdso_len;

	vdso32_pages[0] = virt_to_page(syscall_page);
	vdso32_pages[0] = virt_to_page(vdso_page);

	if (vdso32_syscall()) {
		vsyscall = &vdso32_syscall_start;
		vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
		vdso = &vdso32_syscall_start;
		vdso_len = &vdso32_syscall_end - &vdso32_syscall_start;
	} else if (vdso32_sysenter()){
		vsyscall = &vdso32_sysenter_start;
		vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
		vdso = &vdso32_sysenter_start;
		vdso_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
	} else {
		vsyscall = &vdso32_int80_start;
		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
		vdso = &vdso32_int80_start;
		vdso_len = &vdso32_int80_end - &vdso32_int80_start;
	}

	memcpy(syscall_page, vsyscall, vsyscall_len);
	memcpy(vdso_page, vdso, vdso_len);
	patch_vdso32(vdso_page, vdso_len);

	return 0;
}
+10 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <asm/vdso.h>
#include <asm/page.h>

#if defined(CONFIG_X86_64)
unsigned int __read_mostly vdso_enabled = 1;

extern char vdso_start[], vdso_end[];
@@ -28,8 +29,12 @@ static unsigned vdso_size;
extern char vdsox32_start[], vdsox32_end[];
extern struct page *vdsox32_pages[];
static unsigned vdsox32_size;
#endif
#endif

static void __init patch_vdsox32(void *vdso, size_t len)
#if defined(CONFIG_X86_32) || defined(CONFIG_X86_X32_ABI) || \
	defined(CONFIG_COMPAT)
void __init patch_vdso32(void *vdso, size_t len)
{
	Elf32_Ehdr *hdr = vdso;
	Elf32_Shdr *sechdrs, *alt_sec = 0;
@@ -52,7 +57,7 @@ static void __init patch_vdsox32(void *vdso, size_t len)
	}

	/* If we get here, it's probably a bug. */
	pr_warning("patch_vdsox32: .altinstructions not found\n");
	pr_warning("patch_vdso32: .altinstructions not found\n");
	return;  /* nothing to patch */

found:
@@ -61,6 +66,7 @@ static void __init patch_vdsox32(void *vdso, size_t len)
}
#endif

#if defined(CONFIG_X86_64)
static void __init patch_vdso64(void *vdso, size_t len)
{
	Elf64_Ehdr *hdr = vdso;
@@ -104,7 +110,7 @@ static int __init init_vdso(void)
		vdso_pages[i] = virt_to_page(vdso_start + i*PAGE_SIZE);

#ifdef CONFIG_X86_X32_ABI
	patch_vdsox32(vdsox32_start, vdsox32_end - vdsox32_start);
	patch_vdso32(vdsox32_start, vdsox32_end - vdsox32_start);
	npages = (vdsox32_end - vdsox32_start + PAGE_SIZE - 1) / PAGE_SIZE;
	vdsox32_size = npages << PAGE_SHIFT;
	for (i = 0; i < npages; i++)
@@ -204,3 +210,4 @@ static __init int vdso_setup(char *s)
	return 0;
}
__setup("vdso=", vdso_setup);
#endif