Re: [PATCH v7 4/4] nmi_backtrace: generate one-line reports for idle cpus

Petr Mladek
2016-08-09T12:43:35Z

On Mon 2016-08-08 12:03:38, Chris Metcalf wrote:
> When doing an nmi backtrace of many cores, most of which are idle,
> the output is a little overwhelming and very uninformative. Suppress
> messages for cpus that are idling when they are interrupted and just
> emit one line, "NMI backtrace for N skipped: idling at pc 0xNNN".
>
> We do this by grouping all the cpuidle code together into a new
> .cpuidle.text section, and then checking the address of the
> interrupted PC to see if it lies within that section.
>
> This commit suitably tags x86, arm64, and tile idle routines,
> and only adds in the minimal framework for other architectures.
>
> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Tested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Chris Metcalf <cmetcalf@mellanox.com>
> ---
> arch/alpha/kernel/vmlinux.lds.S | 1 +
> arch/arc/kernel/vmlinux.lds.S | 1 +
> arch/arm/kernel/vmlinux-xip.lds.S | 1 +
> arch/arm/kernel/vmlinux.lds.S | 1 +
> arch/arm64/kernel/vmlinux.lds.S | 1 +
> arch/arm64/mm/proc.S | 2 ++
> arch/avr32/kernel/vmlinux.lds.S | 1 +
> arch/blackfin/kernel/vmlinux.lds.S | 1 +
> arch/c6x/kernel/vmlinux.lds.S | 1 +
> arch/cris/kernel/vmlinux.lds.S | 1 +
> arch/frv/kernel/vmlinux.lds.S | 1 +
> arch/h8300/kernel/vmlinux.lds.S | 1 +
> arch/hexagon/kernel/vmlinux.lds.S | 1 +
> arch/ia64/kernel/vmlinux.lds.S | 1 +
> arch/m32r/kernel/vmlinux.lds.S | 1 +
> arch/m68k/kernel/vmlinux-nommu.lds | 1 +
> arch/m68k/kernel/vmlinux-std.lds | 1 +
> arch/m68k/kernel/vmlinux-sun3.lds | 1 +
> arch/metag/kernel/vmlinux.lds.S | 1 +
> arch/microblaze/kernel/vmlinux.lds.S | 1 +
> arch/mips/kernel/vmlinux.lds.S | 1 +
> arch/mn10300/kernel/vmlinux.lds.S | 1 +
> arch/nios2/kernel/vmlinux.lds.S | 1 +
> arch/openrisc/kernel/vmlinux.lds.S | 1 +
> arch/parisc/kernel/vmlinux.lds.S | 1 +
> arch/powerpc/kernel/vmlinux.lds.S | 1 +
> arch/s390/kernel/vmlinux.lds.S | 1 +
> arch/score/kernel/vmlinux.lds.S | 1 +
> arch/sh/kernel/vmlinux.lds.S | 1 +
> arch/sparc/kernel/vmlinux.lds.S | 1 +
> arch/tile/kernel/entry.S | 2 +-
> arch/tile/kernel/vmlinux.lds.S | 1 +
> arch/um/kernel/dyn.lds.S | 1 +
> arch/um/kernel/uml.lds.S | 1 +
> arch/unicore32/kernel/vmlinux.lds.S | 1 +
> arch/x86/kernel/acpi/cstate.c | 2 +-
> arch/x86/kernel/process.c | 4 ++--
> arch/x86/kernel/vmlinux.lds.S | 1 +
> arch/xtensa/kernel/vmlinux.lds.S | 3 +++
> drivers/acpi/processor_idle.c | 5 +++--
> drivers/cpuidle/driver.c | 5 +++--
> drivers/idle/intel_idle.c | 4 ++--
> include/asm-generic/vmlinux.lds.h | 6 ++++++
> include/linux/cpu.h | 5 +++++
> kernel/sched/idle.c | 13 +++++++++++--
> lib/nmi_backtrace.c | 16 +++++++++++-----
> scripts/mod/modpost.c | 2 +-
> scripts/recordmcount.c | 1 +
> scripts/recordmcount.pl | 1 +
> 49 files changed, 87 insertions(+), 18 deletions(-)
>
> diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
> index 647b84c15382..cebecfb76fbf 100644
> --- a/arch/alpha/kernel/vmlinux.lds.S
> +++ b/arch/alpha/kernel/vmlinux.lds.S
> @@ -22,6 +22,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.gnu.warning)
> diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
> index 894e696bddaa..65652160cfda 100644
> --- a/arch/arc/kernel/vmlinux.lds.S
> +++ b/arch/arc/kernel/vmlinux.lds.S
> @@ -97,6 +97,7 @@ SECTIONS
> _text = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.fixup)
> diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
> index cba1ec899a69..7fa487ef7e2f 100644
> --- a/arch/arm/kernel/vmlinux-xip.lds.S
> +++ b/arch/arm/kernel/vmlinux-xip.lds.S
> @@ -98,6 +98,7 @@ SECTIONS
> IRQENTRY_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.gnu.warning)
> diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
> index d24e5dd2aa7a..f7f55df0bf7b 100644
> --- a/arch/arm/kernel/vmlinux.lds.S
> +++ b/arch/arm/kernel/vmlinux.lds.S
> @@ -111,6 +111,7 @@ SECTIONS
> SOFTIRQENTRY_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> HYPERVISOR_TEXT
> KPROBES_TEXT
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 659963d40bb4..fe7f93b7b11b 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -122,6 +122,7 @@ SECTIONS
> ENTRY_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> HYPERVISOR_TEXT
> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
> index 5bb61de23201..64f088ca3192 100644
> --- a/arch/arm64/mm/proc.S
> +++ b/arch/arm64/mm/proc.S
> @@ -48,11 +48,13 @@
> *
> * Idle the processor (wait for interrupt).
> */
> + .pushsection ".cpuidle.text","ax"
> ENTRY(cpu_do_idle)
> dsb sy // WFI may enter a low-power mode
> wfi
> ret
> ENDPROC(cpu_do_idle)
> + .popsection
>
> #ifdef CONFIG_CPU_PM
> /**
> diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
> index a4589176bed5..17f2730eb497 100644
> --- a/arch/avr32/kernel/vmlinux.lds.S
> +++ b/arch/avr32/kernel/vmlinux.lds.S
> @@ -52,6 +52,7 @@ SECTIONS
> KPROBES_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.gnu.warning)
> diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
> index d920b959ff3a..68069a120055 100644
> --- a/arch/blackfin/kernel/vmlinux.lds.S
> +++ b/arch/blackfin/kernel/vmlinux.lds.S
> @@ -33,6 +33,7 @@ SECTIONS
> #ifndef CONFIG_SCHEDULE_L1
> SCHED_TEXT
> #endif
> + CPUIDLE_TEXT
> LOCK_TEXT
> IRQENTRY_TEXT
> SOFTIRQENTRY_TEXT
> diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
> index 50bc10f97bcb..a1a5c166bc9b 100644
> --- a/arch/c6x/kernel/vmlinux.lds.S
> +++ b/arch/c6x/kernel/vmlinux.lds.S
> @@ -70,6 +70,7 @@ SECTIONS
> _stext = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> IRQENTRY_TEXT
> SOFTIRQENTRY_TEXT
> diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S
> index 7552c2557506..979586261520 100644
> --- a/arch/cris/kernel/vmlinux.lds.S
> +++ b/arch/cris/kernel/vmlinux.lds.S
> @@ -43,6 +43,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.text.__*)
> diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
> index 7e958d829ec9..aa6e573d57da 100644
> --- a/arch/frv/kernel/vmlinux.lds.S
> +++ b/arch/frv/kernel/vmlinux.lds.S
> @@ -63,6 +63,7 @@ SECTIONS
> *(.text..tlbmiss)
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> #ifdef CONFIG_DEBUG_INFO
> INIT_TEXT
> diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
> index cb5dfb02c88d..7f11da1b895e 100644
> --- a/arch/h8300/kernel/vmlinux.lds.S
> +++ b/arch/h8300/kernel/vmlinux.lds.S
> @@ -29,6 +29,7 @@ SECTIONS
> _stext = . ;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> #if defined(CONFIG_ROMKERNEL)
> *(.int_redirect)
> diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
> index 5f268c1071b3..ec87e67feb19 100644
> --- a/arch/hexagon/kernel/vmlinux.lds.S
> +++ b/arch/hexagon/kernel/vmlinux.lds.S
> @@ -50,6 +50,7 @@ SECTIONS
> _text = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.fixup)
> diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
> index dc506b05ffbd..f89d20c97412 100644
> --- a/arch/ia64/kernel/vmlinux.lds.S
> +++ b/arch/ia64/kernel/vmlinux.lds.S
> @@ -46,6 +46,7 @@ SECTIONS {
> __end_ivt_text = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.gnu.linkonce.t*)
> diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
> index 018e4a711d79..ad1fe56455aa 100644
> --- a/arch/m32r/kernel/vmlinux.lds.S
> +++ b/arch/m32r/kernel/vmlinux.lds.S
> @@ -31,6 +31,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.gnu.warning)
> diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds
> index 06a763f49fd3..d2c8abf1c8c4 100644
> --- a/arch/m68k/kernel/vmlinux-nommu.lds
> +++ b/arch/m68k/kernel/vmlinux-nommu.lds
> @@ -45,6 +45,7 @@ SECTIONS {
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> . = ALIGN(16);
> diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
> index d0993594f558..5b5ce1e4d1ed 100644
> --- a/arch/m68k/kernel/vmlinux-std.lds
> +++ b/arch/m68k/kernel/vmlinux-std.lds
> @@ -16,6 +16,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.gnu.warning)
> diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
> index 8080469ee6c1..fe5ea1974b16 100644
> --- a/arch/m68k/kernel/vmlinux-sun3.lds
> +++ b/arch/m68k/kernel/vmlinux-sun3.lds
> @@ -16,6 +16,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.gnu.warning)
> diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
> index 150ace92c7ad..e6c700eaf207 100644
> --- a/arch/metag/kernel/vmlinux.lds.S
> +++ b/arch/metag/kernel/vmlinux.lds.S
> @@ -21,6 +21,7 @@ SECTIONS
> .text : {
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
> index 0a47f0410554..289d0e7f3e3a 100644
> --- a/arch/microblaze/kernel/vmlinux.lds.S
> +++ b/arch/microblaze/kernel/vmlinux.lds.S
> @@ -33,6 +33,7 @@ SECTIONS {
> EXIT_TEXT
> EXIT_CALL
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
> index a82c178d0bb9..d5de67591735 100644
> --- a/arch/mips/kernel/vmlinux.lds.S
> +++ b/arch/mips/kernel/vmlinux.lds.S
> @@ -55,6 +55,7 @@ SECTIONS
> .text : {
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
> index 13c4814c29f8..2d5f1c3f1afb 100644
> --- a/arch/mn10300/kernel/vmlinux.lds.S
> +++ b/arch/mn10300/kernel/vmlinux.lds.S
> @@ -30,6 +30,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.fixup)
> diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
> index e23e89539967..6a8045bb1a77 100644
> --- a/arch/nios2/kernel/vmlinux.lds.S
> +++ b/arch/nios2/kernel/vmlinux.lds.S
> @@ -37,6 +37,7 @@ SECTIONS
> .text : {
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> IRQENTRY_TEXT
> SOFTIRQENTRY_TEXT
> diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
> index d936de4c07ca..d68b9ede8423 100644
> --- a/arch/openrisc/kernel/vmlinux.lds.S
> +++ b/arch/openrisc/kernel/vmlinux.lds.S
> @@ -47,6 +47,7 @@ SECTIONS
> _stext = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
> index f3ead0b6ce46..9ec8ec075dae 100644
> --- a/arch/parisc/kernel/vmlinux.lds.S
> +++ b/arch/parisc/kernel/vmlinux.lds.S
> @@ -69,6 +69,7 @@ SECTIONS
> .text ALIGN(PAGE_SIZE) : {
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
> index b5fba689fca6..7ed59f0d947f 100644
> --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -52,6 +52,7 @@ SECTIONS
> /* careful! __ftr_alt_* sections need to be close to .text */
> *(.text .fixup __ftr_alt_* .ref.text)
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
> index 429bfd111961..000e6e91f6a0 100644
> --- a/arch/s390/kernel/vmlinux.lds.S
> +++ b/arch/s390/kernel/vmlinux.lds.S
> @@ -35,6 +35,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
> index 7274b5c4287e..4117890b1db1 100644
> --- a/arch/score/kernel/vmlinux.lds.S
> +++ b/arch/score/kernel/vmlinux.lds.S
> @@ -40,6 +40,7 @@ SECTIONS
> _text = .; /* Text and read-only data */
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> *(.text.*)
> diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
> index 235a4101999f..5b9a3cc90c58 100644
> --- a/arch/sh/kernel/vmlinux.lds.S
> +++ b/arch/sh/kernel/vmlinux.lds.S
> @@ -36,6 +36,7 @@ SECTIONS
> TEXT_TEXT
> EXTRA_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
> index d79b3b734245..572db686f845 100644
> --- a/arch/sparc/kernel/vmlinux.lds.S
> +++ b/arch/sparc/kernel/vmlinux.lds.S
> @@ -49,6 +49,7 @@ SECTIONS
> HEAD_TEXT
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
> index 670a3569450f..101de132e363 100644
> --- a/arch/tile/kernel/entry.S
> +++ b/arch/tile/kernel/entry.S
> @@ -50,7 +50,7 @@ STD_ENTRY(smp_nap)
> * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and
> * as a result return to the function that called _cpu_idle().
> */
> -STD_ENTRY(_cpu_idle)
> +STD_ENTRY_SECTION(_cpu_idle, .cpuidle.text)
> movei r1, 1
> IRQ_ENABLE_LOAD(r2, r3)
> mtspr INTERRUPT_CRITICAL_SECTION, r1
> diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
> index 9d449caf8910..e1baf094fba4 100644
> --- a/arch/tile/kernel/vmlinux.lds.S
> +++ b/arch/tile/kernel/vmlinux.lds.S
> @@ -42,6 +42,7 @@ SECTIONS
> .text : AT (ADDR(.text) - LOAD_OFFSET) {
> HEAD_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> IRQENTRY_TEXT
> diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
> index adde088aeeff..4fdbcf958cd5 100644
> --- a/arch/um/kernel/dyn.lds.S
> +++ b/arch/um/kernel/dyn.lds.S
> @@ -68,6 +68,7 @@ SECTIONS
> _stext = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> *(.stub .text.* .gnu.linkonce.t.*)
> diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
> index 6899195602b7..1840f55ed042 100644
> --- a/arch/um/kernel/uml.lds.S
> +++ b/arch/um/kernel/uml.lds.S
> @@ -28,6 +28,7 @@ SECTIONS
> _stext = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> *(.fixup)
> /* .gnu.warning sections are handled specially by elf32.em. */
> diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
> index 77e407e49a63..56e788e8ee83 100644
> --- a/arch/unicore32/kernel/vmlinux.lds.S
> +++ b/arch/unicore32/kernel/vmlinux.lds.S
> @@ -37,6 +37,7 @@ SECTIONS
> .text : { /* Real text segment */
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
>
> *(.fixup)
> diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
> index bdfad642123f..af15f4444330 100644
> --- a/arch/x86/kernel/acpi/cstate.c
> +++ b/arch/x86/kernel/acpi/cstate.c
> @@ -152,7 +152,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
> }
> EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
>
> -void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
> +void __cpuidle acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
> {
> unsigned int cpu = smp_processor_id();
> struct cstate_entry *percpu_entry;
> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
> index 62c0b0ea2ce4..c400e30831dc 100644
> --- a/arch/x86/kernel/process.c
> +++ b/arch/x86/kernel/process.c
> @@ -301,7 +301,7 @@ void arch_cpu_idle(void)
> /*
> * We use this if we don't have any better idle routine..
> */
> -void default_idle(void)
> +void __cpuidle default_idle(void)
> {
> trace_cpu_idle_rcuidle(1, smp_processor_id());
> safe_halt();
> @@ -416,7 +416,7 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
> * with interrupts enabled and no flags, which is backwards compatible with the
> * original MWAIT implementation.
> */
> -static void mwait_idle(void)
> +static __cpuidle void mwait_idle(void)
> {
> if (!current_set_polling_and_test()) {
> trace_cpu_idle_rcuidle(1, smp_processor_id());
> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> index 9297a002d8e5..dbf67f64d5ec 100644
> --- a/arch/x86/kernel/vmlinux.lds.S
> +++ b/arch/x86/kernel/vmlinux.lds.S
> @@ -97,6 +97,7 @@ SECTIONS
> _stext = .;
> TEXT_TEXT
> SCHED_TEXT
> + CPUIDLE_TEXT
> LOCK_TEXT
> KPROBES_TEXT
> ENTRY_TEXT
> diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
> index c417cbe4ec87..18a174c7fb87 100644
> --- a/arch/xtensa/kernel/vmlinux.lds.S
> +++ b/arch/xtensa/kernel/vmlinux.lds.S
> @@ -93,6 +93,9 @@ SECTIONS
> VMLINUX_SYMBOL(__sched_text_start) = .;
> *(.sched.literal .sched.text)
> VMLINUX_SYMBOL(__sched_text_end) = .;
> + VMLINUX_SYMBOL(__cpuidle_text_start) = .;
> + *(.cpuidle.literal .cpuidle.text)
> + VMLINUX_SYMBOL(__cpuidle_text_end) = .;
> VMLINUX_SYMBOL(__lock_text_start) = .;
> *(.spinlock.literal .spinlock.text)
> VMLINUX_SYMBOL(__lock_text_end) = .;
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index cea52528aa18..2237d3f24f0e 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -31,6 +31,7 @@
> #include <linux/sched.h> /* need_resched() */
> #include <linux/tick.h>
> #include <linux/cpuidle.h>
> +#include <linux/cpu.h>
> #include <acpi/processor.h>
>
> /*
> @@ -115,7 +116,7 @@ static const struct dmi_system_id processor_power_dmi_table[] = {
> * Callers should disable interrupts before the call and enable
> * interrupts after return.
> */
> -static void acpi_safe_halt(void)
> +static void __cpuidle acpi_safe_halt(void)
> {
> if (!tif_need_resched()) {
> safe_halt();
> @@ -645,7 +646,7 @@ static int acpi_idle_bm_check(void)
> *
> * Caller disables interrupt before call and enables interrupt after return.
> */
> -static void acpi_idle_do_entry(struct acpi_processor_cx *cx)
> +static void __cpuidle acpi_idle_do_entry(struct acpi_processor_cx *cx)
> {
> if (cx->entry_method == ACPI_CSTATE_FFH) {
> /* Call into architectural FFH based C-state */
> diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
> index 389ade4572be..ab264d393233 100644
> --- a/drivers/cpuidle/driver.c
> +++ b/drivers/cpuidle/driver.c
> @@ -14,6 +14,7 @@
> #include <linux/cpuidle.h>
> #include <linux/cpumask.h>
> #include <linux/tick.h>
> +#include <linux/cpu.h>
>
> #include "cpuidle.h"
>
> @@ -178,8 +179,8 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
> }
>
> #ifdef CONFIG_ARCH_HAS_CPU_RELAX
> -static int poll_idle(struct cpuidle_device *dev,
> - struct cpuidle_driver *drv, int index)
> +static int __cpuidle poll_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> {
> local_irq_enable();
> if (!current_set_polling_and_test()) {
> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
> index 67ec58f9ef99..4466a2f969d7 100644
> --- a/drivers/idle/intel_idle.c
> +++ b/drivers/idle/intel_idle.c
> @@ -863,8 +863,8 @@ static struct cpuidle_state dnv_cstates[] = {
> *
> * Must be called under local_irq_disable().
> */
> -static int intel_idle(struct cpuidle_device *dev,
> - struct cpuidle_driver *drv, int index)
> +static __cpuidle int intel_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> {
> unsigned long ecx = 1; /* break on interrupt flag */
> struct cpuidle_state *state = &drv->states[index];
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 24563970ff7b..3e42bcdd014b 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -454,6 +454,12 @@
> *(.spinlock.text) \
> VMLINUX_SYMBOL(__lock_text_end) = .;
>
> +#define CPUIDLE_TEXT \
> + ALIGN_FUNCTION(); \
> + VMLINUX_SYMBOL(__cpuidle_text_start) = .; \
> + *(.cpuidle.text) \
> + VMLINUX_SYMBOL(__cpuidle_text_end) = .;
> +
> #define KPROBES_TEXT \
> ALIGN_FUNCTION(); \
> VMLINUX_SYMBOL(__kprobes_text_start) = .; \
> diff --git a/include/linux/cpu.h b/include/linux/cpu.h
> index 797d9c8e9a1b..6babfa6db9d9 100644
> --- a/include/linux/cpu.h
> +++ b/include/linux/cpu.h
> @@ -239,6 +239,11 @@ void cpu_startup_entry(enum cpuhp_state state);
>
> void cpu_idle_poll_ctrl(bool enable);
>
> +/* Attach to any functions which should be considered cpuidle. */
> +#define __cpuidle __attribute__((__section__(".cpuidle.text")))
> +
> +bool cpu_in_idle(unsigned long pc);
> +
> void arch_cpu_idle(void);
> void arch_cpu_idle_prepare(void);
> void arch_cpu_idle_enter(void);
> diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
> index 9fb873cfc75c..1d8718d5300d 100644
> --- a/kernel/sched/idle.c
> +++ b/kernel/sched/idle.c
> @@ -16,6 +16,9 @@
>
> #include "sched.h"
>
> +/* Linker adds these: start and end of __cpuidle functions */
> +extern char __cpuidle_text_start[], __cpuidle_text_end[];
> +
> /**
> * sched_idle_set_state - Record idle state for the current CPU.
> * @idle_state: State to record.
> @@ -53,7 +56,7 @@ static int __init cpu_idle_nopoll_setup(char *__unused)
> __setup("hlt", cpu_idle_nopoll_setup);
> #endif
>
> -static inline int cpu_idle_poll(void)
> +static noinline int __cpuidle cpu_idle_poll(void)
> {
> rcu_idle_enter();
> trace_cpu_idle_rcuidle(0, smp_processor_id());
> @@ -84,7 +87,7 @@ void __weak arch_cpu_idle(void)
> *
> * To use when the cpuidle framework cannot be used.
> */
> -void default_idle_call(void)
> +void __cpuidle default_idle_call(void)
> {
> if (current_clr_polling_and_test()) {
> local_irq_enable();
> @@ -271,6 +274,12 @@ static void cpu_idle_loop(void)
> }
> }
>
> +bool cpu_in_idle(unsigned long pc)
> +{
> + return pc >= (unsigned long)__cpuidle_text_start &&
> + pc < (unsigned long)__cpuidle_text_end;
> +}
> +
> void cpu_startup_entry(enum cpuhp_state state)
> {
> /*
> diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c
> index 2933f0680174..de0d406e95cc 100644
> --- a/lib/nmi_backtrace.c
> +++ b/lib/nmi_backtrace.c
> @@ -16,6 +16,7 @@
> #include <linux/delay.h>
> #include <linux/kprobes.h>
> #include <linux/nmi.h>
> +#include <linux/cpu.h>
>
> #ifdef arch_trigger_cpumask_backtrace
> /* For reliability, we're prepared to waste bits here. */
> @@ -87,11 +88,16 @@ bool nmi_cpu_backtrace(struct pt_regs *regs)
> int cpu = smp_processor_id();
>
> if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
> - pr_warn("NMI backtrace for cpu %d\n", cpu);
> - if (regs)
> - show_regs(regs);
> - else
> - dump_stack();
> + if (regs && cpu_in_idle(instruction_pointer(regs))) {
> + pr_warn("NMI backtrace for cpu %d skipped: idling at pc %#lx\n",
> + cpu, instruction_pointer(regs));

Hmm, I do not see this message even though the CPU is in the idle state:

[ 7918.884535] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.8.0-rc1-4-default+ #3088
[ 7918.884538] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[ 7918.884539] task: ffff88013a594380 task.stack: ffff88013a598000
[ 7918.884541] RIP: 0010:[<ffffffff81050bc6>] [<ffffffff81050bc6>] native_safe_halt+0x6/0x10
[ 7918.884543] RSP: 0018:ffff88013a59bea8 EFLAGS: 00000206
[ 7918.884544] RAX: ffff88013a594380 RBX: 0000000000000003 RCX: 0000000000000000
[ 7918.884546] RDX: ffff88013a594380 RSI: 0000000000000001 RDI: ffff88013a594380
[ 7918.884548] RBP: ffff88013a59bea8 R08: 0000000000000000 R09: 0000000000000000
[ 7918.884550] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000003
[ 7918.884551] R13: 0000000000000000 R14: ffff88013a598000 R15: ffff88013a598000
[ 7918.884553] FS: 0000000000000000(0000) GS:ffff88013fd80000(0000) knlGS:0000000000000000
[ 7918.884554] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7918.884556] CR2: 00007f8afc65e000 CR3: 00000001383b8000 CR4: 00000000000006e0
[ 7918.884557] Stack:
[ 7918.884559] ffff88013a59bec8 ffffffff819573d3 0000000000000003 0000000000000000
[ 7918.884561] ffff88013a59bed8 ffffffff8102628f ffff88013a59bee8 ffffffff819579ea
[ 7918.884562] ffff88013a59bf30 ffffffff810bfe1a ffff88013a598000 ffff88013a598000
[ 7918.884563] Call Trace:
[ 7918.884565] [<ffffffff819573d3>] default_idle+0x23/0x170
[ 7918.884566] [<ffffffff8102628f>] arch_cpu_idle+0xf/0x20
[ 7918.884568] [<ffffffff819579ea>] default_idle_call+0x2a/0x50
[ 7918.884570] [<ffffffff810bfe1a>] cpu_startup_entry+0x16a/0x260
[ 7918.884571] [<ffffffff8103faf6>] start_secondary+0xf6/0x100
[ 7918.884573] Code: 00 00 00 00 00 55 48 89 e5 fa 5d c3 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 fb 5d c3 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 fb f4 <5d> c3 0f 1f 84 00 00 00 00 00 55
48 89 e5 f4 5d c3 66 0f 1f 84

Note that I test it in a virtual machine using qemu.

The strange thing is that I do not see .cpuidle.text section in
the vmlinux binary. But it is possible that I have misunderstood
the concept.

Best Regards,
Petr