Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/asm: Remove semicolon from "rep" prefixes

Minimum version of binutils required to compile the kernel is 2.25.
This version correctly handles the "rep" prefixes, so it is possible
to remove the semicolon, which was used to support ancient versions
of GNU as.

Due to the semicolon, the compiler considers "rep; insn" (or its
alternate "rep\n\tinsn" form) as two separate instructions. Removing
the semicolon makes asm length calculations more accurate, consequently
making scheduling and inlining decisions of the compiler more accurate.

Removing the semicolon also enables assembler checks involving "rep"
prefixes. Trying to assemble e.g. "rep addl %eax, %ebx" results in:

Error: invalid instruction `add' after `rep'

Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Pavel Machek <pavel@kernel.org>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Link: https://lore.kernel.org/r/20250418071437.4144391-2-ubizjak@gmail.com

authored by

Uros Bizjak and committed by
Ingo Molnar
42c782fa 4850074f

+39 -54
+3 -3
arch/x86/include/asm/io.h
··· 217 217 static inline void __iowrite32_copy(void __iomem *to, const void *from, 218 218 size_t count) 219 219 { 220 - asm volatile("rep ; movsl" 220 + asm volatile("rep movsl" 221 221 : "=&c"(count), "=&D"(to), "=&S"(from) 222 222 : "0"(count), "1"(to), "2"(from) 223 223 : "memory"); ··· 282 282 count--; \ 283 283 } \ 284 284 } else { \ 285 - asm volatile("rep; outs" #bwl \ 285 + asm volatile("rep outs" #bwl \ 286 286 : "+S"(addr), "+c"(count) \ 287 287 : "d"(port) : "memory"); \ 288 288 } \ ··· 298 298 count--; \ 299 299 } \ 300 300 } else { \ 301 - asm volatile("rep; ins" #bwl \ 301 + asm volatile("rep ins" #bwl \ 302 302 : "+D"(addr), "+c"(count) \ 303 303 : "d"(port) : "memory"); \ 304 304 } \
+6 -9
arch/x86/include/asm/string_32.h
··· 33 33 static __always_inline void *__memcpy(void *to, const void *from, size_t n) 34 34 { 35 35 int d0, d1, d2; 36 - asm volatile("rep ; movsl\n\t" 36 + asm volatile("rep movsl\n\t" 37 37 "movl %4,%%ecx\n\t" 38 38 "andl $3,%%ecx\n\t" 39 39 "jz 1f\n\t" 40 - "rep ; movsb\n\t" 40 + "rep movsb\n\t" 41 41 "1:" 42 42 : "=&c" (d0), "=&D" (d1), "=&S" (d2) 43 43 : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) ··· 89 89 if (n >= 5 * 4) { 90 90 /* large block: use rep prefix */ 91 91 int ecx; 92 - asm volatile("rep ; movsl" 92 + asm volatile("rep movsl" 93 93 : "=&c" (ecx), "=&D" (edi), "=&S" (esi) 94 94 : "0" (n / 4), "1" (edi), "2" (esi) 95 95 : "memory" ··· 165 165 static inline void *__memset_generic(void *s, char c, size_t count) 166 166 { 167 167 int d0, d1; 168 - asm volatile("rep\n\t" 169 - "stosb" 168 + asm volatile("rep stosb" 170 169 : "=&c" (d0), "=&D" (d1) 171 170 : "a" (c), "1" (s), "0" (count) 172 171 : "memory"); ··· 198 199 static inline void *memset16(uint16_t *s, uint16_t v, size_t n) 199 200 { 200 201 int d0, d1; 201 - asm volatile("rep\n\t" 202 - "stosw" 202 + asm volatile("rep stosw" 203 203 : "=&c" (d0), "=&D" (d1) 204 204 : "a" (v), "1" (s), "0" (n) 205 205 : "memory"); ··· 209 211 static inline void *memset32(uint32_t *s, uint32_t v, size_t n) 210 212 { 211 213 int d0, d1; 212 - asm volatile("rep\n\t" 213 - "stosl" 214 + asm volatile("rep stosl" 214 215 : "=&c" (d0), "=&D" (d1) 215 216 : "a" (v), "1" (s), "0" (n) 216 217 : "memory");
+3 -5
arch/x86/kernel/head_32.S
··· 86 86 movl $pa(__bss_stop),%ecx 87 87 subl %edi,%ecx 88 88 shrl $2,%ecx 89 - rep ; stosl 89 + rep stosl 90 90 /* 91 91 * Copy bootup parameters out of the way. 92 92 * Note: %esi still has the pointer to the real-mode data. ··· 98 98 movl $pa(boot_params),%edi 99 99 movl $(PARAM_SIZE/4),%ecx 100 100 cld 101 - rep 102 - movsl 101 + rep movsl 103 102 movl pa(boot_params) + NEW_CL_POINTER,%esi 104 103 andl %esi,%esi 105 104 jz 1f # No command line 106 105 movl $pa(boot_command_line),%edi 107 106 movl $(COMMAND_LINE_SIZE/4),%ecx 108 - rep 109 - movsl 107 + rep movsl 110 108 1: 111 109 112 110 #ifdef CONFIG_OLPC
+3 -3
arch/x86/kernel/relocate_kernel_32.S
··· 263 263 264 264 movl %edx, %edi 265 265 movl $1024, %ecx 266 - rep ; movsl 266 + rep movsl 267 267 268 268 movl %ebp, %edi 269 269 movl %eax, %esi 270 270 movl $1024, %ecx 271 - rep ; movsl 271 + rep movsl 272 272 273 273 movl %eax, %edi 274 274 movl %edx, %esi 275 275 movl $1024, %ecx 276 - rep ; movsl 276 + rep movsl 277 277 278 278 lea PAGE_SIZE(%ebp), %esi 279 279 jmp 0b
+3 -3
arch/x86/kernel/relocate_kernel_64.S
··· 363 363 /* copy source page to swap page */ 364 364 movq kexec_pa_swap_page(%rip), %rdi 365 365 movl $512, %ecx 366 - rep ; movsq 366 + rep movsq 367 367 368 368 /* copy destination page to source page */ 369 369 movq %rax, %rdi 370 370 movq %rdx, %rsi 371 371 movl $512, %ecx 372 - rep ; movsq 372 + rep movsq 373 373 374 374 /* copy swap page to destination page */ 375 375 movq %rdx, %rdi 376 376 movq kexec_pa_swap_page(%rip), %rsi 377 377 .Lnoswap: 378 378 movl $512, %ecx 379 - rep ; movsq 379 + rep movsq 380 380 381 381 lea PAGE_SIZE(%rax), %rsi 382 382 jmp .Lloop
+1 -1
arch/x86/lib/iomem.c
··· 10 10 static __always_inline void rep_movs(void *to, const void *from, size_t n) 11 11 { 12 12 unsigned long d0, d1, d2; 13 - asm volatile("rep ; movsl\n\t" 13 + asm volatile("rep movsl\n\t" 14 14 "testb $2,%b4\n\t" 15 15 "je 1f\n\t" 16 16 "movsw\n"
+6 -11
arch/x86/lib/string_32.c
··· 40 40 "stosb\n\t" 41 41 "testb %%al,%%al\n\t" 42 42 "jne 1b\n\t" 43 - "rep\n\t" 44 - "stosb\n" 43 + "rep stosb\n" 45 44 "2:" 46 45 : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) 47 46 : "0" (src), "1" (dest), "2" (count) : "memory"); ··· 53 54 char *strcat(char *dest, const char *src) 54 55 { 55 56 int d0, d1, d2, d3; 56 - asm volatile("repne\n\t" 57 - "scasb\n\t" 57 + asm volatile("repne scasb\n\t" 58 58 "decl %1\n" 59 59 "1:\tlodsb\n\t" 60 60 "stosb\n\t" ··· 70 72 char *strncat(char *dest, const char *src, size_t count) 71 73 { 72 74 int d0, d1, d2, d3; 73 - asm volatile("repne\n\t" 74 - "scasb\n\t" 75 + asm volatile("repne scasb\n\t" 75 76 "decl %1\n\t" 76 77 "movl %8,%3\n" 77 78 "1:\tdecl %3\n\t" ··· 164 167 { 165 168 int d0; 166 169 size_t res; 167 - asm volatile("repne\n\t" 168 - "scasb" 170 + asm volatile("repne scasb" 169 171 : "=c" (res), "=&D" (d0) 170 172 : "1" (s), "a" (0), "0" (0xffffffffu) 171 173 : "memory"); ··· 180 184 void *res; 181 185 if (!count) 182 186 return NULL; 183 - asm volatile("repne\n\t" 184 - "scasb\n\t" 187 + asm volatile("repne scasb\n\t" 185 188 "je 1f\n\t" 186 189 "movl $1,%0\n" 187 190 "1:\tdecl %0" ··· 197 202 { 198 203 if (!size) 199 204 return addr; 200 - asm volatile("repnz; scasb\n\t" 205 + asm volatile("repnz scasb\n\t" 201 206 "jnz 1f\n\t" 202 207 "dec %%edi\n" 203 208 "1:"
+2 -4
arch/x86/lib/strstr_32.c
··· 8 8 register char *__res; 9 9 __asm__ __volatile__( 10 10 "movl %6,%%edi\n\t" 11 - "repne\n\t" 12 - "scasb\n\t" 11 + "repne scasb\n\t" 13 12 "notl %%ecx\n\t" 14 13 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ 15 14 "movl %%ecx,%%edx\n" 16 15 "1:\tmovl %6,%%edi\n\t" 17 16 "movl %%esi,%%eax\n\t" 18 17 "movl %%edx,%%ecx\n\t" 19 - "repe\n\t" 20 - "cmpsb\n\t" 18 + "repe cmpsb\n\t" 21 19 "je 2f\n\t" /* also works for empty string, see above */ 22 20 "xchgl %%eax,%%esi\n\t" 23 21 "incl %%esi\n\t"
+9 -9
arch/x86/lib/usercopy_32.c
··· 38 38 might_fault(); \ 39 39 __asm__ __volatile__( \ 40 40 ASM_STAC "\n" \ 41 - "0: rep; stosl\n" \ 41 + "0: rep stosl\n" \ 42 42 " movl %2,%0\n" \ 43 - "1: rep; stosb\n" \ 43 + "1: rep stosb\n" \ 44 44 "2: " ASM_CLAC "\n" \ 45 45 _ASM_EXTABLE_TYPE_REG(0b, 2b, EX_TYPE_UCOPY_LEN4, %2) \ 46 46 _ASM_EXTABLE_UA(1b, 2b) \ ··· 140 140 " shrl $2, %0\n" 141 141 " andl $3, %%eax\n" 142 142 " cld\n" 143 - "99: rep; movsl\n" 143 + "99: rep movsl\n" 144 144 "36: movl %%eax, %0\n" 145 - "37: rep; movsb\n" 145 + "37: rep movsb\n" 146 146 "100:\n" 147 147 _ASM_EXTABLE_UA(1b, 100b) 148 148 _ASM_EXTABLE_UA(2b, 100b) ··· 242 242 " shrl $2, %0\n" 243 243 " andl $3, %%eax\n" 244 244 " cld\n" 245 - "6: rep; movsl\n" 245 + "6: rep movsl\n" 246 246 " movl %%eax,%0\n" 247 - "7: rep; movsb\n" 247 + "7: rep movsb\n" 248 248 "8:\n" 249 249 _ASM_EXTABLE_UA(0b, 8b) 250 250 _ASM_EXTABLE_UA(1b, 8b) ··· 293 293 " negl %0\n" \ 294 294 " andl $7,%0\n" \ 295 295 " subl %0,%3\n" \ 296 - "4: rep; movsb\n" \ 296 + "4: rep movsb\n" \ 297 297 " movl %3,%0\n" \ 298 298 " shrl $2,%0\n" \ 299 299 " andl $3,%3\n" \ 300 300 " .align 2,0x90\n" \ 301 - "0: rep; movsl\n" \ 301 + "0: rep movsl\n" \ 302 302 " movl %3,%0\n" \ 303 - "1: rep; movsb\n" \ 303 + "1: rep movsb\n" \ 304 304 "2:\n" \ 305 305 _ASM_EXTABLE_TYPE_REG(4b, 2b, EX_TYPE_UCOPY_LEN1, %3) \ 306 306 _ASM_EXTABLE_TYPE_REG(0b, 2b, EX_TYPE_UCOPY_LEN4, %3) \
+1 -2
arch/x86/platform/pvh/head.S
··· 87 87 mov %ebx, %esi 88 88 movl rva(pvh_start_info_sz)(%ebp), %ecx 89 89 shr $2,%ecx 90 - rep 91 - movsl 90 + rep movsl 92 91 93 92 leal rva(early_stack_end)(%ebp), %esp 94 93
+1 -2
arch/x86/power/hibernate_asm_32.S
··· 69 69 movl pbe_orig_address(%edx), %edi 70 70 71 71 movl $(PAGE_SIZE >> 2), %ecx 72 - rep 73 - movsl 72 + rep movsl 74 73 75 74 movl pbe_next(%edx), %edx 76 75 jmp copy_loop
+1 -2
arch/x86/power/hibernate_asm_64.S
··· 138 138 movq pbe_address(%rdx), %rsi 139 139 movq pbe_orig_address(%rdx), %rdi 140 140 movq $(PAGE_SIZE >> 3), %rcx 141 - rep 142 - movsq 141 + rep movsq 143 142 144 143 /* progress to the next pbe */ 145 144 movq pbe_next(%rdx), %rdx