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

Commit 5967ed87 authored by Jan Beulich's avatar Jan Beulich Committed by H. Peter Anvin
Browse files

x86-64: Reduce SMP locks table size



Reduce the SMP locks table size by using relative pointers instead of
absolute ones, thus cutting the table size by half.

Signed-off-by: default avatarJan Beulich <jbeulich@novell.com>
LKML-Reference: <4BCF30FE020000780003B3B6@vpn.id2.novell.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
parent 402af0d7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -6,8 +6,8 @@
	.macro LOCK_PREFIX
1:	lock
	.section .smp_locks,"a"
	_ASM_ALIGN
	_ASM_PTR 1b
	.balign 4
	.long 1b - .
	.previous
	.endm
#else
+2 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@
#ifdef CONFIG_SMP
#define LOCK_PREFIX \
		".section .smp_locks,\"a\"\n"	\
		_ASM_ALIGN "\n"			\
		_ASM_PTR "661f\n" /* address */	\
		".balign 4\n"			\
		".long 661f - .\n" /* offset */	\
		".previous\n"			\
		"661:\n\tlock; "

+25 −20
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
}

extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
extern u8 *__smp_locks[], *__smp_locks_end[];
extern s32 __smp_locks[], __smp_locks_end[];
static void *text_poke_early(void *addr, const void *opcode, size_t len);

/* Replace instructions with better alternatives for this CPU type.
@@ -235,37 +235,39 @@ void __init_or_module apply_alternatives(struct alt_instr *start,

#ifdef CONFIG_SMP

static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
static void alternatives_smp_lock(const s32 *start, const s32 *end,
				  u8 *text, u8 *text_end)
{
	u8 **ptr;
	const s32 *poff;

	mutex_lock(&text_mutex);
	for (ptr = start; ptr < end; ptr++) {
		if (*ptr < text)
			continue;
		if (*ptr > text_end)
	for (poff = start; poff < end; poff++) {
		u8 *ptr = (u8 *)poff + *poff;

		if (!*poff || ptr < text || ptr >= text_end)
			continue;
		/* turn DS segment override prefix into lock prefix */
		text_poke(*ptr, ((unsigned char []){0xf0}), 1);
		text_poke(ptr, ((unsigned char []){0xf0}), 1);
	};
	mutex_unlock(&text_mutex);
}

static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
static void alternatives_smp_unlock(const s32 *start, const s32 *end,
				    u8 *text, u8 *text_end)
{
	u8 **ptr;
	const s32 *poff;

	if (noreplace_smp)
		return;

	mutex_lock(&text_mutex);
	for (ptr = start; ptr < end; ptr++) {
		if (*ptr < text)
			continue;
		if (*ptr > text_end)
	for (poff = start; poff < end; poff++) {
		u8 *ptr = (u8 *)poff + *poff;

		if (!*poff || ptr < text || ptr >= text_end)
			continue;
		/* turn lock prefix into DS segment override prefix */
		text_poke(*ptr, ((unsigned char []){0x3E}), 1);
		text_poke(ptr, ((unsigned char []){0x3E}), 1);
	};
	mutex_unlock(&text_mutex);
}
@@ -276,8 +278,8 @@ struct smp_alt_module {
	char		*name;

	/* ptrs to lock prefixes */
	u8		**locks;
	u8		**locks_end;
	const s32	*locks;
	const s32	*locks_end;

	/* .text segment, needed to avoid patching init code ;) */
	u8		*text;
@@ -398,17 +400,20 @@ void alternatives_smp_switch(int smp)
int alternatives_text_reserved(void *start, void *end)
{
	struct smp_alt_module *mod;
	u8 **ptr;
	const s32 *poff;
	u8 *text_start = start;
	u8 *text_end = end;

	list_for_each_entry(mod, &smp_alt_modules, next) {
		if (mod->text > text_end || mod->text_end < text_start)
			continue;
		for (ptr = mod->locks; ptr < mod->locks_end; ptr++)
			if (text_start <= *ptr && text_end >= *ptr)
		for (poff = mod->locks; poff < mod->locks_end; poff++) {
			const u8 *ptr = (const u8 *)poff + *poff;

			if (text_start <= ptr && text_end > ptr)
				return 1;
		}
	}

	return 0;
}