From: Alexandre Chartre <alexandre.chartre@oracle.com>
To: linux-kernel@vger.kernel.org, mingo@kernel.org,
jpoimboe@kernel.org, peterz@infradead.org
Cc: alexandre.chartre@oracle.com
Subject: [PATCH v3 27/28] objtool: Improve the disassembly of the pv_ops call
Date: Wed, 12 Nov 2025 17:03:14 +0100 [thread overview]
Message-ID: <20251112160315.2207947-28-alexandre.chartre@oracle.com> (raw)
In-Reply-To: <20251112160315.2207947-1-alexandre.chartre@oracle.com>
When using the --disas option, print the destination name of pv_ops
calls when we can figure out if XENPV mode is used or not. If the
PV mode can't be predicted when print the default pv_ops destination
as a destination example.
Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
---
tools/objtool/disas.c | 101 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 89 insertions(+), 12 deletions(-)
diff --git a/tools/objtool/disas.c b/tools/objtool/disas.c
index 2a6c3708ec315..20d64b58182ce 100644
--- a/tools/objtool/disas.c
+++ b/tools/objtool/disas.c
@@ -12,6 +12,7 @@
#include <objtool/special.h>
#include <objtool/warn.h>
+#include <asm/cpufeatures.h>
#include <bfd.h>
#include <linux/string.h>
#include <tools/dis-asm-compat.h>
@@ -54,6 +55,7 @@ struct disas_alt {
int offset; /* instruction offset */
} insn[DISAS_ALT_INSN_MAX]; /* alternative instructions */
int insn_idx; /* index of the next instruction to print */
+ int pv_mode; /* PV mode */
};
#define DALT_DEFAULT(dalt) (!(dalt)->alt)
@@ -665,13 +667,65 @@ char *disas_alt_name(struct alternative *alt)
return str;
}
+/*
+ * Set the PV mode for the current alternative and return the PV mode
+ * to use for next alternatives.
+ */
+static enum pv_mode disas_alt_set_pvmode(struct disas_alt *dalt,
+ enum pv_mode pv_mode)
+{
+ struct alt_group *alt_group;
+ int feature;
+ int flags;
+
+ dalt->pv_mode = pv_mode;
+
+ alt_group = DALT_GROUP(dalt);
+ if (!alt_group)
+ return pv_mode;
+
+ feature = alt_feature(alt_group->feature);
+ flags = alt_flags(alt_group->feature);
+
+ /*
+ * The only PV mode we identify is the XENPV mode which is
+ * enabled with the X86_FEATURE_XENPV feature. When we are
+ * sure that XENPV mode is not used then assume that the
+ * default PV mode is used.
+ */
+ if (feature != X86_FEATURE_XENPV)
+ return pv_mode;
+
+ if (flags & ALT_FLAG_NOT) {
+ /*
+ * This alternative is not used with XENPV mode, so
+ * it is used in default mode. Then next alternatives
+ * will be used in XENPV mode.
+ */
+ dalt->pv_mode = PV_MODE_DEFAULT;
+ pv_mode = PV_MODE_XENPV;
+ } else {
+ /*
+ * This alternative is used with XENPV mode so next
+ * alternatives will apply in default mode.
+ */
+ dalt->pv_mode = PV_MODE_XENPV;
+ pv_mode = PV_MODE_DEFAULT;
+ }
+
+ return pv_mode;
+}
+
/*
* Initialize an alternative. The default alternative should be initialized
* with alt=NULL.
+ *
+ * Return the PV mode to use for the next alternative or -1 on error.
*/
-static int disas_alt_init(struct disas_alt *dalt,
- struct instruction *orig_insn,
- struct alternative *alt)
+static enum pv_mode disas_alt_init(struct disas_alt *dalt,
+ struct instruction *orig_insn,
+ struct alternative *alt,
+ enum pv_mode pv_mode)
{
dalt->orig_insn = orig_insn;
dalt->alt = alt;
@@ -682,7 +736,7 @@ static int disas_alt_init(struct disas_alt *dalt,
return -1;
dalt->width = strlen(dalt->name);
- return 0;
+ return disas_alt_set_pvmode(dalt, pv_mode);
}
static int disas_alt_add_insn(struct disas_alt *dalt, int index, char *insn_str,
@@ -753,27 +807,50 @@ static int disas_alt_extable(struct disas_alt *dalt)
return 1;
}
+static bool disas_alt_is_direct_call(struct instruction *insn)
+{
+ return (insn->alt_group &&
+ (alt_flags(insn->alt_group->feature) & ALT_FLAG_DIRECT_CALL));
+}
+
/*
* Disassemble an alternative and store instructions in the disas_alt
* structure. Return the number of instructions in the alternative.
*/
static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
{
+ struct instruction *orig_insn;
struct objtool_file *file;
struct instruction *insn;
+ const char *name;
int offset;
char *str;
int count;
int err;
file = dctx->file;
+ orig_insn = dalt->orig_insn;
count = 0;
offset = 0;
alt_for_each_insn(file, DALT_GROUP(dalt), insn) {
-
- disas_insn_alt(dctx, insn);
- str = strdup(disas_result(dctx));
+ /*
+ * An alternative direct call initially has the
+ * "call BUG_func" instruction but it will be
+ * replaced with a direct call to the target of
+ * the pv_ops call in the original instruction.
+ */
+ if (disas_alt_is_direct_call(insn)) {
+ name = pv_call_dest_name(file, orig_insn,
+ dalt->pv_mode);
+ if (name)
+ str = strfmt("callq %s", name);
+ else
+ str = strdup("NOP");
+ } else {
+ disas_insn_alt(dctx, insn);
+ str = strdup(disas_result(dctx));
+ }
if (!str)
return -1;
@@ -876,6 +953,7 @@ static void *disas_alt(struct disas_context *dctx,
struct instruction *orig_insn)
{
struct disas_alt alts[DISAS_ALT_MAX] = { 0 };
+ enum pv_mode pv_mode = PV_MODE_UNKNOWN;
struct alternative *alt;
struct disas_alt *dalt;
int offset_next;
@@ -884,7 +962,6 @@ static void *disas_alt(struct disas_context *dctx,
int alt_id;
int offset;
int count;
- int err;
int i;
alt_id = orig_insn->offset;
@@ -892,8 +969,8 @@ static void *disas_alt(struct disas_context *dctx,
/*
* Initialize and disassemble the default alternative.
*/
- err = disas_alt_init(&alts[0], orig_insn, NULL);
- if (err)
+ pv_mode = disas_alt_init(&alts[0], orig_insn, NULL, pv_mode);
+ if (pv_mode < 0)
goto error;
insn_count = disas_alt_default(dctx, &alts[0]);
@@ -911,8 +988,8 @@ static void *disas_alt(struct disas_context *dctx,
break;
}
dalt = &alts[i];
- err = disas_alt_init(dalt, orig_insn, alt);
- if (err)
+ pv_mode = disas_alt_init(dalt, orig_insn, alt, pv_mode);
+ if (pv_mode < 0)
goto error;
count = -1;
--
2.43.5
next prev parent reply other threads:[~2025-11-12 16:04 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-12 16:02 [PATCH v3 00/28] objtool: Function validation tracing Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 01/28] objtool: Move disassembly functions to a separated file Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 02/28] objtool: Create disassembly context Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 03/28] objtool: Disassemble code with libopcodes instead of running objdump Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 04/28] tool build: Remove annoying newline in build output Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 05/28] objtool: Print symbol during disassembly Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 06/28] objtool: Store instruction disassembly result Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 07/28] objtool: Disassemble instruction on warning or backtrace Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 08/28] objtool: Extract code to validate instruction from the validate branch loop Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 09/28] objtool: Record symbol name max length Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 10/28] objtool: Add option to trace function validation Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 11/28] objtool: Trace instruction state changes during " Alexandre Chartre
2025-11-12 16:02 ` [PATCH v3 12/28] objtool: Improve register reporting " Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 13/28] objtool: Identify the different types of alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 14/28] objtool: Improve tracing of alternative instructions Alexandre Chartre
2025-11-13 5:14 ` kernel test robot
2025-11-12 16:03 ` [PATCH v3 15/28] objtool: Do not validate IBT for .return_sites and .call_sites Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 16/28] objtool: Add the --disas=<function-pattern> action Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 17/28] objtool: Print headers for alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 18/28] objtool: Disassemble group alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 19/28] objtool: Print addresses with alternative instructions Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 20/28] objtool: Disassemble exception table alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 21/28] objtool: Disassemble jump " Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 22/28] objtool: Fix address references in alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 23/28] objtool: Provide access to feature and flags of group alternatives Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 24/28] objtool: Function to get the name of a CPU feature Alexandre Chartre
2025-11-12 16:03 ` [PATCH v3 25/28] objtool: Improve naming of group alternatives Alexandre Chartre
2025-11-13 5:15 ` kernel test robot
2025-11-12 16:03 ` [PATCH v3 26/28] objtool: Get the destination name of a PV call Alexandre Chartre
2025-11-12 16:03 ` Alexandre Chartre [this message]
2025-11-12 16:03 ` [PATCH v3 28/28] objtool: Print single line for alternatives with one instruction Alexandre Chartre
2025-11-13 9:21 ` [PATCH v3 00/28] objtool: Function validation tracing Alexandre Chartre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251112160315.2207947-28-alexandre.chartre@oracle.com \
--to=alexandre.chartre@oracle.com \
--cc=jpoimboe@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®