x86: re-work memset()

Move the function to its own assembly file. Having it in C just for the
entire body to be an asm() isn't really helpful. Then have two flavors:
A "basic" version using qword steps for the bulk of the operation, and an
ERMS version for modern hardware, to be substituted in via alternatives
patching.

For RET to be usable in an alternative's replacement code, extend the
CALL/JMP patching to cover the case of "JMP __x86_return_thunk" coming
last in replacement code.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
This commit is contained in:
Jan Beulich committed 2025-07-23 15:18:13 +02:00
1 parent c5b06d0b1b
commit eabcdd0faa
4 files changed
+37 -13

No files matched your search

+1
View File
@@ -47,6 +47,7 @@ obj-$(CONFIG_RETURN_THUNK) += indirect-thunk.o
obj-$(CONFIG_PV) += ioport_emulate.o
obj-y += irq.o
obj-$(CONFIG_KEXEC) += machine_kexec.o
obj-y += memset.o
obj-y += mm.o x86_64/mm.o
obj-$(CONFIG_VM_EVENT) += monitor.o
obj-y += mpparse.o
+6
View File
@@ -351,6 +351,12 @@ static int init_or_livepatch _apply_alternatives(struct alt_instr *start,
/* 0xe8/0xe9 are relative branches; fix the offset. */
if ( a->repl_len >= 5 && (*buf & 0xfe) == 0xe8 )
*(int32_t *)(buf + 1) += repl - orig;
else if ( IS_ENABLED(CONFIG_RETURN_THUNK) &&
a->repl_len > 5 && buf[a->repl_len - 5] == 0xe9 &&
((long)repl + a->repl_len +
*(int32_t *)(buf + a->repl_len - 4) ==
(long)__x86_return_thunk) )
*(int32_t *)(buf + a->repl_len - 4) += repl - orig;
a->priv = 1;
+30
View File
@@ -0,0 +1,30 @@
#include <asm/asm_defns.h>
.macro memset
and $7, %edx
shr $3, %rcx
movzbl %sil, %esi
mov $0x0101010101010101, %rax
imul %rsi, %rax
mov %rdi, %r8
rep stosq
or %edx, %ecx
jz 0f
rep stosb
0:
mov %r8, %rax
RET
.endm
.macro memset_erms
mov %esi, %eax
mov %rdi, %r8
rep stosb
mov %r8, %rax
RET
.endm
FUNC(memset)
mov %rdx, %rcx
ALTERNATIVE memset, memset_erms, X86_FEATURE_ERMS
END(memset)
-13
View File
@@ -22,19 +22,6 @@ void *(memcpy)(void *dest, const void *src, size_t n)
return dest;
}
void *(memset)(void *s, int c, size_t n)
{
long d0, d1;
asm volatile (
"rep stosb"
: "=&c" (d0), "=&D" (d1)
: "a" (c), "1" (s), "0" (n)
: "memory");
return s;
}
void *(memmove)(void *dest, const void *src, size_t n)
{
long d0, d1, d2;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.