[tip: objtool/core] objtool/x86: Reorder ORC register numbering

From: tip-bot2 for Josh Poimboeuf

Date: Wed Mar 18 2026 - 04:42:04 EST


The following commit has been merged into the objtool/core branch of tip:

Commit-ID: 1735858caa4bbb8b923860c0833d463b5d9c5f79
Gitweb: https://git.kernel.org/tip/1735858caa4bbb8b923860c0833d463b5d9c5f79
Author: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
AuthorDate: Wed, 18 Mar 2026 09:38:38 +01:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Wed, 18 Mar 2026 09:38:52 +01:00

objtool/x86: Reorder ORC register numbering

Reorder the ORC register values so their ordering matches the x86
instruction set register encodings.

No functional change intended.

Suggested-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
arch/x86/include/asm/orc_types.h | 10 +++----
arch/x86/kernel/unwind_orc.c | 30 ++++++++++++---------
tools/arch/x86/include/asm/orc_types.h | 10 +++----
tools/objtool/arch/x86/decode.c | 21 ++++++++-------
tools/objtool/arch/x86/orc.c | 36 ++++++++++++-------------
5 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h
index b3cc797..5837c2b 100644
--- a/arch/x86/include/asm/orc_types.h
+++ b/arch/x86/include/asm/orc_types.h
@@ -28,16 +28,16 @@
* and GCC realigned stacks.
*/
#define ORC_REG_UNDEFINED 0
-#define ORC_REG_PREV_SP 1
+#define ORC_REG_AX 1
#define ORC_REG_DX 2
-#define ORC_REG_DI 3
+#define ORC_REG_SP 3
#define ORC_REG_BP 4
-#define ORC_REG_SP 5
+#define ORC_REG_DI 5
#define ORC_REG_R10 6
#define ORC_REG_R13 7
-#define ORC_REG_BP_INDIRECT 8
+#define ORC_REG_PREV_SP 8
#define ORC_REG_SP_INDIRECT 9
-#define ORC_REG_AX 10
+#define ORC_REG_BP_INDIRECT 10
#define ORC_REG_MAX 15

#define ORC_TYPE_UNDEFINED 0
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index 32f7e91..6407bc9 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -546,17 +546,23 @@ bool unwind_next_frame(struct unwind_state *state)
indirect = true;
break;

- case ORC_REG_R10:
- if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
- orc_warn_current("missing R10 value at %pB\n",
+ /*
+ * Any of the below registers may temporarily hold the stack pointer,
+ * typically during a DRAP stack realignment sequence or some other
+ * stack swizzle.
+ */
+
+ case ORC_REG_AX:
+ if (!get_reg(state, offsetof(struct pt_regs, ax), &sp)) {
+ orc_warn_current("missing AX value at %pB\n",
(void *)state->ip);
goto err;
}
break;

- case ORC_REG_R13:
- if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
- orc_warn_current("missing R13 value at %pB\n",
+ case ORC_REG_DX:
+ if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
+ orc_warn_current("missing DX value at %pB\n",
(void *)state->ip);
goto err;
}
@@ -570,17 +576,17 @@ bool unwind_next_frame(struct unwind_state *state)
}
break;

- case ORC_REG_DX:
- if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
- orc_warn_current("missing DX value at %pB\n",
+ case ORC_REG_R10:
+ if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
+ orc_warn_current("missing R10 value at %pB\n",
(void *)state->ip);
goto err;
}
break;

- case ORC_REG_AX:
- if (!get_reg(state, offsetof(struct pt_regs, ax), &sp)) {
- orc_warn_current("missing AX value at %pB\n",
+ case ORC_REG_R13:
+ if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
+ orc_warn_current("missing R13 value at %pB\n",
(void *)state->ip);
goto err;
}
diff --git a/tools/arch/x86/include/asm/orc_types.h b/tools/arch/x86/include/asm/orc_types.h
index b3cc797..5837c2b 100644
--- a/tools/arch/x86/include/asm/orc_types.h
+++ b/tools/arch/x86/include/asm/orc_types.h
@@ -28,16 +28,16 @@
* and GCC realigned stacks.
*/
#define ORC_REG_UNDEFINED 0
-#define ORC_REG_PREV_SP 1
+#define ORC_REG_AX 1
#define ORC_REG_DX 2
-#define ORC_REG_DI 3
+#define ORC_REG_SP 3
#define ORC_REG_BP 4
-#define ORC_REG_SP 5
+#define ORC_REG_DI 5
#define ORC_REG_R10 6
#define ORC_REG_R13 7
-#define ORC_REG_BP_INDIRECT 8
+#define ORC_REG_PREV_SP 8
#define ORC_REG_SP_INDIRECT 9
-#define ORC_REG_AX 10
+#define ORC_REG_BP_INDIRECT 10
#define ORC_REG_MAX 15

#define ORC_TYPE_UNDEFINED 0
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index c3a10f3..23e48ea 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -891,14 +891,20 @@ int arch_decode_hint_reg(u8 sp_reg, int *base)
case ORC_REG_UNDEFINED:
*base = CFI_UNDEFINED;
break;
+ case ORC_REG_AX:
+ *base = CFI_AX;
+ break;
+ case ORC_REG_DX:
+ *base = CFI_DX;
+ break;
case ORC_REG_SP:
*base = CFI_SP;
break;
case ORC_REG_BP:
*base = CFI_BP;
break;
- case ORC_REG_SP_INDIRECT:
- *base = CFI_SP_INDIRECT;
+ case ORC_REG_DI:
+ *base = CFI_DI;
break;
case ORC_REG_R10:
*base = CFI_R10;
@@ -906,14 +912,11 @@ int arch_decode_hint_reg(u8 sp_reg, int *base)
case ORC_REG_R13:
*base = CFI_R13;
break;
- case ORC_REG_DI:
- *base = CFI_DI;
- break;
- case ORC_REG_DX:
- *base = CFI_DX;
+ case ORC_REG_SP_INDIRECT:
+ *base = CFI_SP_INDIRECT;
break;
- case ORC_REG_AX:
- *base = CFI_AX;
+ case ORC_REG_BP_INDIRECT:
+ *base = CFI_BP_INDIRECT;
break;
default:
return -1;
diff --git a/tools/objtool/arch/x86/orc.c b/tools/objtool/arch/x86/orc.c
index 5494bb4..eff078e 100644
--- a/tools/objtool/arch/x86/orc.c
+++ b/tools/objtool/arch/x86/orc.c
@@ -46,17 +46,20 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct
orc->signal = cfi->signal;

switch (cfi->cfa.base) {
+ case CFI_AX:
+ orc->sp_reg = ORC_REG_AX;
+ break;
+ case CFI_DX:
+ orc->sp_reg = ORC_REG_DX;
+ break;
case CFI_SP:
orc->sp_reg = ORC_REG_SP;
break;
- case CFI_SP_INDIRECT:
- orc->sp_reg = ORC_REG_SP_INDIRECT;
- break;
case CFI_BP:
orc->sp_reg = ORC_REG_BP;
break;
- case CFI_BP_INDIRECT:
- orc->sp_reg = ORC_REG_BP_INDIRECT;
+ case CFI_DI:
+ orc->sp_reg = ORC_REG_DI;
break;
case CFI_R10:
orc->sp_reg = ORC_REG_R10;
@@ -64,14 +67,11 @@ int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruct
case CFI_R13:
orc->sp_reg = ORC_REG_R13;
break;
- case CFI_DI:
- orc->sp_reg = ORC_REG_DI;
- break;
- case CFI_DX:
- orc->sp_reg = ORC_REG_DX;
+ case CFI_SP_INDIRECT:
+ orc->sp_reg = ORC_REG_SP_INDIRECT;
break;
- case CFI_AX:
- orc->sp_reg = ORC_REG_AX;
+ case CFI_BP_INDIRECT:
+ orc->sp_reg = ORC_REG_BP_INDIRECT;
break;
default:
ERROR_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base);
@@ -125,24 +125,24 @@ static const char *reg_name(unsigned int reg)
switch (reg) {
case ORC_REG_PREV_SP:
return "prevsp";
+ case ORC_REG_AX:
+ return "ax";
case ORC_REG_DX:
return "dx";
- case ORC_REG_DI:
- return "di";
case ORC_REG_BP:
return "bp";
case ORC_REG_SP:
return "sp";
+ case ORC_REG_DI:
+ return "di";
case ORC_REG_R10:
return "r10";
case ORC_REG_R13:
return "r13";
- case ORC_REG_BP_INDIRECT:
- return "bp(ind)";
case ORC_REG_SP_INDIRECT:
return "sp(ind)";
- case ORC_REG_AX:
- return "ax";
+ case ORC_REG_BP_INDIRECT:
+ return "bp(ind)";
default:
return "?";
}