@@ -3505,6 +3505,34 @@ static struct instruction *next_insn_to_validate(struct objtool_file *file,
35053505 return next_insn_same_sec (file , alt_group -> orig_group -> last_insn );
35063506}
35073507
3508+ static bool skip_alt_group (struct instruction * insn )
3509+ {
3510+ struct instruction * alt_insn = insn -> alts ? insn -> alts -> insn : NULL ;
3511+
3512+ /* ANNOTATE_IGNORE_ALTERNATIVE */
3513+ if (insn -> alt_group && insn -> alt_group -> ignore )
3514+ return true;
3515+
3516+ /*
3517+ * For NOP patched with CLAC/STAC, only follow the latter to avoid
3518+ * impossible code paths combining patched CLAC with unpatched STAC
3519+ * or vice versa.
3520+ *
3521+ * ANNOTATE_IGNORE_ALTERNATIVE could have been used here, but Linus
3522+ * requested not to do that to avoid hurting .s file readability
3523+ * around CLAC/STAC alternative sites.
3524+ */
3525+
3526+ if (!alt_insn )
3527+ return false;
3528+
3529+ /* Don't override ASM_{CLAC,STAC}_UNSAFE */
3530+ if (alt_insn -> alt_group && alt_insn -> alt_group -> ignore )
3531+ return false;
3532+
3533+ return alt_insn -> type == INSN_CLAC || alt_insn -> type == INSN_STAC ;
3534+ }
3535+
35083536/*
35093537 * Follow the branch starting at the given instruction, and recursively follow
35103538 * any other branches (jumps). Meanwhile, track the frame pointer state at
@@ -3625,7 +3653,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
36253653 }
36263654 }
36273655
3628- if (insn -> alt_group && insn -> alt_group -> ignore )
3656+ if (skip_alt_group ( insn ) )
36293657 return 0 ;
36303658
36313659 if (handle_insn_ops (insn , next_insn , & state ))
@@ -3684,14 +3712,20 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
36843712
36853713 break ;
36863714
3687- case INSN_CONTEXT_SWITCH :
3688- if (func ) {
3689- if (!next_insn || !next_insn -> hint ) {
3690- WARN_INSN (insn , "unsupported instruction in callable function" );
3691- return 1 ;
3692- }
3693- break ;
3715+ case INSN_SYSCALL :
3716+ if (func && (!next_insn || !next_insn -> hint )) {
3717+ WARN_INSN (insn , "unsupported instruction in callable function" );
3718+ return 1 ;
3719+ }
3720+
3721+ break ;
3722+
3723+ case INSN_SYSRET :
3724+ if (func && (!next_insn || !next_insn -> hint )) {
3725+ WARN_INSN (insn , "unsupported instruction in callable function" );
3726+ return 1 ;
36943727 }
3728+
36953729 return 0 ;
36963730
36973731 case INSN_STAC :
@@ -3886,6 +3920,12 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
38863920 WARN_INSN (insn , "RET before UNTRAIN" );
38873921 return 1 ;
38883922
3923+ case INSN_SYSCALL :
3924+ break ;
3925+
3926+ case INSN_SYSRET :
3927+ return 0 ;
3928+
38893929 case INSN_NOP :
38903930 if (insn -> retpoline_safe )
38913931 return 0 ;
@@ -3895,6 +3935,9 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn)
38953935 break ;
38963936 }
38973937
3938+ if (insn -> dead_end )
3939+ return 0 ;
3940+
38983941 if (!next ) {
38993942 WARN_INSN (insn , "teh end!" );
39003943 return 1 ;
0 commit comments