Merge tag 'x86_core_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2022 01:42:07 +0000 (18:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 May 2022 01:42:07 +0000 (18:42 -0700)
Pull core x86 updates from Borislav Petkov:

 - Remove all the code around GS switching on 32-bit now that it is not
   needed anymore

 - Other misc improvements

* tag 'x86_core_for_v5.19_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  bug: Use normal relative pointers in 'struct bug_entry'
  x86/nmi: Make register_nmi_handler() more robust
  x86/asm: Merge load_gs_index()
  x86/32: Remove lazy GS macros
  ELF: Remove elf_core_copy_kernel_regs()
  x86/32: Simplify ELF_CORE_COPY_REGS

23 files changed:
arch/arm64/include/asm/asm-bug.h
arch/powerpc/include/asm/bug.h
arch/powerpc/kernel/fadump.c
arch/powerpc/platforms/powernv/opal-core.c
arch/riscv/include/asm/bug.h
arch/s390/include/asm/bug.h
arch/x86/include/asm/bug.h
arch/x86/include/asm/elf.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/nmi.h
arch/x86/include/asm/segment.h
arch/x86/include/asm/special_insns.h
arch/x86/kernel/nmi.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/signal.c
arch/x86/kernel/vm86_32.c
arch/x86/lib/insn-eval.c
arch/x86/math-emu/get_address.c
include/linux/elfcore.h
kernel/kexec_core.c
lib/bug.c

index 03f52f84a4f3f8a23d8e825ee1b64b321fdf59f7..c762038ba40093c9690d1eae8e3d6ab38d71d5d7 100644 (file)
@@ -14,7 +14,7 @@
        14472:  .string file;                                   \
                .popsection;                                    \
                                                                \
-               .long 14472b - 14470b;                          \
+               .long 14472b - .;                               \
                .short line;
 #else
 #define _BUGVERBOSE_LOCATION(file, line)
@@ -25,7 +25,7 @@
 #define __BUG_ENTRY(flags)                             \
                .pushsection __bug_table,"aw";          \
                .align 2;                               \
-       14470:  .long 14471f - 14470b;                  \
+       14470:  .long 14471f - .;                       \
 _BUGVERBOSE_LOCATION(__FILE__, __LINE__)               \
                .short flags;                           \
                .popsection;                            \
index ecbae1832de31ffd540ccaaf085d288d478c83ab..61a4736355c244448104080e144631a3cb8839b2 100644 (file)
@@ -13,7 +13,8 @@
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 .macro __EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
-5001:   .4byte \addr - 5001b, 5002f - 5001b
+5001:   .4byte \addr - .
+        .4byte 5002f - .
         .short \line, \flags
         .org 5001b+BUG_ENTRY_SIZE
         .previous
@@ -24,7 +25,7 @@
 #else
 .macro __EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
-5001:   .4byte \addr - 5001b
+5001:   .4byte \addr - .
         .short \flags
         .org 5001b+BUG_ENTRY_SIZE
         .previous
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #define _EMIT_BUG_ENTRY                                \
        ".section __bug_table,\"aw\"\n"         \
-       "2:\t.4byte 1b - 2b, %0 - 2b\n"         \
-       "\t.short %1, %2\n"                     \
+       "2:     .4byte 1b - .\n"                \
+       "       .4byte %0 - .\n"                \
+       "       .short %1, %2\n"                \
        ".org 2b+%3\n"                          \
        ".previous\n"
 #else
 #define _EMIT_BUG_ENTRY                                \
        ".section __bug_table,\"aw\"\n"         \
-       "2:\t.4byte 1b - 2b\n"                  \
-       "\t.short %2\n"                         \
+       "2:     .4byte 1b - .\n"                \
+       "       .short %2\n"                    \
        ".org 2b+%3\n"                          \
        ".previous\n"
 #endif
index 65562c4a0a690b7672eddacfe81c2ecda083fcd7..4c09c6688ac6685665ddfc82aef3376a52b366d9 100644 (file)
@@ -752,7 +752,7 @@ u32 *__init fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs)
         * FIXME: How do i get PID? Do I really need it?
         * prstatus.pr_pid = ????
         */
-       elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
+       elf_core_copy_regs(&prstatus.pr_reg, regs);
        buf = append_elf_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS,
                              &prstatus, sizeof(prstatus));
        return buf;
index b97bc179f65ad25f5018060aed91f0a8ef13a914..adcb1a1a2bfe805519e1774101ecdc5c5eb913c9 100644 (file)
@@ -112,7 +112,7 @@ static void __init fill_prstatus(struct elf_prstatus *prstatus, int pir,
                          struct pt_regs *regs)
 {
        memset(prstatus, 0, sizeof(struct elf_prstatus));
-       elf_core_copy_kernel_regs(&(prstatus->pr_reg), regs);
+       elf_core_copy_regs(&(prstatus->pr_reg), regs);
 
        /*
         * Overload PID with PIR value.
index d3804a2f9aad33fb8089691ca5f5ccd847452b51..1aaea81fb1413eeb87dc23cbd9346055fb6f6ef8 100644 (file)
@@ -30,8 +30,8 @@
 typedef u32 bug_insn_t;
 
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
-#define __BUG_ENTRY_ADDR       RISCV_INT " 1b - 2b"
-#define __BUG_ENTRY_FILE       RISCV_INT " %0 - 2b"
+#define __BUG_ENTRY_ADDR       RISCV_INT " 1b - ."
+#define __BUG_ENTRY_FILE       RISCV_INT " %0 - ."
 #else
 #define __BUG_ENTRY_ADDR       RISCV_PTR " 1b"
 #define __BUG_ENTRY_FILE       RISCV_PTR " %0"
index 0b25f28351edc496ddfe728b169a4700e724cd7f..aebe1e22c7befa486bbe269383164f9a792b5c89 100644 (file)
@@ -15,7 +15,8 @@
                "1:     .asciz  \""__FILE__"\"\n"               \
                ".previous\n"                                   \
                ".section __bug_table,\"awM\",@progbits,%2\n"   \
-               "2:     .long   0b-2b,1b-2b\n"                  \
+               "2:     .long   0b-.\n"                         \
+               "       .long   1b-.\n"                         \
                "       .short  %0,%1\n"                        \
                "       .org    2b+%2\n"                        \
                ".previous\n"                                   \
@@ -30,7 +31,7 @@
        asm_inline volatile(                                    \
                "0:     mc      0,0\n"                          \
                ".section __bug_table,\"awM\",@progbits,%1\n"   \
-               "1:     .long   0b-1b\n"                        \
+               "1:     .long   0b-.\n"                         \
                "       .short  %0\n"                           \
                "       .org    1b+%1\n"                        \
                ".previous\n"                                   \
index aaf0cb0db4aecfebc103498e1f2f8106f5b52733..a3ec87d198ac8398309e2962b5bcc59eeb074692 100644 (file)
@@ -18,7 +18,7 @@
 #ifdef CONFIG_X86_32
 # define __BUG_REL(val)        ".long " __stringify(val)
 #else
-# define __BUG_REL(val)        ".long " __stringify(val) " - 2b"
+# define __BUG_REL(val)        ".long " __stringify(val) " - ."
 #endif
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
index 29fea180a6658e84bd0a094d4e767558cc91b4e1..cb0ff1055ab1632f0c22b1f470ea8d0e57a23ffd 100644 (file)
@@ -116,7 +116,7 @@ extern unsigned int vdso32_enabled;
  * now struct_user_regs, they are different)
  */
 
-#define ELF_CORE_COPY_REGS_COMMON(pr_reg, regs)        \
+#define ELF_CORE_COPY_REGS(pr_reg, regs)       \
 do {                                           \
        pr_reg[0] = regs->bx;                   \
        pr_reg[1] = regs->cx;                   \
@@ -128,6 +128,7 @@ do {                                                \
        pr_reg[7] = regs->ds;                   \
        pr_reg[8] = regs->es;                   \
        pr_reg[9] = regs->fs;                   \
+       savesegment(gs, pr_reg[10]);            \
        pr_reg[11] = regs->orig_ax;             \
        pr_reg[12] = regs->ip;                  \
        pr_reg[13] = regs->cs;                  \
@@ -136,18 +137,6 @@ do {                                               \
        pr_reg[16] = regs->ss;                  \
 } while (0);
 
-#define ELF_CORE_COPY_REGS(pr_reg, regs)       \
-do {                                           \
-       ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\
-       pr_reg[10] = get_user_gs(regs);         \
-} while (0);
-
-#define ELF_CORE_COPY_KERNEL_REGS(pr_reg, regs)        \
-do {                                           \
-       ELF_CORE_COPY_REGS_COMMON(pr_reg, regs);\
-       savesegment(gs, pr_reg[10]);            \
-} while (0);
-
 #define ELF_PLATFORM   (utsname()->machine)
 #define set_personality_64bit()        do { } while (0)
 
index 27516046117a389a80b962579b8c42e6f17e67b9..b8d40ddeab00f9b3989962d095c8d62f73a2d3dc 100644 (file)
@@ -141,7 +141,7 @@ do {                                                \
 #ifdef CONFIG_X86_32
 #define deactivate_mm(tsk, mm)                 \
 do {                                           \
-       lazy_load_gs(0);                        \
+       loadsegment(gs, 0);                     \
 } while (0)
 #else
 #define deactivate_mm(tsk, mm)                 \
index 1cb9c17a4cb4b1fba49646749ee2a6400ab6fb93..5c5f1e56c4048db1a725b450e6f700b484d150d2 100644 (file)
@@ -47,6 +47,7 @@ struct nmiaction {
 #define register_nmi_handler(t, fn, fg, n, init...)    \
 ({                                                     \
        static struct nmiaction init fn##_na = {        \
+               .list = LIST_HEAD_INIT(fn##_na.list),   \
                .handler = (fn),                        \
                .name = (n),                            \
                .flags = (fg),                          \
index 656ed6531d035d20d9aed5aaaddc79a32b065619..2e7890dd58a47714fbba4bbddb68e05605835ee5 100644 (file)
@@ -350,18 +350,6 @@ static inline void __loadsegment_fs(unsigned short value)
 #define savesegment(seg, value)                                \
        asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
 
-/*
- * x86-32 user GS accessors.  This is ugly and could do with some cleaning up.
- */
-#ifdef CONFIG_X86_32
-# define get_user_gs(regs)             (u16)({ unsigned long v; savesegment(gs, v); v; })
-# define set_user_gs(regs, v)          loadsegment(gs, (unsigned long)(v))
-# define task_user_gs(tsk)             ((tsk)->thread.gs)
-# define lazy_save_gs(v)               savesegment(gs, (v))
-# define lazy_load_gs(v)               loadsegment(gs, (v))
-# define load_gs_index(v)              loadsegment(gs, (v))
-#endif /* X86_32 */
-
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
index 68c257a3de0d393b9ba904526fb485bb5f12ab38..45b18eb94fa1a854933f78ed6df4371d4855bb4d 100644 (file)
@@ -184,14 +184,15 @@ static inline void wbinvd(void)
        native_wbinvd();
 }
 
-#ifdef CONFIG_X86_64
 
 static inline void load_gs_index(unsigned int selector)
 {
+#ifdef CONFIG_X86_64
        native_load_gs_index(selector);
-}
-
+#else
+       loadsegment(gs, selector);
 #endif
+}
 
 #endif /* CONFIG_PARAVIRT_XXL */
 
index e73f7df362f5d178b008dc8e15ff4eb6d4f7af5e..cec0bfa3bc04fa21fbf741d5c6fca0464956bf1d 100644 (file)
@@ -157,7 +157,7 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action)
        struct nmi_desc *desc = nmi_to_desc(type);
        unsigned long flags;
 
-       if (!action->handler)
+       if (WARN_ON_ONCE(!action->handler || !list_empty(&action->list)))
                return -EINVAL;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
@@ -177,7 +177,7 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action)
                list_add_rcu(&action->list, &desc->head);
        else
                list_add_tail_rcu(&action->list, &desc->head);
-       
+
        raw_spin_unlock_irqrestore(&desc->lock, flags);
        return 0;
 }
@@ -186,7 +186,7 @@ EXPORT_SYMBOL(__register_nmi_handler);
 void unregister_nmi_handler(unsigned int type, const char *name)
 {
        struct nmi_desc *desc = nmi_to_desc(type);
-       struct nmiaction *n;
+       struct nmiaction *n, *found = NULL;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
@@ -200,12 +200,16 @@ void unregister_nmi_handler(unsigned int type, const char *name)
                        WARN(in_nmi(),
                                "Trying to free NMI (%s) from NMI context!\n", n->name);
                        list_del_rcu(&n->list);
+                       found = n;
                        break;
                }
        }
 
        raw_spin_unlock_irqrestore(&desc->lock, flags);
-       synchronize_rcu();
+       if (found) {
+               synchronize_rcu();
+               INIT_LIST_HEAD(&found->list);
+       }
 }
 EXPORT_SYMBOL_GPL(unregister_nmi_handler);
 
index d5275ecb1e92a3b17feef9e109b7104a988301ff..cbe6aa3f649d8415cded6748a1eb8a45b4d730e5 100644 (file)
@@ -161,6 +161,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
        savesegment(ds, p->thread.ds);
 #else
        p->thread.sp0 = (unsigned long) (childregs + 1);
+       savesegment(gs, p->thread.gs);
        /*
         * Clear all status flags including IF and set fixed bit. 64bit
         * does not have this initialization as the frame does not contain
@@ -192,10 +193,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
        if (sp)
                childregs->sp = sp;
 
-#ifdef CONFIG_X86_32
-       task_user_gs(p) = get_user_gs(current_pt_regs());
-#endif
-
        if (unlikely(p->flags & PF_IO_WORKER)) {
                /*
                 * An IO thread is a user space thread, but it doesn't
index 0faa5e28dd64eb713a6d99a113e91e205cd2729e..2f314b170c9f0737d6ee673ed380d894a6978911 100644 (file)
@@ -63,10 +63,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
        unsigned long d0, d1, d2, d3, d6, d7;
        unsigned short gs;
 
-       if (user_mode(regs))
-               gs = get_user_gs(regs);
-       else
-               savesegment(gs, gs);
+       savesegment(gs, gs);
 
        show_ip(regs, log_lvl);
 
@@ -114,7 +111,7 @@ void release_thread(struct task_struct *dead_task)
 void
 start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 {
-       set_user_gs(regs, 0);
+       loadsegment(gs, 0);
        regs->fs                = 0;
        regs->ds                = __USER_DS;
        regs->es                = __USER_DS;
@@ -177,7 +174,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
         * used %fs or %gs (it does not today), or if the kernel is
         * running inside of a hypervisor layer.
         */
-       lazy_save_gs(prev->gs);
+       savesegment(gs, prev->gs);
 
        /*
         * Load the per-thread Thread-Local Storage descriptor.
@@ -208,7 +205,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
         * Restore %gs if needed (which is common)
         */
        if (prev->gs | next->gs)
-               lazy_load_gs(next->gs);
+               loadsegment(gs, next->gs);
 
        this_cpu_write(current_task, next_p);
 
index 98d10ef605717820e802540b86fdb5c1b051bd38..37c12fb92906b64cfb2e0b7e96a20a2ffa57cfca 100644 (file)
@@ -170,9 +170,9 @@ static u16 get_segment_reg(struct task_struct *task, unsigned long offset)
                retval = *pt_regs_access(task_pt_regs(task), offset);
        else {
                if (task == current)
-                       retval = get_user_gs(task_pt_regs(task));
+                       savesegment(gs, retval);
                else
-                       retval = task_user_gs(task);
+                       retval = task->thread.gs;
        }
        return retval;
 }
@@ -210,7 +210,7 @@ static int set_segment_reg(struct task_struct *task,
                break;
 
        case offsetof(struct user_regs_struct, gs):
-               task_user_gs(task) = value;
+               task->thread.gs = value;
        }
 
        return 0;
index e439eb14325fa131057e93426e5f78aacad96262..9c7265b524c73ac26c0bf419ab2d0a0d5745d3bf 100644 (file)
@@ -93,7 +93,7 @@ static bool restore_sigcontext(struct pt_regs *regs,
                return false;
 
 #ifdef CONFIG_X86_32
-       set_user_gs(regs, sc.gs);
+       loadsegment(gs, sc.gs);
        regs->fs = sc.fs;
        regs->es = sc.es;
        regs->ds = sc.ds;
@@ -146,8 +146,10 @@ __unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
                     struct pt_regs *regs, unsigned long mask)
 {
 #ifdef CONFIG_X86_32
-       unsafe_put_user(get_user_gs(regs),
-                                 (unsigned int __user *)&sc->gs, Efault);
+       unsigned int gs;
+       savesegment(gs, gs);
+
+       unsafe_put_user(gs,       (unsigned int __user *)&sc->gs, Efault);
        unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault);
        unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault);
        unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault);
index c21bcd668284259d8f8833205a936106a8010af6..e9e803a4d44cf6ffe8938071a18b305feafdbf81 100644 (file)
@@ -151,7 +151,7 @@ exit_vm86:
 
        memcpy(&regs->pt, &vm86->regs32, sizeof(struct pt_regs));
 
-       lazy_load_gs(vm86->regs32.gs);
+       loadsegment(gs, vm86->regs32.gs);
 
        regs->pt.ax = retval;
        return;
@@ -325,7 +325,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
  * Save old state
  */
        vm86->saved_sp0 = tsk->thread.sp0;
-       lazy_save_gs(vm86->regs32.gs);
+       savesegment(gs, vm86->regs32.gs);
 
        /* make room for real-mode segments */
        preempt_disable();
index b781d324211bb7ab91b506ea3bf847a7e854d330..21104c41cba04868e54d14f93a3592b9fa2541ba 100644 (file)
@@ -342,9 +342,9 @@ static int resolve_seg_reg(struct insn *insn, struct pt_regs *regs, int regoff)
  */
 static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx)
 {
-#ifdef CONFIG_X86_64
        unsigned short sel;
 
+#ifdef CONFIG_X86_64
        switch (seg_reg_idx) {
        case INAT_SEG_REG_IGNORE:
                return 0;
@@ -402,7 +402,8 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx)
        case INAT_SEG_REG_FS:
                return (unsigned short)(regs->fs & 0xffff);
        case INAT_SEG_REG_GS:
-               return get_user_gs(regs);
+               savesegment(gs, sel);
+               return sel;
        case INAT_SEG_REG_IGNORE:
        default:
                return -EINVAL;
index b82ca14ba71826a247268de49e4a8d22d81b216b..4a9fd9029a53646c6ecfc14aad4d07a2e5bedb52 100644 (file)
@@ -153,7 +153,7 @@ static long pm_address(u_char FPU_modrm, u_char segment,
        switch (segment) {
        case PREFIX_GS_ - 1:
                /* user gs handling can be lazy, use special accessors */
-               addr->selector = get_user_gs(FPU_info->regs);
+               savesegment(gs, addr->selector);
                break;
        default:
                addr->selector = PM_REG_(segment);
index f8e206e82476c30f067ac96f0ca4036dc693638c..346a8b56cdc831f798b0c59eab56160446d6de74 100644 (file)
@@ -84,15 +84,6 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *re
 #endif
 }
 
-static inline void elf_core_copy_kernel_regs(elf_gregset_t *elfregs, struct pt_regs *regs)
-{
-#ifdef ELF_CORE_COPY_KERNEL_REGS
-       ELF_CORE_COPY_KERNEL_REGS((*elfregs), regs);
-#else
-       elf_core_copy_regs(elfregs, regs);
-#endif
-}
-
 static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs)
 {
 #if defined (ELF_CORE_COPY_TASK_REGS)
index 68480f731192ebe325f607953dbdcc70d2dfbe18..be4b54c2c615c696c6533fb388dc32e4473c5e7f 100644 (file)
@@ -1078,7 +1078,7 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
                return;
        memset(&prstatus, 0, sizeof(prstatus));
        prstatus.common.pr_pid = current->pid;
-       elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
+       elf_core_copy_regs(&prstatus.pr_reg, regs);
        buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
                              &prstatus, sizeof(prstatus));
        final_note(buf);
index 45a0584f65417e97e1664644b1a21195fd4b231c..c223a2575b7217f8f61ea422b5a93e642afa9505 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -6,8 +6,7 @@
 
   CONFIG_BUG - emit BUG traps.  Nothing happens without this.
   CONFIG_GENERIC_BUG - enable this code.
-  CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit pointers relative to
-       the containing struct bug_entry for bug_addr and file.
+  CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit relative pointers for bug_addr and file
   CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
 
   CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
@@ -53,10 +52,10 @@ extern struct bug_entry __start___bug_table[], __stop___bug_table[];
 
 static inline unsigned long bug_addr(const struct bug_entry *bug)
 {
-#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
-       return bug->bug_addr;
+#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
+       return (unsigned long)&bug->bug_addr_disp + bug->bug_addr_disp;
 #else
-       return (unsigned long)bug + bug->bug_addr_disp;
+       return bug->bug_addr;
 #endif
 }
 
@@ -131,10 +130,10 @@ void bug_get_file_line(struct bug_entry *bug, const char **file,
                       unsigned int *line)
 {
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
-       *file = bug->file;
+#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
+       *file = (const char *)&bug->file_disp + bug->file_disp;
 #else
-       *file = (const char *)bug + bug->file_disp;
+       *file = bug->file;
 #endif
        *line = bug->line;
 #else