]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/extable: switch to using FIELD_GET_SIGNED()
authorYury Norov <ynorov@nvidia.com>
Mon, 27 Apr 2026 21:41:19 +0000 (17:41 -0400)
committerYury Norov <ynorov@nvidia.com>
Wed, 20 May 2026 15:18:27 +0000 (11:18 -0400)
The EX_DATA register is laid out such that EX_DATA_IMM occupied MSB.
It's done to make sure that FIELD_GET() will sign-extend the IMM
field during extraction.

To enforce that, all EX_DATA masks are made signed integers. This
works, but relies on the particular implementation of FIELD_GET(),
i.e. masking then shifting, not vice versa; and the particular
placement of the fields in the register.

Switch to using the dedicated FIELD_GET_SIGNED(), and relax those
limitations.

Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
arch/x86/include/asm/extable_fixup_types.h
arch/x86/mm/extable.c

index 906b0d5541e896fc4f24bd2306607e3a8838483d..fd0cfb47210390ed610ecae0d9f2e70fd1d8b0a8 100644 (file)
@@ -2,15 +2,10 @@
 #ifndef _ASM_X86_EXTABLE_FIXUP_TYPES_H
 #define _ASM_X86_EXTABLE_FIXUP_TYPES_H
 
-/*
- * Our IMM is signed, as such it must live at the top end of the word. Also,
- * since C99 hex constants are of ambiguous type, force cast the mask to 'int'
- * so that FIELD_GET() will DTRT and sign extend the value when it extracts it.
- */
-#define EX_DATA_TYPE_MASK              ((int)0x000000FF)
-#define EX_DATA_REG_MASK               ((int)0x00000F00)
-#define EX_DATA_FLAG_MASK              ((int)0x0000F000)
-#define EX_DATA_IMM_MASK               ((int)0xFFFF0000)
+#define EX_DATA_TYPE_MASK              (0x000000FF)
+#define EX_DATA_REG_MASK               (0x00000F00)
+#define EX_DATA_FLAG_MASK              (0x0000F000)
+#define EX_DATA_IMM_MASK               (0xFFFF0000)
 
 #define EX_DATA_REG_SHIFT              8
 #define EX_DATA_FLAG_SHIFT             12
index 6b9ff1c6cafa27e822c3bb6a2988d67152e14e8f..ceb8d03191ab2c7e3abac3c9eafe7397fd606ea6 100644 (file)
@@ -322,7 +322,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
 
        type = FIELD_GET(EX_DATA_TYPE_MASK, e->data);
        reg  = FIELD_GET(EX_DATA_REG_MASK,  e->data);
-       imm  = FIELD_GET(EX_DATA_IMM_MASK,  e->data);
+       imm  = FIELD_GET_SIGNED(EX_DATA_IMM_MASK, e->data);
 
        switch (type) {
        case EX_TYPE_DEFAULT: