Commit da6b8559 authored by Yongliang Gao's avatar Yongliang Gao Committed by Joel Fernandes
Browse files

rcu/cpu_stall_cputime: fix the hardirq count for x86 architecture



When counting the number of hardirqs in the x86 architecture,
it is essential to add arch_irq_stat_cpu to ensure accuracy.

For example, a CPU loop within the rcu_read_lock function.

Before:
[   70.910184] rcu: INFO: rcu_preempt self-detected stall on CPU
[   70.910436] rcu:     3-....: (4999 ticks this GP) idle=***
[   70.910711] rcu:              hardirqs   softirqs   csw/system
[   70.910870] rcu:      number:        0        657            0
[   70.911024] rcu:     cputime:        0          0         2498   ==> 2498(ms)
[   70.911278] rcu:     (t=5001 jiffies g=3677 q=29 ncpus=8)

After:
[   68.046132] rcu: INFO: rcu_preempt self-detected stall on CPU
[   68.046354] rcu:     2-....: (4999 ticks this GP) idle=***
[   68.046628] rcu:              hardirqs   softirqs   csw/system
[   68.046793] rcu:      number:     2498        663            0
[   68.046951] rcu:     cputime:        0          0         2496   ==> 2496(ms)
[   68.047244] rcu:     (t=5000 jiffies g=3825 q=4 ncpus=8)

Fixes: be42f00b ("rcu: Add RCU stall diagnosis information")
Reported-by: default avatarkernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202501090842.SfI6QPGS-lkp@intel.com/


Signed-off-by: default avatarYongliang Gao <leonylgao@tencent.com>
Reviewed-by: default avatarNeeraj Upadhyay <Neeraj.Upadhyay@amd.com>
Link: https://lore.kernel.org/r/20250216084109.3109837-1-leonylgao@gmail.com


Signed-off-by: default avatarBoqun Feng <boqun.feng@gmail.com>
Signed-off-by: default avatarJoel Fernandes <joelagnelf@nvidia.com>
parent 0999f615
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -801,6 +801,10 @@ static int rcu_watching_snap_save(struct rcu_data *rdp)
	return 0;
}

#ifndef arch_irq_stat_cpu
#define arch_irq_stat_cpu(cpu) 0
#endif

/*
 * Returns positive if the specified CPU has passed through a quiescent state
 * by virtue of being in or having passed through an dynticks idle state since
@@ -936,9 +940,9 @@ static int rcu_watching_snap_recheck(struct rcu_data *rdp)
			rsrp->cputime_irq     = kcpustat_field(kcsp, CPUTIME_IRQ, cpu);
			rsrp->cputime_softirq = kcpustat_field(kcsp, CPUTIME_SOFTIRQ, cpu);
			rsrp->cputime_system  = kcpustat_field(kcsp, CPUTIME_SYSTEM, cpu);
			rsrp->nr_hardirqs = kstat_cpu_irqs_sum(rdp->cpu);
			rsrp->nr_softirqs = kstat_cpu_softirqs_sum(rdp->cpu);
			rsrp->nr_csw = nr_context_switches_cpu(rdp->cpu);
			rsrp->nr_hardirqs = kstat_cpu_irqs_sum(cpu) + arch_irq_stat_cpu(cpu);
			rsrp->nr_softirqs = kstat_cpu_softirqs_sum(cpu);
			rsrp->nr_csw = nr_context_switches_cpu(cpu);
			rsrp->jiffies = jiffies;
			rsrp->gp_seq = rdp->gp_seq;
		}
+1 −1
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ struct rcu_snap_record {
	u64		cputime_irq;	/* Accumulated cputime of hard irqs */
	u64		cputime_softirq;/* Accumulated cputime of soft irqs */
	u64		cputime_system; /* Accumulated cputime of kernel tasks */
	unsigned long	nr_hardirqs;	/* Accumulated number of hard irqs */
	u64		nr_hardirqs;	/* Accumulated number of hard irqs */
	unsigned int	nr_softirqs;	/* Accumulated number of soft irqs */
	unsigned long long nr_csw;	/* Accumulated number of task switches */
	unsigned long   jiffies;	/* Track jiffies value */
+2 −2
Original line number Diff line number Diff line
@@ -435,8 +435,8 @@ static void print_cpu_stat_info(int cpu)
	rsr.cputime_system  = kcpustat_field(kcsp, CPUTIME_SYSTEM, cpu);

	pr_err("\t         hardirqs   softirqs   csw/system\n");
	pr_err("\t number: %8ld %10d %12lld\n",
		kstat_cpu_irqs_sum(cpu) - rsrp->nr_hardirqs,
	pr_err("\t number: %8lld %10d %12lld\n",
		kstat_cpu_irqs_sum(cpu) + arch_irq_stat_cpu(cpu) - rsrp->nr_hardirqs,
		kstat_cpu_softirqs_sum(cpu) - rsrp->nr_softirqs,
		nr_context_switches_cpu(cpu) - rsrp->nr_csw);
	pr_err("\tcputime: %8lld %10lld %12lld   ==> %d(ms)\n",