mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:38:03 +00:00
a9da824762
VMware high-bandwidth hypercalls take the RBP register as input. This
breaks basic frame pointer convention, as RBP should never be clobbered.
So frame pointer unwinding is broken for the instructions surrounding
the hypercalls. Fortunately this doesn't break live patching with
CONFIG_FRAME_POINTER, as it only unwinds from blocking tasks, and stack
traces from preempted tasks are already marked unreliable anyway.
However, for live patching with ORC, this could actually be a
theoretical problem if vmw_port_hb_{in,out}() were still compiled with a
frame pointer due to having an aligned stack. In practice that hasn't
seemed to be an issue since the objtool warnings have only been seen
with CONFIG_FRAME_POINTER.
Add unwind hint annotations to tell the ORC unwinder to mark stack
traces as unreliable.
Fixes the following warnings:
vmlinux.o: warning: objtool: vmw_port_hb_in+0x1df: return with modified stack frame
vmlinux.o: warning: objtool: vmw_port_hb_out+0x1dd: return with modified stack frame
Fixes: 89da76fde6
("drm/vmwgfx: Add VMWare host messaging capability")
Reported-by: kernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/oe-kbuild-all/202305160135.97q0Elax-lkp@intel.com/
Link: https://lore.kernel.org/r/4c795f2d87bc0391cf6543bcb224fa540b55ce4b.1685981486.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
94 lines
2.0 KiB
C
94 lines
2.0 KiB
C
#ifndef _ASM_X86_UNWIND_HINTS_H
|
|
#define _ASM_X86_UNWIND_HINTS_H
|
|
|
|
#include <linux/objtool.h>
|
|
|
|
#include "orc_types.h"
|
|
|
|
#ifdef __ASSEMBLY__
|
|
|
|
.macro UNWIND_HINT_END_OF_STACK
|
|
UNWIND_HINT type=UNWIND_HINT_TYPE_END_OF_STACK
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_UNDEFINED
|
|
UNWIND_HINT type=UNWIND_HINT_TYPE_UNDEFINED
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_ENTRY
|
|
VALIDATE_UNRET_BEGIN
|
|
UNWIND_HINT_END_OF_STACK
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0 signal=1
|
|
.if \base == %rsp
|
|
.if \indirect
|
|
.set sp_reg, ORC_REG_SP_INDIRECT
|
|
.else
|
|
.set sp_reg, ORC_REG_SP
|
|
.endif
|
|
.elseif \base == %rbp
|
|
.set sp_reg, ORC_REG_BP
|
|
.elseif \base == %rdi
|
|
.set sp_reg, ORC_REG_DI
|
|
.elseif \base == %rdx
|
|
.set sp_reg, ORC_REG_DX
|
|
.elseif \base == %r10
|
|
.set sp_reg, ORC_REG_R10
|
|
.else
|
|
.error "UNWIND_HINT_REGS: bad base register"
|
|
.endif
|
|
|
|
.set sp_offset, \offset
|
|
|
|
.if \partial
|
|
.set type, UNWIND_HINT_TYPE_REGS_PARTIAL
|
|
.elseif \extra == 0
|
|
.set type, UNWIND_HINT_TYPE_REGS_PARTIAL
|
|
.set sp_offset, \offset + (16*8)
|
|
.else
|
|
.set type, UNWIND_HINT_TYPE_REGS
|
|
.endif
|
|
|
|
UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type signal=\signal
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0 signal=1
|
|
UNWIND_HINT_REGS base=\base offset=\offset partial=1 signal=\signal
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_IRET_ENTRY base=%rsp offset=0 signal=1
|
|
VALIDATE_UNRET_BEGIN
|
|
UNWIND_HINT_IRET_REGS base=\base offset=\offset signal=\signal
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_FUNC
|
|
UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=8 type=UNWIND_HINT_TYPE_FUNC
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_SAVE
|
|
UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE
|
|
.endm
|
|
|
|
.macro UNWIND_HINT_RESTORE
|
|
UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
|
|
.endm
|
|
|
|
#else
|
|
|
|
#define UNWIND_HINT_UNDEFINED \
|
|
UNWIND_HINT(UNWIND_HINT_TYPE_UNDEFINED, 0, 0, 0)
|
|
|
|
#define UNWIND_HINT_FUNC \
|
|
UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0)
|
|
|
|
#define UNWIND_HINT_SAVE \
|
|
UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0)
|
|
|
|
#define UNWIND_HINT_RESTORE \
|
|
UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0)
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* _ASM_X86_UNWIND_HINTS_H */
|