Re: [PATCH 04/12] x86: add noreturn in a few more places

Nicola Vetrini <[email protected]>
Newsgroups gmane.comp.emulators.xen.devel
Organization BUGSENG s.r.l.
Message-ID <[email protected]>
On 2026-08-28 09:01, Jan Beulich wrote:
> start_secondary(), do_double_fault(), play_dead(), and tboot_s3_error()
> never return, so would better be annotated anyway. The 
> do_double_fault()
> change needs accompanying by adjustments to entry_from_{pv,xen}(), as
> Eclair then deems the "return" there as unreachable.
> 
> context_switch() and continue_running() are odd: We can't
> (unconditionally) add noreturn to their declarations, as Arm's variants 
> do
> return. Put the attribute on x86'es definitions instead (the use of
> unreachable() in reset_stack_and_call_ind() allows the compiler to 
> figure
> that out itself, but Eclair wants the annotation in addition).
> 
> Signed-off-by: Jan Beulich <[email protected]>

Reviewed-by: Nicola Vetrini <[email protected]>

> ---
> entry_from_pv() wants the annotation only when PV=n, yet once added gcc
> then warns about "return" being used in a "noreturn" function. Is there
> any other approach to address this besides adding #ifdef inside the
> function (i.e. replacing the !IS_ENABLED(CONFIG_PV) check that's 
> there)?
> 

Besides GCC's warning, this would violate MISRA C's Rule 17.9 ("A 
function declared with a _Noreturn function specifier shall not return 
to its caller")
which is not (yet) adopted by Xen, as it comes with MISRA C:2012 
Amendment 3, whereas as you know Xen is based on MISRA C:2012 Amendment 
2 rules.
Besides this, perhaps an alternative could be something like this 
(untested):

#define __noreturn_0
#define __noreturn_1 __attribute__((noreturn))

#define __noreturn_select(x) __noreturn_select_(x)
#define __noreturn_select_(x) __noreturn_ ## x

#define noreturn(cond) __noreturn_select(cond)

assuming use sites such as noreturn(IS_ENABLED(CONFIG_FOO))

> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -2163,7 +2163,7 @@ static void __context_switch(void)
>      per_cpu(curr_vcpu, cpu) = n;
>  }
> 
> -void context_switch(struct vcpu *prev, struct vcpu *next)
> +void noreturn context_switch(struct vcpu *prev, struct vcpu *next)
>  {
>      unsigned int cpu = smp_processor_id();
>      struct cpu_info *info = get_cpu_info();
> @@ -2240,7 +2240,7 @@ void context_switch(struct vcpu *prev, s
>      reset_stack_and_call_ind(nextd->arch.ctxt_switch->tail);
>  }
> 
> -void continue_running(struct vcpu *same)
> +void noreturn continue_running(struct vcpu *same)
>  {
>      reset_stack_and_call_ind(same->domain->arch.ctxt_switch->tail);
>  }
> --- a/xen/arch/x86/include/asm/cpuidle.h
> +++ b/xen/arch/x86/include/asm/cpuidle.h
> @@ -26,7 +26,7 @@ static inline int mwait_idle_init(struct
>  int cpuidle_init_cpu(unsigned int cpu);
>  void cf_check default_dead_idle(void);
>  void cf_check acpi_dead_idle(void);
> -void play_dead(void);
> +void noreturn play_dead(void);
>  void trace_exit_reason(u32 *irq_traced);
>  void update_idle_stats(struct acpi_processor_power *power,
>                         struct acpi_processor_cx *cx,
> --- a/xen/arch/x86/include/asm/tboot.h
> +++ b/xen/arch/x86/include/asm/tboot.h
> @@ -126,7 +126,7 @@ int tboot_in_measured_env(void);
>  int tboot_protect_mem_regions(void);
>  int cf_check tboot_parse_dmar_table(acpi_table_handler dmar_handler);
>  int tboot_s3_resume(void);
> -void tboot_s3_error(int error);
> +void noreturn tboot_s3_error(int error);
>  int tboot_wake_ap(int apicid, unsigned long sipi_vec);
>  #else
>  static inline void tboot_probe(void) {}
> --- a/xen/arch/x86/smpboot.c
> +++ b/xen/arch/x86/smpboot.c
> @@ -326,7 +326,7 @@ static void set_cpu_sibling_map(unsigned
>      }
>  }
> 
> -void asmlinkage start_secondary(void)
> +void asmlinkage noreturn start_secondary(void)
>  {
>      struct cpu_info *info = get_cpu_info();
>      unsigned int cpu = smp_processor_id();
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -1080,7 +1080,7 @@ const char *vector_name(unsigned int vec
>      return (vec < ARRAY_SIZE(names) && names[vec][0]) ? names[vec] : 
> "???";
>  }
> 
> -void asmlinkage do_double_fault(struct cpu_user_regs *regs)
> +void asmlinkage noreturn do_double_fault(struct cpu_user_regs *regs)
>  {
>      unsigned int cpu;
>      struct extra_state state;
> @@ -2304,7 +2304,7 @@ void asmlinkage entry_from_pv(struct cpu
>      case X86_ET_HW_EXC:
>          switch ( vec )
>          {
> -        case X86_EXC_DF: return do_double_fault(regs);
> +        case X86_EXC_DF: do_double_fault(regs); /* noreturn */
>          case X86_EXC_MC: return do_machine_check(regs);
>          }
>          break;
> @@ -2615,7 +2615,7 @@ void asmlinkage entry_from_xen(struct cp
>      case X86_ET_HW_EXC:
>          switch ( regs->fred_ss.vector )
>          {
> -        case X86_EXC_DF: return do_double_fault(regs);
> +        case X86_EXC_DF: do_double_fault(regs); /* noreturn */
>          case X86_EXC_MC: return do_machine_check(regs);
>          }
>          break;

-- 
Nicola Vetrini, B.Sc.
Software Engineer
BUGSENG (https://bugseng.com)
LinkedIn: https://www.linkedin.com/in/nicola-vetrini-a42471253
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.