x86/alternatives: Add longer 64-bit NOPs
authorPeter Zijlstra <peterz@infradead.org>
Mon, 15 May 2023 09:28:05 +0000 (11:28 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Wed, 31 May 2023 08:21:21 +0000 (10:21 +0200)
By adding support for longer NOPs there are a few more alternatives
that can turn into a single instruction.

Add up to NOP11, the same limit where GNU as .nops also stops
generating longer nops. This is because a number of uarchs have severe
decode penalties for more than 3 prefixes.

  [ bp: Sync up with the version in tools/ while at it. ]

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230515093020.661756940@infradead.org
arch/x86/include/asm/nops.h
arch/x86/kernel/alternative.c
tools/arch/x86/include/asm/nops.h

index c5573ea..1c1b755 100644 (file)
@@ -34,6 +34,8 @@
 #define BYTES_NOP7     0x8d,0xb4,0x26,0x00,0x00,0x00,0x00
 #define BYTES_NOP8     0x3e,BYTES_NOP7
 
+#define ASM_NOP_MAX 8
+
 #else
 
 /*
@@ -47,6 +49,9 @@
  * 6: osp nopl 0x00(%eax,%eax,1)
  * 7: nopl 0x00000000(%eax)
  * 8: nopl 0x00000000(%eax,%eax,1)
+ * 9: cs nopl 0x00000000(%eax,%eax,1)
+ * 10: osp cs nopl 0x00000000(%eax,%eax,1)
+ * 11: osp osp cs nopl 0x00000000(%eax,%eax,1)
  */
 #define BYTES_NOP1     0x90
 #define BYTES_NOP2     0x66,BYTES_NOP1
 #define BYTES_NOP6     0x66,BYTES_NOP5
 #define BYTES_NOP7     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00
 #define BYTES_NOP8     0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00
+#define BYTES_NOP9     0x2e,BYTES_NOP8
+#define BYTES_NOP10    0x66,BYTES_NOP9
+#define BYTES_NOP11    0x66,BYTES_NOP10
+
+#define ASM_NOP9  _ASM_BYTES(BYTES_NOP9)
+#define ASM_NOP10 _ASM_BYTES(BYTES_NOP10)
+#define ASM_NOP11 _ASM_BYTES(BYTES_NOP11)
+
+#define ASM_NOP_MAX 11
 
 #endif /* CONFIG_64BIT */
 
@@ -68,8 +82,6 @@
 #define ASM_NOP7 _ASM_BYTES(BYTES_NOP7)
 #define ASM_NOP8 _ASM_BYTES(BYTES_NOP8)
 
-#define ASM_NOP_MAX 8
-
 #ifndef __ASSEMBLY__
 extern const unsigned char * const x86_nops[];
 #endif
index 93aa95a..0747d29 100644 (file)
@@ -98,6 +98,11 @@ static const unsigned char x86nops[] =
        BYTES_NOP6,
        BYTES_NOP7,
        BYTES_NOP8,
+#ifdef CONFIG_64BIT
+       BYTES_NOP9,
+       BYTES_NOP10,
+       BYTES_NOP11,
+#endif
 };
 
 const unsigned char * const x86_nops[ASM_NOP_MAX+1] =
@@ -111,6 +116,11 @@ const unsigned char * const x86_nops[ASM_NOP_MAX+1] =
        x86nops + 1 + 2 + 3 + 4 + 5,
        x86nops + 1 + 2 + 3 + 4 + 5 + 6,
        x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+#ifdef CONFIG_64BIT
+       x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
+       x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9,
+       x86nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10,
+#endif
 };
 
 /*
index c5573ea..1c1b755 100644 (file)
@@ -34,6 +34,8 @@
 #define BYTES_NOP7     0x8d,0xb4,0x26,0x00,0x00,0x00,0x00
 #define BYTES_NOP8     0x3e,BYTES_NOP7
 
+#define ASM_NOP_MAX 8
+
 #else
 
 /*
@@ -47,6 +49,9 @@
  * 6: osp nopl 0x00(%eax,%eax,1)
  * 7: nopl 0x00000000(%eax)
  * 8: nopl 0x00000000(%eax,%eax,1)
+ * 9: cs nopl 0x00000000(%eax,%eax,1)
+ * 10: osp cs nopl 0x00000000(%eax,%eax,1)
+ * 11: osp osp cs nopl 0x00000000(%eax,%eax,1)
  */
 #define BYTES_NOP1     0x90
 #define BYTES_NOP2     0x66,BYTES_NOP1
 #define BYTES_NOP6     0x66,BYTES_NOP5
 #define BYTES_NOP7     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00
 #define BYTES_NOP8     0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00
+#define BYTES_NOP9     0x2e,BYTES_NOP8
+#define BYTES_NOP10    0x66,BYTES_NOP9
+#define BYTES_NOP11    0x66,BYTES_NOP10
+
+#define ASM_NOP9  _ASM_BYTES(BYTES_NOP9)
+#define ASM_NOP10 _ASM_BYTES(BYTES_NOP10)
+#define ASM_NOP11 _ASM_BYTES(BYTES_NOP11)
+
+#define ASM_NOP_MAX 11
 
 #endif /* CONFIG_64BIT */
 
@@ -68,8 +82,6 @@
 #define ASM_NOP7 _ASM_BYTES(BYTES_NOP7)
 #define ASM_NOP8 _ASM_BYTES(BYTES_NOP8)
 
-#define ASM_NOP_MAX 8
-
 #ifndef __ASSEMBLY__
 extern const unsigned char * const x86_nops[];
 #endif