From 44e23c46636b507217443fd7e53e641df6e0f445 Mon Sep 17 00:00:00 2001 From: Roy Hopkins Date: Tue, 16 Jan 2024 09:46:14 +0000 Subject: [PATCH] gdbstub: Fix order of task list when first BP occurs after tasks created A remote GDB connects to the SVSM GDB stub after SVSM hits the first breakpoint. At this point the remote GDB does not know which task is halted or anything about the current list of tasks in SVSM. Therefore after requesting the tasklist it assumes the first task (thread) in the list is the one that is halted. See 'qfThreadInfo' documentation at https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html for details. The order of the list of tasks provided by the GDB stub is based on iterating the task list. Therefore the first task reported by SVSM may not be the task that is currently halted. This patch queries the current task and makes sure it is reported first every time the task list is requested. Signed-off-by: Roy Hopkins --- src/debug/gdbstub.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/debug/gdbstub.rs b/src/debug/gdbstub.rs index b8edc0d5e..8997b9897 100644 --- a/src/debug/gdbstub.rs +++ b/src/debug/gdbstub.rs @@ -539,32 +539,23 @@ pub mod svsm_gdbstub { ) -> Result<(), Self::Error> { let mut tl = TASKLIST.lock(); - let mut any_scheduled = false; - - if tl.list().is_empty() { - // Task list has not been initialised yet. Report a single thread - // for the current CPU + // Get the current task. If this is the first request after the remote + // GDB has connected then we need to report the current task first. + // There is no harm in doing this every time the thread list is requested. + let current_task = this_cpu().runqueue().lock_read().current_task_id(); + if current_task == INITIAL_TASK_ID { thread_is_active(Tid::new(INITIAL_TASK_ID as usize).unwrap()); } else { + thread_is_active(Tid::new(current_task as usize).unwrap()); + let mut cursor = tl.list().front_mut(); while cursor.get().is_some() { - if cursor.get().unwrap().task.lock_read().allocation.is_some() { - any_scheduled = true; - break; + let this_task = cursor.get().unwrap().task.lock_read().id; + if this_task != current_task { + thread_is_active(Tid::new(this_task as usize).unwrap()); } cursor.move_next(); } - if any_scheduled { - let mut cursor = tl.list().front_mut(); - while cursor.get().is_some() { - thread_is_active( - Tid::new(cursor.get().unwrap().task.lock_read().id as usize).unwrap(), - ); - cursor.move_next(); - } - } else { - thread_is_active(Tid::new(INITIAL_TASK_ID as usize).unwrap()); - } } Ok(()) }