From f1dee044ae2c5627ab918d5b947ec6785d2d74c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <royger@FreeBSD.org>
Date: Tue, 5 Mar 2024 14:15:03 +0100
Subject: [PATCH] x86/xen: fix accounted interrupt time

The current addition to the interrupt nesting level in
xen_arch_intr_handle_upcall() is wrong, as intr_execute_handlers() as called by
xen_arch_intr_execute_handlers() will already add one nesting level and save
the previous frame.

Such extra interrupt nesting count lead to statclock() reporting idle time as
interrupt, as the call from interrupt context will always be seen as a nested
one (td->td_intr_nesting_level >= 2) due to the nesting count increase done by
both xen_arch_intr_handle_upcall() and intr_execute_handlers().

Fix this by removing the extra nesting increase done in
xen_arch_intr_handle_upcall().

PR: 277231
Reported by: Matthew Grooms <mgrooms@shrew.net>
Fixes: af610cabf1f4 ('xen/intr: adjust xen_intr_handle_upcall() to match driver filter')
Sponsored by: Cloud Software Group
---
 sys/dev/xen/bus/xen_intr.c  |  4 ++--
 sys/x86/xen/xen_arch_intr.c | 10 +---------
 2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/sys/dev/xen/bus/xen_intr.c b/sys/dev/xen/bus/xen_intr.c
index 609f31b5418a..30a755de81fa 100644
--- a/sys/dev/xen/bus/xen_intr.c
+++ b/sys/dev/xen/bus/xen_intr.c
@@ -344,9 +344,9 @@ xen_intr_active_ports(const struct xen_intr_pcpu_data *const pcpu,
  * \param trap_frame  The trap frame context for the current interrupt.
  */
 int
-xen_intr_handle_upcall(void *unused __unused)
+xen_intr_handle_upcall(void *data)
 {
-	struct trapframe *trap_frame = curthread->td_intr_frame;
+	struct trapframe *trap_frame = data;
 	u_int l1i, l2i, port, cpu __diagused;
 	u_long masked_l1, masked_l2;
 	struct xenisrc *isrc;
diff --git a/sys/x86/xen/xen_arch_intr.c b/sys/x86/xen/xen_arch_intr.c
index dcf8b4aa35f1..4136f9bfc7f8 100644
--- a/sys/x86/xen/xen_arch_intr.c
+++ b/sys/x86/xen/xen_arch_intr.c
@@ -81,7 +81,6 @@ extern void xen_arch_intr_handle_upcall(struct trapframe *);
 void
 xen_arch_intr_handle_upcall(struct trapframe *trap_frame)
 {
-	struct trapframe *old;
 
 	/*
 	 * Disable preemption in order to always check and fire events
@@ -91,14 +90,7 @@ xen_arch_intr_handle_upcall(struct trapframe *trap_frame)
 
 	++*DPCPU_GET(pintrcnt);
 
-	++curthread->td_intr_nesting_level;
-	old = curthread->td_intr_frame;
-	curthread->td_intr_frame = trap_frame;
-
-	xen_intr_handle_upcall(NULL);
-
-	curthread->td_intr_frame = old;
-	--curthread->td_intr_nesting_level;
+	xen_intr_handle_upcall(trap_frame);
 
 	if (xen_evtchn_needs_ack)
 		lapic_eoi();
-- 
2.44.0