From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983175171296.599647957176; Thu, 7 Dec 2023 13:06:15 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLXs-0002bd-TC; Thu, 07 Dec 2023 16:04:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXp-0002Zc-CR for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:29 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXm-0005mq-1B for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:29 -0500 Received: (qmail 10209 invoked by uid 484); 7 Dec 2023 21:04:01 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:03:59 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.198773 secs); 07 Dec 2023 21:04:01 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 01/17] gdbstub, mcdstub: file and build structure adapted to accomodate for the mcdstub Date: Thu, 7 Dec 2023 22:03:42 +0100 Message-Id: <20231207210358.7409-2-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983175427100001 mcdstub files created including the shared header between the mcd shared li= brary and the mcdstub. MAINTAINERS file updated --- MAINTAINERS | 11 +- debug/common/debug.c | 18 ++++ debug/common/meson.build | 0 {gdbstub =3D> debug/gdbstub}/gdbstub.c | 0 {gdbstub =3D> debug/gdbstub}/internals.h | 0 {gdbstub =3D> debug/gdbstub}/meson.build | 0 {gdbstub =3D> debug/gdbstub}/syscalls.c | 0 {gdbstub =3D> debug/gdbstub}/system.c | 0 {gdbstub =3D> debug/gdbstub}/trace-events | 0 debug/gdbstub/trace.h | 1 + {gdbstub =3D> debug/gdbstub}/user-target.c | 0 {gdbstub =3D> debug/gdbstub}/user.c | 0 debug/mcdstub/arm_mcdstub.c | 18 ++++ debug/mcdstub/mcdstub.c | 18 ++++ debug/mcdstub/meson.build | 0 debug/meson.build | 1 + gdbstub/trace.h | 1 - include/mcdstub/arm_mcdstub.h | 18 ++++ include/mcdstub/mcd_shared_defines.h | 132 +++++++++++++++++++++++ include/mcdstub/mcdstub.h | 18 ++++ include/mcdstub/mcdstub_common.h | 18 ++++ include/qemu/debug.h | 18 ++++ meson.build | 4 +- 23 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 debug/common/debug.c create mode 100644 debug/common/meson.build rename {gdbstub =3D> debug/gdbstub}/gdbstub.c (100%) rename {gdbstub =3D> debug/gdbstub}/internals.h (100%) rename {gdbstub =3D> debug/gdbstub}/meson.build (100%) rename {gdbstub =3D> debug/gdbstub}/syscalls.c (100%) rename {gdbstub =3D> debug/gdbstub}/system.c (100%) rename {gdbstub =3D> debug/gdbstub}/trace-events (100%) create mode 100644 debug/gdbstub/trace.h rename {gdbstub =3D> debug/gdbstub}/user-target.c (100%) rename {gdbstub =3D> debug/gdbstub}/user.c (100%) create mode 100644 debug/mcdstub/arm_mcdstub.c create mode 100644 debug/mcdstub/mcdstub.c create mode 100644 debug/mcdstub/meson.build create mode 100644 debug/meson.build delete mode 100644 gdbstub/trace.h create mode 100644 include/mcdstub/arm_mcdstub.h create mode 100644 include/mcdstub/mcd_shared_defines.h create mode 100644 include/mcdstub/mcdstub.h create mode 100644 include/mcdstub/mcdstub_common.h create mode 100644 include/qemu/debug.h diff --git a/MAINTAINERS b/MAINTAINERS index 695e0bd34f..467da56a38 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2955,7 +2955,7 @@ M: Alex Benn=C3=A9e R: Philippe Mathieu-Daud=C3=A9 S: Maintained F: docs/system/gdb.rst -F: gdbstub/* +F: debug/gdbstub/* F: include/exec/gdbstub.h F: include/gdbstub/* F: gdb-xml/ @@ -2963,6 +2963,15 @@ F: tests/tcg/multiarch/gdbstub/* F: scripts/feature_to_c.py F: scripts/probe-gdb-support.py =20 +MCD stub +M: Nicolas Eder +R: Alex Benn=C3=A9e +S: Maintained +F: debug/mcdstub/* +F: debug/common/* +F: include/mcdstub/* +F: include/qemu/debug.h + Memory API M: Paolo Bonzini M: Peter Xu diff --git a/debug/common/debug.c b/debug/common/debug.c new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/debug/common/debug.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/debug/common/meson.build b/debug/common/meson.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c similarity index 100% rename from gdbstub/gdbstub.c rename to debug/gdbstub/gdbstub.c diff --git a/gdbstub/internals.h b/debug/gdbstub/internals.h similarity index 100% rename from gdbstub/internals.h rename to debug/gdbstub/internals.h diff --git a/gdbstub/meson.build b/debug/gdbstub/meson.build similarity index 100% rename from gdbstub/meson.build rename to debug/gdbstub/meson.build diff --git a/gdbstub/syscalls.c b/debug/gdbstub/syscalls.c similarity index 100% rename from gdbstub/syscalls.c rename to debug/gdbstub/syscalls.c diff --git a/gdbstub/system.c b/debug/gdbstub/system.c similarity index 100% rename from gdbstub/system.c rename to debug/gdbstub/system.c diff --git a/gdbstub/trace-events b/debug/gdbstub/trace-events similarity index 100% rename from gdbstub/trace-events rename to debug/gdbstub/trace-events diff --git a/debug/gdbstub/trace.h b/debug/gdbstub/trace.h new file mode 100644 index 0000000000..ca6f0e8d29 --- /dev/null +++ b/debug/gdbstub/trace.h @@ -0,0 +1 @@ +#include "trace/trace-debug_gdbstub.h" diff --git a/gdbstub/user-target.c b/debug/gdbstub/user-target.c similarity index 100% rename from gdbstub/user-target.c rename to debug/gdbstub/user-target.c diff --git a/gdbstub/user.c b/debug/gdbstub/user.c similarity index 100% rename from gdbstub/user.c rename to debug/gdbstub/user.c diff --git a/debug/mcdstub/arm_mcdstub.c b/debug/mcdstub/arm_mcdstub.c new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/debug/mcdstub/arm_mcdstub.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/debug/mcdstub/mcdstub.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/debug/mcdstub/meson.build b/debug/mcdstub/meson.build new file mode 100644 index 0000000000..e69de29bb2 diff --git a/debug/meson.build b/debug/meson.build new file mode 100644 index 0000000000..a5b093f31e --- /dev/null +++ b/debug/meson.build @@ -0,0 +1 @@ +subdir('gdbstub') diff --git a/gdbstub/trace.h b/gdbstub/trace.h deleted file mode 100644 index dee87b1238..0000000000 --- a/gdbstub/trace.h +++ /dev/null @@ -1 +0,0 @@ -#include "trace/trace-gdbstub.h" diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/include/mcdstub/arm_mcdstub.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/include/mcdstub/mcd_shared_defines.h b/include/mcdstub/mcd_sha= red_defines.h new file mode 100644 index 0000000000..b6f2d81c34 --- /dev/null +++ b/include/mcdstub/mcd_shared_defines.h @@ -0,0 +1,132 @@ +/* + * MIT License + * + * Copyright (c) 2023 Lauterbach GmbH, Nicolas Eder + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL= THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN THE + * SOFTWARE. + */ + +/* + *this file is shared between the mcd dll and the mcd stub. + *it has to be kept exectly the same! + */ + +#ifndef MCD_SHARED_DEFINES +#define MCD_SHARED_DEFINES + +/* default tcp port */ +#define MCD_DEFAULT_TCP_PORT "1235" + +/* tcp data characters */ +#define TCP_CHAR_OPEN_SERVER 'I' +#define TCP_CHAR_OPEN_CORE 'i' +#define TCP_CHAR_GO 'C' +#define TCP_CHAR_STEP 'c' +#define TCP_CHAR_BREAK 'b' +#define TCP_CHAR_QUERY 'q' +#define TCP_CHAR_CLOSE_SERVER 'D' +#define TCP_CHAR_CLOSE_CORE 'd' +#define TCP_CHAR_KILLQEMU 'k' +#define TCP_CHAR_RESET 'r' +#define TCP_CHAR_READ_REGISTER 'p' +#define TCP_CHAR_WRITE_REGISTER 'P' +#define TCP_CHAR_READ_MEMORY 'm' +#define TCP_CHAR_WRITE_MEMORY 'M' +#define TCP_CHAR_BREAKPOINT_INSERT 't' +#define TCP_CHAR_BREAKPOINT_REMOVE 'T' + +/* tcp protocol chars */ +#define TCP_ACKNOWLEDGED '+' +#define TCP_NOT_ACKNOWLEDGED '-' +#define TCP_COMMAND_START '$' +#define TCP_COMMAND_END '#' +#define TCP_WAS_LAST '|' +#define TCP_WAS_NOT_LAST '~' +#define TCP_HANDSHAKE_SUCCESS "shaking your hand" +#define TCP_EXECUTION_SUCCESS "success" +#define TCP_EXECUTION_ERROR "error" + +/* tcp query arguments */ +#define QUERY_FIRST "f" +#define QUERY_CONSEQUTIVE "c" +#define QUERY_END_INDEX "!" + +#define QUERY_ARG_SYSTEM "system" +#define QUERY_ARG_CORES "cores" +#define QUERY_ARG_RESET "reset" +#define QUERY_ARG_TRIGGER "trigger" +#define QUERY_ARG_MEMORY "memory" +#define QUERY_ARG_REGGROUP "reggroup" +#define QUERY_ARG_REG "reg" +#define QUERY_ARG_STATE "state" + +/* tcp query packet argument list */ +#define TCP_ARGUMENT_NAME "name" +#define TCP_ARGUMENT_DATA "data" +#define TCP_ARGUMENT_ID "id" +#define TCP_ARGUMENT_TYPE "type" +#define TCP_ARGUMENT_BITS_PER_MAU "bpm" +#define TCP_ARGUMENT_INVARIANCE "i" +#define TCP_ARGUMENT_ENDIAN "e" +#define TCP_ARGUMENT_MIN "min" +#define TCP_ARGUMENT_MAX "max" +#define TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS "sao" +#define TCP_ARGUMENT_REGGROUPID "reggroupid" +#define TCP_ARGUMENT_MEMSPACEID "memspaceid" +#define TCP_ARGUMENT_SIZE "size" +#define TCP_ARGUMENT_THREAD "thread" +#define TCP_ARGUMENT_ADDRESS "address" +#define TCP_ARGUMENT_STOP_STRING "stop_str" +#define TCP_ARGUMENT_INFO_STRING "info_str" +#define TCP_ARGUMENT_STATE "state" +#define TCP_ARGUMENT_EVENT "event" +#define TCP_ARGUMENT_DEVICE "device" +#define TCP_ARGUMENT_CORE "core" +#define TCP_ARGUMENT_AMOUNT_CORE "nr_cores" +#define TCP_ARGUMENT_AMOUNT_TRIGGER "nr_trigger" +#define TCP_ARGUMENT_OPTION "option" +#define TCP_ARGUMENT_ACTION "action" +#define TCP_ARGUMENT_OPCODE "opcode" + +/* for packets sent to qemu */ +#define ARGUMENT_SEPARATOR ';' +#define NEGATIVE_FLAG 0 +#define POSITIVE_FLAG 1 + +/* core states */ +#define CORE_STATE_RUNNING "running" +#define CORE_STATE_HALTED "halted" +#define CORE_STATE_DEBUG "debug" +#define CORE_STATE_UNKNOWN "unknown" + +/* breakpoint types */ +#define MCD_BREAKPOINT_HW 1 +#define MCD_BREAKPOINT_READ 2 +#define MCD_BREAKPOINT_WRITE 3 +#define MCD_BREAKPOINT_RW 4 + +/* trigger data */ +#define MCD_TRIG_ACT_BREAK "check_data_value" +#define MCD_TRIG_OPT_VALUE "break_on_trigger" + +/* register mem space key words */ +#define MCD_GRP_KEYWORD "GPR" +#define MCD_CP_KEYWORD "CP" + +#endif diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/include/mcdstub/mcdstub.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/include/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_com= mon.h new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/include/mcdstub/mcdstub_common.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/include/qemu/debug.h b/include/qemu/debug.h new file mode 100644 index 0000000000..c24aaf1202 --- /dev/null +++ b/include/qemu/debug.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nicolas Eder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: LGPL-2.0+ + */ diff --git a/meson.build b/meson.build index d2c4c2adb3..2e1a7048e9 100644 --- a/meson.build +++ b/meson.build @@ -3263,7 +3263,7 @@ trace_events_subdirs =3D [ 'qom', 'monitor', 'util', - 'gdbstub', + 'debug/gdbstub', ] if have_linux_user trace_events_subdirs +=3D [ 'linux-user' ] @@ -3389,7 +3389,7 @@ subdir('authz') subdir('crypto') subdir('ui') subdir('hw') -subdir('gdbstub') +subdir('debug') =20 if enable_modules libmodulecommon =3D static_library('module-common', files('module-common= .c') + genh, pic: true, c_args: '-DBUILD_DSO') --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983172625267.8490105331905; Thu, 7 Dec 2023 13:06:12 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLXw-0002hl-B7; Thu, 07 Dec 2023 16:04:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXq-0002bS-Dk for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:30 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXm-0005n6-9G for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:30 -0500 Received: (qmail 10238 invoked by uid 484); 7 Dec 2023 21:04:03 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:02 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.081391 secs); 07 Dec 2023 21:04:03 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 02/17] gdbstub: hex conversion functions moved to cutils.h Date: Thu, 7 Dec 2023 22:03:43 +0100 Message-Id: <20231207210358.7409-3-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983173388100006 Content-Type: text/plain; charset="utf-8" --- debug/gdbstub/gdbstub.c | 19 ++++++++++--------- debug/gdbstub/internals.h | 26 -------------------------- include/qemu/cutils.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/debug/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c index 46d752bbc2..f43d4355c0 100644 --- a/debug/gdbstub/gdbstub.c +++ b/debug/gdbstub/gdbstub.c @@ -80,8 +80,8 @@ void gdb_memtohex(GString *buf, const uint8_t *mem, int l= en) int i, c; for(i =3D 0; i < len; i++) { c =3D mem[i]; - g_string_append_c(buf, tohex(c >> 4)); - g_string_append_c(buf, tohex(c & 0xf)); + g_string_append_c(buf, nibble_to_hexchar(c >> 4)); + g_string_append_c(buf, nibble_to_hexchar(c & 0xf)); } g_string_append_c(buf, '\0'); } @@ -91,7 +91,8 @@ void gdb_hextomem(GByteArray *mem, const char *buf, int l= en) int i; =20 for(i =3D 0; i < len; i++) { - guint8 byte =3D fromhex(buf[0]) << 4 | fromhex(buf[1]); + guint8 byte =3D hexchar_to_nibble(buf[0]) << 4 | + hexchar_to_nibble(buf[1]); g_byte_array_append(mem, &byte, 1); buf +=3D 2; } @@ -118,8 +119,8 @@ static void hexdump(const char *buf, int len, if (i < len) { char value =3D buf[i]; =20 - line_buffer[hex_col + 0] =3D tohex((value >> 4) & 0xF); - line_buffer[hex_col + 1] =3D tohex((value >> 0) & 0xF); + line_buffer[hex_col + 0] =3D nibble_to_hexchar((value >> 4) & = 0xF); + line_buffer[hex_col + 1] =3D nibble_to_hexchar((value >> 0) & = 0xF); line_buffer[txt_col + 0] =3D (value >=3D ' ' && value < 127) ? value : '.'; @@ -151,8 +152,8 @@ int gdb_put_packet_binary(const char *buf, int len, boo= l dump) csum +=3D buf[i]; } footer[0] =3D '#'; - footer[1] =3D tohex((csum >> 4) & 0xf); - footer[2] =3D tohex((csum) & 0xf); + footer[1] =3D nibble_to_hexchar((csum >> 4) & 0xf); + footer[2] =3D nibble_to_hexchar((csum) & 0xf); g_byte_array_append(gdbserver_state.last_packet, footer, 3); =20 gdb_put_buffer(gdbserver_state.last_packet->data, @@ -2267,7 +2268,7 @@ void gdb_read_byte(uint8_t ch) break; } gdbserver_state.line_buf[gdbserver_state.line_buf_index] =3D '= \0'; - gdbserver_state.line_csum =3D fromhex(ch) << 4; + gdbserver_state.line_csum =3D hexchar_to_nibble(ch) << 4; gdbserver_state.state =3D RS_CHKSUM2; break; case RS_CHKSUM2: @@ -2277,7 +2278,7 @@ void gdb_read_byte(uint8_t ch) gdbserver_state.state =3D RS_GETLINE; break; } - gdbserver_state.line_csum |=3D fromhex(ch); + gdbserver_state.line_csum |=3D hexchar_to_nibble(ch); =20 if (gdbserver_state.line_csum !=3D (gdbserver_state.line_sum &= 0xff)) { trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_= sum, gdbserver_state.line_csum); diff --git a/debug/gdbstub/internals.h b/debug/gdbstub/internals.h index 5c0c725e54..4b67adfeda 100644 --- a/debug/gdbstub/internals.h +++ b/debug/gdbstub/internals.h @@ -75,32 +75,6 @@ typedef struct GDBState { /* lives in main gdbstub.c */ extern GDBState gdbserver_state; =20 -/* - * Inline utility function, convert from int to hex and back - */ - -static inline int fromhex(int v) -{ - if (v >=3D '0' && v <=3D '9') { - return v - '0'; - } else if (v >=3D 'A' && v <=3D 'F') { - return v - 'A' + 10; - } else if (v >=3D 'a' && v <=3D 'f') { - return v - 'a' + 10; - } else { - return 0; - } -} - -static inline int tohex(int v) -{ - if (v < 10) { - return v + '0'; - } else { - return v - 10 + 'a'; - } -} - /* * Connection helpers for both system and user backends */ diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index 92c927a6a3..5ab1a4ffb0 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -267,4 +267,34 @@ void qemu_hexdump_line(char *line, unsigned int b, con= st void *bufptr, void qemu_hexdump(FILE *fp, const char *prefix, const void *bufptr, size_t size); =20 + +/** + * hexchar_to_nibble() - Converts hex character to nibble. + */ +static inline int hexchar_to_nibble(int v) +{ + if (v >=3D '0' && v <=3D '9') { + return v - '0'; + } else if (v >=3D 'A' && v <=3D 'F') { + return v - 'A' + 10; + } else if (v >=3D 'a' && v <=3D 'f') { + return v - 'a' + 10; + } else { + g_assert_not_reached(); + } +} + +/** + * nibble_to_hexchar() - Converts nibble to hex character. + */ +static inline int nibble_to_hexchar(int v) +{ + g_assert(v <=3D 0xf); + if (v < 10) { + return v + '0'; + } else { + return v - 10 + 'a'; + } +} + #endif --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983110364535.4422356661335; Thu, 7 Dec 2023 13:05:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLXt-0002cx-D0; Thu, 07 Dec 2023 16:04:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXq-0002bK-2v for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:30 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXm-0005nB-9G for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:29 -0500 Received: (qmail 10260 invoked by uid 484); 7 Dec 2023 21:04:04 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:03 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.073749 secs); 07 Dec 2023 21:04:04 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 03/17] gdbstub: GDBRegisterState moved to gdbstub.h so it can be used outside of the gdbstub Date: Thu, 7 Dec 2023 22:03:44 +0100 Message-Id: <20231207210358.7409-4-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983112506100001 Content-Type: text/plain; charset="utf-8" --- debug/gdbstub/gdbstub.c | 8 -------- include/exec/gdbstub.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/debug/gdbstub/gdbstub.c b/debug/gdbstub/gdbstub.c index f43d4355c0..5df7841878 100644 --- a/debug/gdbstub/gdbstub.c +++ b/debug/gdbstub/gdbstub.c @@ -45,14 +45,6 @@ =20 #include "internals.h" =20 -typedef struct GDBRegisterState { - int base_reg; - int num_regs; - gdb_get_reg_cb get_reg; - gdb_set_reg_cb set_reg; - const char *xml; -} GDBRegisterState; - GDBState gdbserver_state; =20 void gdb_init_gdbserver_state(void) diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index d8a3c56fa2..cdbad65930 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -27,6 +27,14 @@ typedef struct GDBFeatureBuilder { typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg); typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg); =20 +typedef struct GDBRegisterState { + int base_reg; + int num_regs; + gdb_get_reg_cb get_reg; + gdb_set_reg_cb set_reg; + const char *xml; +} GDBRegisterState; + /** * gdb_register_coprocessor() - register a supplemental set of registers * @cpu - the CPU associated with registers --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983145505750.6789116422874; Thu, 7 Dec 2023 13:05:45 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLXw-0002hp-ER; Thu, 07 Dec 2023 16:04:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXq-0002bb-SJ for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:31 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXn-0005nM-4o for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:30 -0500 Received: (qmail 10283 invoked by uid 484); 7 Dec 2023 21:04:07 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:05 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.072318 secs); 07 Dec 2023 21:04:07 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 04/17] gdbstub: DebugClass added to system mode. Date: Thu, 7 Dec 2023 22:03:45 +0100 Message-Id: <20231207210358.7409-5-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983146799100003 Content-Type: text/plain; charset="utf-8" This class is used to abstract debug features between different debuggers --- debug/common/debug.c | 33 +++++++++++++++++++++++++++++++++ debug/common/meson.build | 1 + debug/gdbstub/system.c | 18 ++++++++++++++++++ debug/meson.build | 1 + include/hw/boards.h | 1 + include/qemu/debug.h | 20 ++++++++++++++++++++ include/qemu/typedefs.h | 2 ++ system/cpus.c | 9 ++++++++- 8 files changed, 84 insertions(+), 1 deletion(-) diff --git a/debug/common/debug.c b/debug/common/debug.c index c24aaf1202..476c969c98 100644 --- a/debug/common/debug.c +++ b/debug/common/debug.c @@ -16,3 +16,36 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#include "qemu/osdep.h" +#include "qemu/debug.h" +#include "qom/object_interfaces.h" + +static void debug_instance_init(Object *obj) +{ +} + +static void debug_finalize(Object *obj) +{ +} + +static void debug_class_init(ObjectClass *oc, void *data) +{ +} + +static const TypeInfo debug_info =3D { + .name =3D TYPE_DEBUG, + .parent =3D TYPE_OBJECT, + .instance_size =3D sizeof(DebugState), + .instance_init =3D debug_instance_init, + .instance_finalize =3D debug_finalize, + .class_size =3D sizeof(DebugClass), + .class_init =3D debug_class_init +}; + +static void debug_register_types(void) +{ + type_register_static(&debug_info); +} + +type_init(debug_register_types); diff --git a/debug/common/meson.build b/debug/common/meson.build index e69de29bb2..815cb6f0fc 100644 --- a/debug/common/meson.build +++ b/debug/common/meson.build @@ -0,0 +1 @@ +system_ss.add(files('debug.c')) diff --git a/debug/gdbstub/system.c b/debug/gdbstub/system.c index 83fd452800..06bc580147 100644 --- a/debug/gdbstub/system.c +++ b/debug/gdbstub/system.c @@ -14,6 +14,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/cutils.h" +#include "qemu/debug.h" #include "exec/gdbstub.h" #include "gdbstub/syscalls.h" #include "exec/hwaddr.h" @@ -46,6 +47,20 @@ static void reset_gdbserver_state(void) gdbserver_state.allow_stop_reply =3D false; } =20 +/** + * gdb_init_debug_class() - initialize gdb-specific DebugClass + */ +static void gdb_init_debug_class(void) +{ + Object *obj; + obj =3D object_new(TYPE_DEBUG); + DebugState *ds =3D DEBUG(obj); + DebugClass *dc =3D DEBUG_GET_CLASS(ds); + dc->set_stop_cpu =3D gdb_set_stop_cpu; + MachineState *ms =3D MACHINE(qdev_get_machine()); + ms->debug_state =3D ds; +} + /* * Return the GDB index for a given vCPU state. * @@ -405,6 +420,9 @@ int gdbserver_start(const char *device) gdbserver_system_state.mon_chr =3D mon_chr; gdb_syscall_reset(); =20 + /* create new debug object */ + gdb_init_debug_class(); + return 0; } =20 diff --git a/debug/meson.build b/debug/meson.build index a5b093f31e..f46ab14af9 100644 --- a/debug/meson.build +++ b/debug/meson.build @@ -1 +1,2 @@ +subdir('common') subdir('gdbstub') diff --git a/include/hw/boards.h b/include/hw/boards.h index da85f86efb..2e28913afc 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -400,6 +400,7 @@ struct MachineState { CpuTopology smp; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; + DebugState *debug_state; }; =20 #define DEFINE_MACHINE(namestr, machine_initfn) \ diff --git a/include/qemu/debug.h b/include/qemu/debug.h index c24aaf1202..9526f9fb48 100644 --- a/include/qemu/debug.h +++ b/include/qemu/debug.h @@ -16,3 +16,23 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#ifndef QEMU_DEBUG_H +#define QEMU_DEBUG_H + +#include "qom/object.h" +#include "qemu/typedefs.h" + +struct DebugClass { + ObjectClass parent_class; + void (*set_stop_cpu)(CPUState *cpu); +}; + +struct DebugState { + Object parent_obj; +}; + +#define TYPE_DEBUG "debug" +OBJECT_DECLARE_TYPE(DebugState, DebugClass, DEBUG) + +#endif /* QEMU_DEBUG_H */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 5abdbc3874..e48b544173 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -46,6 +46,8 @@ typedef struct CpuInfoFast CpuInfoFast; typedef struct CPUJumpCache CPUJumpCache; typedef struct CPUState CPUState; typedef struct CPUTLBEntryFull CPUTLBEntryFull; +typedef struct DebugClass DebugClass; +typedef struct DebugState DebugState; typedef struct DeviceListener DeviceListener; typedef struct DeviceState DeviceState; typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot; diff --git a/system/cpus.c b/system/cpus.c index a444a747f0..7a7fff14bc 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "monitor/monitor.h" #include "qemu/coroutine-tls.h" +#include "qemu/debug.h" #include "qapi/error.h" #include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc.h" @@ -313,7 +314,13 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - gdb_set_stop_cpu(cpu); + MachineState *ms =3D MACHINE(qdev_get_machine()); + DebugState *ds =3D ms->debug_state; + DebugClass *dc =3D DEBUG_GET_CLASS(ds); + + if (dc->set_stop_cpu) { + dc->set_stop_cpu(cpu); + } qemu_system_debug_request(); cpu->stopped =3D true; } --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983172520895.1192366667859; Thu, 7 Dec 2023 13:06:12 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY2-0002kE-7D; Thu, 07 Dec 2023 16:04:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXs-0002dC-0S for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:32 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXn-0005nf-Uk for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:31 -0500 Received: (qmail 10305 invoked by uid 484); 7 Dec 2023 21:04:08 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:07 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.073117 secs); 07 Dec 2023 21:04:08 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 05/17] mcdstub: memory helper functions added Date: Thu, 7 Dec 2023 22:03:46 +0100 Message-Id: <20231207210358.7409-6-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983173376100005 Content-Type: text/plain; charset="utf-8" --- include/exec/cpu-common.h | 3 +++ include/exec/memory.h | 9 +++++++++ system/memory.c | 11 +++++++++++ system/physmem.c | 26 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 41115d8919..dd989b5ab2 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -182,6 +182,9 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t star= t, size_t length); int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, void *ptr, size_t len, bool is_write); =20 +int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *le= n); + + /* vl.c */ void list_cpus(void); =20 diff --git a/include/exec/memory.h b/include/exec/memory.h index 831f7c996d..174de807d5 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -3142,6 +3142,15 @@ bool ram_block_discard_is_disabled(void); */ bool ram_block_discard_is_required(void); =20 +/* + * mcd_find_address_space() - Find the address spaces with the correspondi= ng + * name. + * + * Currently only used by the mcd debugger. + * @as_name: Name to look for. + */ +AddressSpace *mcd_find_address_space(const char *as_name); + #endif =20 #endif diff --git a/system/memory.c b/system/memory.c index 798b6c0a17..9a8fa79e0c 100644 --- a/system/memory.c +++ b/system/memory.c @@ -3562,6 +3562,17 @@ void mtree_info(bool flatview, bool dispatch_tree, b= ool owner, bool disabled) } } =20 +AddressSpace *mcd_find_address_space(const char *as_name) +{ + AddressSpace *as; + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + if (strcmp(as->name, as_name) =3D=3D 0) { + return as; + } + } + return NULL; +} + void memory_region_init_ram(MemoryRegion *mr, Object *owner, const char *name, diff --git a/system/physmem.c b/system/physmem.c index a63853a7bc..70733c67c7 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -3422,6 +3422,32 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, return 0; } =20 +int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *le= n) +{ + hwaddr phys_addr; + vaddr l, page; + + cpu_synchronize_state(cpu); + MemTxAttrs attrs; + + page =3D *addr & TARGET_PAGE_MASK; + phys_addr =3D cpu_get_phys_page_attrs_debug(cpu, page, &attrs); + /* if no physical page mapped, return an error */ + if (phys_addr =3D=3D -1) { + return -1; + } + l =3D (page + TARGET_PAGE_SIZE) - *addr; + if (l > *len) { + l =3D *len; + } + phys_addr +=3D (*addr & ~TARGET_PAGE_MASK); + + /* set output values */ + *addr =3D phys_addr; + *len =3D l; + return 0; +} + /* * Allows code that needs to deal with migration bitmaps etc to still be b= uilt * target independent. --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983206059260.8005399639135; Thu, 7 Dec 2023 13:06:46 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY4-0002mG-2z; Thu, 07 Dec 2023 16:04:44 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXs-0002gn-T9 for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:33 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXp-0005ns-Ik for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:32 -0500 Received: (qmail 10328 invoked by uid 484); 7 Dec 2023 21:04:09 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:08 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 4e-06 secs); 07 Dec 2023 21:04:09 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 06/17] mcdstub: -mcd start option added, mcd specific defines added Date: Thu, 7 Dec 2023 22:03:47 +0100 Message-Id: <20231207210358.7409-7-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983208221100003 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 201 +++++++++++++++++++++++++++++++ debug/mcdstub/meson.build | 12 ++ debug/meson.build | 1 + include/mcdstub/mcdstub.h | 152 +++++++++++++++++++++++ include/mcdstub/mcdstub_common.h | 46 +++++++ qemu-options.hx | 18 +++ system/vl.c | 13 ++ 7 files changed, 443 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index c24aaf1202..32f4d1980f 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -16,3 +16,204 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "chardev/char.h" +#include "chardev/char-fe.h" +#include "sysemu/cpus.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" + +#include "mcdstub/mcd_shared_defines.h" +#include "mcdstub/mcdstub.h" + +typedef struct { + CharBackend chr; +} MCDSystemState; + +MCDSystemState mcdserver_system_state; + +MCDState mcdserver_state; + +/** + * mcd_supports_guest_debug() - Returns true if debugging the selected + * accelerator is supported. + */ +static bool mcd_supports_guest_debug(void) +{ + const AccelOpsClass *ops =3D cpus_get_accel(); + if (ops->supports_guest_debug) { + return ops->supports_guest_debug(); + } + return false; +} + +#ifndef _WIN32 +static void mcd_sigterm_handler(int signal) +{ + if (runstate_is_running()) { + vm_stop(RUN_STATE_PAUSED); + } +} +#endif + +/** + * mcd_vm_state_change() - Handles a state change of the QEMU VM. + * + * This function is called when the QEMU VM goes through a state transitio= n. + * It stores the runstate the CPU is in to the cpu_state and when in + * RUN_STATE_DEBUG it collects additional data on what watchpoint was hit. + * This function also resets the singlestep behavior. + * @running: True if he VM is running. + * @state: The new (and active) VM run state. + */ +static void mcd_vm_state_change(void *opaque, bool running, RunState state) +{ +} + +/** + * mcd_chr_can_receive() - Returns the maximum packet length of a TCP pack= et. + */ +static int mcd_chr_can_receive(void *opaque) +{ + return MAX_PACKET_LENGTH; +} + +/** + * mcd_chr_receive() - Handles receiving a TCP packet. + * + * This function gets called by QEMU when a TCP packet is received. + * It iterates over that packet an calls :c:func:`mcd_read_byte` for each = char + * of the packet. + * @buf: Content of the packet. + * @size: Length of the packet. + */ +static void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) +{ +} + +/** + * mcd_chr_event() - Handles a TCP client connect. + * + * This function gets called by QEMU when a TCP cliet connects to the open= ed + * TCP port. It attaches the first process. From here on TCP packets can be + * exchanged. + * @event: Type of event. + */ +static void mcd_chr_event(void *opaque, QEMUChrEvent event) +{ +} + +/** + * mcd_init_mcdserver_state() - Initializes the mcdserver_state struct. + * + * This function allocates memory for the mcdserver_state struct and sets + * all of its members to their inital values. This includes setting the + * cpu_state to halted and initializing the query functions with + * :c:func:`init_query_cmds_table`. + */ +static void mcd_init_mcdserver_state(void) +{ +} + +/** + * reset_mcdserver_state() - Resets the mcdserver_state struct. + * + * This function deletes all processes connected to the mcdserver_state. + */ +static void reset_mcdserver_state(void) +{ +} + +/** + * create_processes() - Sorts all processes and calls + * :c:func:`mcd_create_default_process`. + * + * This function sorts all connected processes with the qsort function. + * Afterwards, it creates a new process with + * :c:func:`mcd_create_default_process`. + * @s: A MCDState object. + */ +static void create_processes(MCDState *s) +{ +} + +int mcdserver_start(const char *device) +{ + char mcd_device_config[TCP_CONFIG_STRING_LENGTH]; + char mcd_tcp_port[TCP_CONFIG_STRING_LENGTH]; + Chardev *chr =3D NULL; + + if (!first_cpu) { + error_report("mcdstub: meaningless to attach to a " + "machine without any CPU."); + return -1; + } + + if (!mcd_supports_guest_debug()) { + error_report("mcdstub: current accelerator doesn't " + "support guest debugging"); + return -1; + } + + if (!device) { + return -1; + } + + /* if device =3D=3D default -> set tcp_port =3D tcp:: */ + if (strcmp(device, "default") =3D=3D 0) { + snprintf(mcd_tcp_port, sizeof(mcd_tcp_port), "tcp::%s", + MCD_DEFAULT_TCP_PORT); + device =3D mcd_tcp_port; + } + + if (strcmp(device, "none") !=3D 0) { + if (strstart(device, "tcp:", NULL)) { + /* enforce required TCP attributes */ + snprintf(mcd_device_config, sizeof(mcd_device_config), + "%s,wait=3Doff,nodelay=3Don,server=3Don", device); + device =3D mcd_device_config; + } +#ifndef _WIN32 + else if (strcmp(device, "stdio") =3D=3D 0) { + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler =3D mcd_sigterm_handler; + sigaction(SIGINT, &act, NULL); + strcpy(mcd_device_config, device); + } +#endif + chr =3D qemu_chr_new_noreplay("mcd", device, true, NULL); + if (!chr) { + return -1; + } + } + + if (!mcdserver_state.init) { + mcd_init_mcdserver_state(); + + qemu_add_vm_change_state_handler(mcd_vm_state_change, NULL); + } else { + qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); + reset_mcdserver_state(); + } + + create_processes(&mcdserver_state); + + if (chr) { + qemu_chr_fe_init(&mcdserver_system_state.chr, chr, &error_abort); + qemu_chr_fe_set_handlers(&mcdserver_system_state.chr, + mcd_chr_can_receive, + mcd_chr_receive, mcd_chr_event, + NULL, &mcdserver_state, NULL, true); + } + mcdserver_state.state =3D chr ? RS_IDLE : RS_INACTIVE; + + return 0; +} diff --git a/debug/mcdstub/meson.build b/debug/mcdstub/meson.build index e69de29bb2..7e5ae878b0 100644 --- a/debug/mcdstub/meson.build +++ b/debug/mcdstub/meson.build @@ -0,0 +1,12 @@ +# only system emulation is supported over mcd +mcd_system_ss =3D ss.source_set() +mcd_system_ss.add(files('mcdstub.c')) +mcd_system_ss =3D mcd_system_ss.apply(config_host, strict: false) + +libmcd_system =3D static_library('mcd_system', + mcd_system_ss.sources() + genh, + name_suffix: 'fa', + build_by_default: have_system) + +mcd_system =3D declare_dependency(link_whole: libmcd_system) +system_ss.add(mcd_system) diff --git a/debug/meson.build b/debug/meson.build index f46ab14af9..97c80d7406 100644 --- a/debug/meson.build +++ b/debug/meson.build @@ -1,2 +1,3 @@ subdir('common') subdir('gdbstub') +subdir('mcdstub') diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index c24aaf1202..9ec9b427bd 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -16,3 +16,155 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#ifndef MCDSTUB_H +#define MCDSTUB_H + +#include "mcdstub_common.h" + +#define MAX_PACKET_LENGTH 1024 + +/* trigger defines */ +#define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 +#define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 + +/* schema defines */ +#define ARG_SCHEMA_QRYHANDLE 'q' +#define ARG_SCHEMA_STRING 's' +#define ARG_SCHEMA_INT 'd' +#define ARG_SCHEMA_UINT64_T 'l' +#define ARG_SCHEMA_CORENUM 'c' +#define ARG_SCHEMA_HEXDATA 'h' + +/* resets */ +#define RESET_SYSTEM "full_system_reset" +#define RESET_GPR "gpr_reset" +#define RESET_MEMORY "memory_reset" + +/* misc */ +#define QUERY_TOTAL_NUMBER 12 +#define CMD_SCHEMA_LENGTH 6 +#define MCD_SYSTEM_NAME "qemu-system" + +/* supported architectures */ +#define MCDSTUB_ARCH_ARM "arm" + +/* tcp query packet values templates */ +#define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" + +/* state strings */ +#define STATE_STR_UNKNOWN(d) "cpu " #d " in unknown state" +#define STATE_STR_DEBUG(d) "cpu " #d " in debug state" +#define STATE_STR_RUNNING(d) "cpu " #d " running" +#define STATE_STR_HALTED(d) "cpu " #d " currently halted" +#define STATE_STR_INIT_HALTED "vm halted since boot" +#define STATE_STR_INIT_RUNNING "vm running since boot" +#define STATE_STR_BREAK_HW "stopped beacuse of HW breakpoint" +#define STATE_STEP_PERFORMED "stopped beacuse of single step" +#define STATE_STR_BREAK_READ(d) "stopped beacuse of read access at " #d +#define STATE_STR_BREAK_WRITE(d) "stopped beacuse of write access at " #d +#define STATE_STR_BREAK_RW(d) "stopped beacuse of read or write access at = " #d +#define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason" + +typedef struct MCDProcess { + uint32_t pid; + bool attached; +} MCDProcess; + +typedef void (*MCDCmdHandler)(GArray *params, void *user_ctx); +typedef struct MCDCmdParseEntry { + MCDCmdHandler handler; + const char *cmd; + char schema[CMD_SCHEMA_LENGTH]; +} MCDCmdParseEntry; + +typedef union MCDCmdVariant { + const char *data; + uint32_t data_uint32_t; + uint64_t data_uint64_t; + uint32_t query_handle; + uint32_t cpu_id; +} MCDCmdVariant; + +#define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) + +enum RSState { + RS_INACTIVE, + RS_IDLE, + RS_GETLINE, + RS_DATAEND, +}; + +typedef struct breakpoint_st { + uint32_t type; + uint64_t address; + uint32_t id; +} breakpoint_st; + +typedef struct mcd_trigger_into_st { + char type[ARGUMENT_STRING_LENGTH]; + char option[ARGUMENT_STRING_LENGTH]; + char action[ARGUMENT_STRING_LENGTH]; + uint32_t nr_trigger; +} mcd_trigger_into_st; + +typedef struct mcd_cpu_state_st { + const char *state; + bool memory_changed; + bool registers_changed; + bool target_was_stopped; + uint32_t bp_type; + uint64_t bp_address; + const char *stop_str; + const char *info_str; +} mcd_cpu_state_st; + +typedef struct MCDState { + bool init; + CPUState *c_cpu; + enum RSState state; + char line_buf[MAX_PACKET_LENGTH]; + int line_buf_index; + int line_sum; + int line_csum; + GByteArray *last_packet; + int signal; + + MCDProcess *processes; + int process_num; + GString *str_buf; + GByteArray *mem_buf; + int sstep_flags; + int supported_sstep_flags; + + uint32_t query_cpu_id; + GList *all_memspaces; + GList *all_reggroups; + GList *all_registers; + GList *all_breakpoints; + GArray *resets; + mcd_trigger_into_st trigger; + mcd_cpu_state_st cpu_state; + MCDCmdParseEntry mcd_query_cmds_table[QUERY_TOTAL_NUMBER]; +} MCDState; + +/* lives in mcdstub.c */ +extern MCDState mcdserver_state; + +typedef struct xml_attrib { + char argument[ARGUMENT_STRING_LENGTH]; + char value[ARGUMENT_STRING_LENGTH]; +} xml_attrib; + +typedef struct mcd_reset_st { + const char *name; + uint8_t id; +} mcd_reset_st; + +/** + * mcdserver_start() - initializes the mcdstub and opens a TCP port + * @device: TCP port (e.g. tcp::1235) + */ +int mcdserver_start(const char *device); + +#endif /* MCDSTUB_H */ diff --git a/include/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_com= mon.h index c24aaf1202..b64748c080 100644 --- a/include/mcdstub/mcdstub_common.h +++ b/include/mcdstub/mcdstub_common.h @@ -16,3 +16,49 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#ifndef MCDSTUB_COMMON_H +#define MCDSTUB_COMMON_H + +#define ARGUMENT_STRING_LENGTH 64 +#define TCP_CONFIG_STRING_LENGTH 128 + +typedef struct mcd_mem_space_st { + const char *name; + uint32_t id; + uint32_t type; + uint32_t bits_per_mau; + uint8_t invariance; + uint32_t endian; + uint64_t min_addr; + uint64_t max_addr; + uint32_t supported_access_options; + /* internal */ + bool is_secure; + bool is_physical; +} mcd_mem_space_st; + +typedef struct mcd_reg_st { + /* xml info */ + char name[ARGUMENT_STRING_LENGTH]; + char group[ARGUMENT_STRING_LENGTH]; + char type[ARGUMENT_STRING_LENGTH]; + uint32_t bitsize; + uint32_t id; /* id used by the mcd interface */ + uint32_t internal_id; /* id inside reg type */ + uint8_t reg_type; + /* mcd metadata */ + uint32_t mcd_reg_group_id; + uint32_t mcd_mem_space_id; + uint32_t mcd_reg_type; + uint32_t mcd_hw_thread_id; + /* data for op-code */ + uint32_t opcode; +} mcd_reg_st; + +typedef struct mcd_reg_group_st { + const char *name; + uint32_t id; +} mcd_reg_group_st; + +#endif /* MCDSTUB_COMMON_H */ diff --git a/qemu-options.hx b/qemu-options.hx index 42fd09e4de..b60df3463c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4444,6 +4444,24 @@ SRST (see the :ref:`GDB usage` chapter in the System Emulation Users Guide). ERST =20 +DEF("mcd", HAS_ARG, QEMU_OPTION_mcd, \ + "-mcd dev accept mcd connection on 'dev'. (QEMU defaults to sta= rting\n" + " the guest without waiting for a mcd client to connect= ; use -S too\n" + " if you want it to not start execution.)\n" + " To use the default Port write '-mcd default'\n", + QEMU_ARCH_ALL) +SRST +``-mcd dev`` + Accept a mcd connection on device dev. Note that this option does not = pause QEMU + execution -- if you want QEMU to not start the guest until you + connect with mcd and issue a ``run`` command, you will need to + also pass the ``-S`` option to QEMU. + + The most usual configuration is to listen on a local TCP socket:: + + -mcd tcp::1235 +ERST + DEF("d", HAS_ARG, QEMU_OPTION_d, \ "-d item1,... enable logging of specified items (use '-d help' for = a list of log items)\n", QEMU_ARCH_ALL) diff --git a/system/vl.c b/system/vl.c index 2bcd9efb9a..2c4610c19f 100644 --- a/system/vl.c +++ b/system/vl.c @@ -68,6 +68,7 @@ #include "sysemu/numa.h" #include "sysemu/hostmem.h" #include "exec/gdbstub.h" +#include "mcdstub/mcdstub.h" #include "qemu/timer.h" #include "chardev/char.h" #include "qemu/bitmap.h" @@ -1271,6 +1272,7 @@ struct device_config { DEV_PARALLEL, /* -parallel */ DEV_DEBUGCON, /* -debugcon */ DEV_GDB, /* -gdb, -s */ + DEV_MCD, /* -mcd */ DEV_SCLP, /* s390 sclp */ } type; const char *cmdline; @@ -2686,6 +2688,12 @@ static void qemu_machine_creation_done(void) if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } + if (foreach_device_config(DEV_MCD, mcdserver_start) < 0) { + /* + * starts the mcdserver if the mcd option was set + */ + exit(1); + } if (!vga_interface_created && !default_vga && vga_interface_type !=3D VGA_NONE) { warn_report("A -vga option was passed but this machine " @@ -3041,6 +3049,11 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_gdb: add_device_config(DEV_GDB, optarg); break; +#if !defined(CONFIG_USER_ONLY) + case QEMU_OPTION_mcd: + add_device_config(DEV_MCD, optarg); + break; +#endif case QEMU_OPTION_L: if (is_help_option(optarg)) { list_data_dirs =3D true; --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983159467653.398715418034; Thu, 7 Dec 2023 13:05:59 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY2-0002kt-UQ; Thu, 07 Dec 2023 16:04:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXs-0002go-TO for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:33 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXq-0005o2-IQ for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:32 -0500 Received: (qmail 10351 invoked by uid 484); 7 Dec 2023 21:04:11 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:09 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 3e-06 secs); 07 Dec 2023 21:04:11 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 07/17] mcdstub: mcdserver initialization functions added Date: Thu, 7 Dec 2023 22:03:48 +0100 Message-Id: <20231207210358.7409-8-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983161139100003 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 154 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index 32f4d1980f..176d5d2311 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -22,9 +22,12 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/error-report.h" +#include "qemu/debug.h" #include "qapi/error.h" #include "chardev/char.h" #include "chardev/char-fe.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "sysemu/runstate.h" @@ -109,6 +112,39 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent e= vent) { } =20 +/** + * init_query_cmds_table() - Initializes all query functions. + * + * This function adds all query functions to the mcd_query_cmds_table. This + * includes their command string, handler function and parameter schema. + * @mcd_query_cmds_table: Lookup table with all query commands. + */ +static void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) +{} + +/** + * mcd_set_stop_cpu() - Sets c_cpu to the just stopped CPU. + * + * @cpu: The CPU state. + */ +static void mcd_set_stop_cpu(CPUState *cpu) +{ + mcdserver_state.c_cpu =3D cpu; +} + +/** + * mcd_init_debug_class() - initialize mcd-specific DebugClass + */ +static void mcd_init_debug_class(void){ + Object *obj; + obj =3D object_new(TYPE_DEBUG); + DebugState *ds =3D DEBUG(obj); + DebugClass *dc =3D DEBUG_GET_CLASS(ds); + dc->set_stop_cpu =3D mcd_set_stop_cpu; + MachineState *ms =3D MACHINE(qdev_get_machine()); + ms->debug_state =3D ds; +} + /** * mcd_init_mcdserver_state() - Initializes the mcdserver_state struct. * @@ -119,6 +155,35 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent e= vent) */ static void mcd_init_mcdserver_state(void) { + g_assert(!mcdserver_state.init); + memset(&mcdserver_state, 0, sizeof(MCDState)); + mcdserver_state.init =3D true; + mcdserver_state.str_buf =3D g_string_new(NULL); + mcdserver_state.mem_buf =3D g_byte_array_sized_new(MAX_PACKET_LENGTH); + mcdserver_state.last_packet =3D g_byte_array_sized_new(MAX_PACKET_LENG= TH + 4); + + /* + * What single-step modes are supported is accelerator dependent. + * By default try to use no IRQs and no timers while single + * stepping so as to make single stepping like a typical ICE HW step. + */ + mcdserver_state.supported_sstep_flags =3D + accel_supported_gdbstub_sstep_flags(); + mcdserver_state.sstep_flags =3D SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOT= IMER; + mcdserver_state.sstep_flags &=3D mcdserver_state.supported_sstep_flags; + + /* init query table */ + init_query_cmds_table(mcdserver_state.mcd_query_cmds_table); + + /* at this time the cpu hans't been started! -> set cpu_state */ + mcd_cpu_state_st cpu_state =3D { + .state =3D CORE_STATE_HALTED, + .info_str =3D STATE_STR_INIT_HALTED, + }; + mcdserver_state.cpu_state =3D cpu_state; + + /* create new debug object */ + mcd_init_debug_class(); } =20 /** @@ -128,6 +193,84 @@ static void mcd_init_mcdserver_state(void) */ static void reset_mcdserver_state(void) { + g_free(mcdserver_state.processes); + mcdserver_state.processes =3D NULL; + mcdserver_state.process_num =3D 0; +} + +/** + * mcd_create_default_process() - Creates a default process for debugging. + * + * This function creates a new, not yet attached, process with an ID one a= bove + * the previous maximum ID. + * @s: A MCDState object. + */ +static void mcd_create_default_process(MCDState *s) +{ + MCDProcess *process; + int max_pid =3D 0; + + if (mcdserver_state.process_num) { + max_pid =3D s->processes[s->process_num - 1].pid; + } + + s->processes =3D g_renew(MCDProcess, s->processes, ++s->process_num); + process =3D &s->processes[s->process_num - 1]; + + /* We need an available PID slot for this process */ + assert(max_pid < UINT32_MAX); + + process->pid =3D max_pid + 1; + process->attached =3D false; +} + +/** + * find_cpu_clusters() - Returns the CPU cluster of the child object. + * + * @param[in] child Object with unknown CPU cluster. + * @param[in] opaque Pointer to an MCDState object. + */ +static int find_cpu_clusters(Object *child, void *opaque) +{ + if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) { + MCDState *s =3D (MCDState *) opaque; + CPUClusterState *cluster =3D CPU_CLUSTER(child); + MCDProcess *process; + + s->processes =3D g_renew(MCDProcess, s->processes, ++s->process_nu= m); + + process =3D &s->processes[s->process_num - 1]; + assert(cluster->cluster_id !=3D UINT32_MAX); + process->pid =3D cluster->cluster_id + 1; + process->attached =3D false; + + return 0; + } + + return object_child_foreach(child, find_cpu_clusters, opaque); +} + +/** + * pid_order() - Compares process IDs. + * + * This function returns -1 if process "a" has a ower process ID than "b". + * If "b" has a lower ID than "a" 1 is returned and if they are qual 0 is + * returned. + * @a: Process a. + * @b: Process b. + */ +static int pid_order(const void *a, const void *b) +{ + MCDProcess *pa =3D (MCDProcess *) a; + MCDProcess *pb =3D (MCDProcess *) b; + + if (pa->pid < pb->pid) { + return -1; + } else if (pa->pid > pb->pid) { + return 1; + } else { + return 0; + } } =20 /** @@ -141,6 +284,17 @@ static void reset_mcdserver_state(void) */ static void create_processes(MCDState *s) { + object_child_foreach(object_get_root(), find_cpu_clusters, s); + + if (mcdserver_state.processes) { + /* Sort by PID */ + qsort(mcdserver_state.processes, + mcdserver_state.process_num, + sizeof(mcdserver_state.processes[0]), + pid_order); + } + + mcd_create_default_process(s); } =20 int mcdserver_start(const char *device) --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983315916113.2223020336312; Thu, 7 Dec 2023 13:08:35 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY4-0002mZ-IC; Thu, 07 Dec 2023 16:04:44 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXz-0002k7-SR for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:40 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXv-0005oG-4U for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:37 -0500 Received: (qmail 10374 invoked by uid 484); 7 Dec 2023 21:04:13 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:11 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.072232 secs); 07 Dec 2023 21:04:13 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 08/17] cutils: qemu_strtou32 function added Date: Thu, 7 Dec 2023 22:03:49 +0100 Message-Id: <20231207210358.7409-9-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983316292100001 Content-Type: text/plain; charset="utf-8" --- include/qemu/cutils.h | 2 ++ util/cutils.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index 5ab1a4ffb0..14f492ba61 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -158,6 +158,8 @@ int qemu_strtoul(const char *nptr, const char **endptr,= int base, unsigned long *result); int qemu_strtoi64(const char *nptr, const char **endptr, int base, int64_t *result); +int qemu_strtou32(const char *nptr, const char **endptr, int base, + uint32_t *result); int qemu_strtou64(const char *nptr, const char **endptr, int base, uint64_t *result); int qemu_strtod(const char *nptr, const char **endptr, double *result); diff --git a/util/cutils.c b/util/cutils.c index 42364039a5..5e00a4ec14 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -665,6 +665,36 @@ int qemu_strtoi64(const char *nptr, const char **endpt= r, int base, return check_strtox_error(nptr, ep, endptr, *result =3D=3D 0, errno); } =20 +/** + * Convert string @nptr to an uint32_t. + * + * Works like qemu_strtoul(), except it stores UINT32_MAX on overflow. + * (If you want to prohibit negative numbers that wrap around to + * positive, use parse_uint()). + */ +int qemu_strtou32(const char *nptr, const char **endptr, int base, + uint32_t *result) +{ + char *ep; + + assert((unsigned) base <=3D 36 && base !=3D 1); + if (!nptr) { + *result =3D 0; + if (endptr) { + *endptr =3D nptr; + } + return -EINVAL; + } + + errno =3D 0; + *result =3D strtoul(nptr, &ep, base); + /* Windows returns 1 for negative out-of-range values. */ + if (errno =3D=3D ERANGE) { + *result =3D -1; + } + return check_strtox_error(nptr, ep, endptr, *result =3D=3D 0, errno); +} + /** * Convert string @nptr to an uint64_t. * --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983110381498.32689729445235; Thu, 7 Dec 2023 13:05:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY9-0002o6-LL; Thu, 07 Dec 2023 16:04:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY1-0002kA-5Q for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:41 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXw-0005oD-3D for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:40 -0500 Received: (qmail 10396 invoked by uid 484); 7 Dec 2023 21:04:14 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:13 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.279061 secs); 07 Dec 2023 21:04:14 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 09/17] mcdstub: TCP packet plumbing added Date: Thu, 7 Dec 2023 22:03:50 +0100 Message-Id: <20231207210358.7409-10-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983112552100005 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 422 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index 176d5d2311..f97bccf409 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -87,6 +87,320 @@ static int mcd_chr_can_receive(void *opaque) return MAX_PACKET_LENGTH; } =20 +/** + * mcd_put_buffer() - Sends the buf as TCP packet with qemu_chr_fe_write_a= ll. + * + * @buf: TCP packet data. + * @len: TCP packet length. + */ +static void mcd_put_buffer(const uint8_t *buf, int len) +{ + qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len); +} + +/** + * mcd_put_packet_binary() - Adds footer and header to the TCP packet data= in + * buf. + * + * Besides adding header and footer, this function also stores the complet= e TCP + * packet in the last_packet member of the mcdserver_state. Then the packet + * gets send with the :c:func:`mcd_put_buffer` function. + * @buf: TCP packet data. + * @len: TCP packet length. + */ +static int mcd_put_packet_binary(const char *buf, int len) +{ + g_byte_array_set_size(mcdserver_state.last_packet, 0); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) buf, len); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1); + + mcd_put_buffer(mcdserver_state.last_packet->data, + mcdserver_state.last_packet->len); + return 0; +} + +/** + * mcd_put_packet() - Calls :c:func:`mcd_put_packet_binary` with buf and l= ength + * of buf. + * + * @buf: TCP packet data. + */ +static int mcd_put_packet(const char *buf) +{ + return mcd_put_packet_binary(buf, strlen(buf)); +} + +/** + * cmd_parse_params() - Extracts all parameters from a TCP packet. + * + * This function uses the schema parameter to determine which type of para= meter + * to expect. It then extracts that parameter from the data and stores it = in + * the params GArray. + * @data: TCP packet data. + * @schema: List of expected parameters for the packet. + * @params: GArray with all extracted parameters. + */ +static int cmd_parse_params(const char *data, const char *schema, + GArray *params) +{ + char data_buffer[64] =3D {0}; + const char *remaining_data =3D data; + + for (int i =3D 0; i < strlen(schema); i++) { + /* get correct part of data */ + char *separator =3D strchr(remaining_data, ARGUMENT_SEPARATOR); + + if (separator) { + /* multiple arguments */ + int seperator_index =3D (int)(separator - remaining_data); + strncpy(data_buffer, remaining_data, seperator_index); + data_buffer[seperator_index] =3D 0; + } else { + strncpy(data_buffer, remaining_data, strlen(remaining_data)); + data_buffer[strlen(remaining_data)] =3D 0; + } + + /* store right data */ + MCDCmdVariant this_param; + switch (schema[i]) { + case ARG_SCHEMA_STRING: + /* this has to be the last argument */ + this_param.data =3D remaining_data; + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_HEXDATA: + g_string_printf(mcdserver_state.str_buf, "%s", data_buffer); + break; + case ARG_SCHEMA_INT: + if (qemu_strtou32(remaining_data, &remaining_data, 10, + (uint32_t *)&this_param.data_uint32_t)) { + return -1; + } + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_UINT64_T: + if (qemu_strtou64(remaining_data, &remaining_data, 10, + (uint64_t *)&this_param.data_uint64_t)) { + return -1; + } + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_QRYHANDLE: + if (qemu_strtou32(remaining_data, &remaining_data, 10, + (uint32_t *)&this_param.query_handle)) { + return -1; + } + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_CORENUM: + if (qemu_strtou32(remaining_data, &remaining_data, 10, + (uint32_t *)&this_param.cpu_id)) { + return -1; + } + g_array_append_val(params, this_param); + break; + default: + return -1; + } + /* update remaining data for the next run */ + remaining_data =3D &(remaining_data[1]); + } + return 0; +} + +/** + * process_string_cmd() - Collects all parameters from the data and calls = the + * correct handler. + * + * The parameters are extracted with the :c:func:`cmd_parse_params functio= n. + * This function selects the command in the cmds array, which fits the sta= rt of + * the data string. This way the correct commands is selected. + * @data: TCP packet data. + * @cmds: Array of possible commands. + * @num_cmds: Number of commands in the cmds array. + */ +static int process_string_cmd(void *user_ctx, const char *data, + const MCDCmdParseEntry *cmds, int num_cmds) +{ + int i; + g_autoptr(GArray) params =3D g_array_new(false, true, sizeof(MCDCmdVar= iant)); + + if (!cmds) { + return -1; + } + + for (i =3D 0; i < num_cmds; i++) { + const MCDCmdParseEntry *cmd =3D &cmds[i]; + g_assert(cmd->handler && cmd->cmd); + + /* continue if data and command are different */ + if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) { + continue; + } + + if (strlen(cmd->schema)) { + /* extract data for parameters */ + if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, par= ams)) + { + return -1; + } + } + + /* call handler */ + cmd->handler(params, user_ctx); + return 0; + } + + return -1; +} + +/** + * run_cmd_parser() - Prepares the mcdserver_state before executing TCP pa= cket + * functions. + * + * This function empties the str_buf and mem_buf of the mcdserver_state and + * then calls :c:func:`process_string_cmd`. In case this function fails, an + * empty TCP packet is sent back the MCD Shared Library. + * @data: TCP packet data. + * @cmd: Handler function (can be an array of functions). + */ +static void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) +{ + if (!data) { + return; + } + + g_string_set_size(mcdserver_state.str_buf, 0); + g_byte_array_set_size(mcdserver_state.mem_buf, 0); + + if (process_string_cmd(NULL, data, cmd, 1)) { + mcd_put_packet(""); + } +} + +/** + * mcd_handle_packet() - Evaluates the type of received packet and chooses= the + * correct handler. + * + * This function takes the first character of the line_buf to determine the + * type of packet. Then it selects the correct handler function and parame= ter + * schema. With this info it calls :c:func:`run_cmd_parser`. + * @line_buf: TCP packet data. + */ +static int mcd_handle_packet(const char *line_buf) +{ + /* + * decides what function (handler) to call depending on + * the first character in the line_buf + */ + const MCDCmdParseEntry *cmd_parser =3D NULL; + + switch (line_buf[0]) { + default: + /* command not supported */ + mcd_put_packet(""); + break; + } + + if (cmd_parser) { + /* parse commands and run the selected handler function */ + run_cmd_parser(line_buf, cmd_parser); + } + + return RS_IDLE; +} + +/** + * mcd_read_byte() - Resends the last packet if not acknowledged and extra= cts + * the data from a received TCP packet. + * + * In case the last sent packet was not acknowledged from the mcdstub, + * this function resends it. + * If it was acknowledged this function parses the incoming packet + * byte by byte. + * It extracts the data in the packet and sends an + * acknowledging response when finished. Then :c:func:`mcd_handle_packet` = gets + * called. + * @ch: Character of the received TCP packet, which should be parsed. + */ +static void mcd_read_byte(uint8_t ch) +{ + uint8_t reply; + + if (mcdserver_state.last_packet->len) { + if (ch =3D=3D TCP_NOT_ACKNOWLEDGED) { + /* the previous packet was not akcnowledged */ + mcd_put_buffer(mcdserver_state.last_packet->data, + mcdserver_state.last_packet->len); + } else if (ch =3D=3D TCP_ACKNOWLEDGED) { + /* the previous packet was acknowledged */ + } + + if (ch =3D=3D TCP_ACKNOWLEDGED || ch =3D=3D TCP_COMMAND_START) { + /* + * either acknowledged or a new communication starts + * -> discard previous packet + */ + g_byte_array_set_size(mcdserver_state.last_packet, 0); + } + if (ch !=3D TCP_COMMAND_START) { + /* skip to the next char */ + return; + } + } + + switch (mcdserver_state.state) { + case RS_IDLE: + if (ch =3D=3D TCP_COMMAND_START) { + /* start of command packet */ + mcdserver_state.line_buf_index =3D 0; + mcdserver_state.line_sum =3D 0; + mcdserver_state.state =3D RS_GETLINE; + } + break; + case RS_GETLINE: + if (ch =3D=3D TCP_COMMAND_END) { + /* end of command */ + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] =3D= 0; + mcdserver_state.state =3D RS_DATAEND; + } else if (mcdserver_state.line_buf_index >=3D + sizeof(mcdserver_state.line_buf) - 1) { + /* the input string is too long for the linebuffer! */ + mcdserver_state.state =3D RS_IDLE; + } else { + /* copy the content to the line_buf */ + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] =3D= ch; + mcdserver_state.line_sum +=3D ch; + } + break; + case RS_DATAEND: + if (ch =3D=3D TCP_WAS_NOT_LAST) { + reply =3D TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state =3D mcd_handle_packet(mcdserver_state.li= ne_buf); + } else if (ch =3D=3D TCP_WAS_LAST) { + reply =3D TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state =3D mcd_handle_packet(mcdserver_state.li= ne_buf); + } else { + /* not acknowledged! */ + reply =3D TCP_NOT_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + /* waiting for package to get resent */ + mcdserver_state.state =3D RS_IDLE; + } + break; + default: + abort(); + } +} + /** * mcd_chr_receive() - Handles receiving a TCP packet. * @@ -98,6 +412,99 @@ static int mcd_chr_can_receive(void *opaque) */ static void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) { + int i; + + for (i =3D 0; i < size; i++) { + mcd_read_byte(buf[i]); + if (buf[i] =3D=3D 0) { + break; + } + } +} + +/** + * mcd_get_process() - Returns the process of the provided pid. + * + * @pid: The process ID. + */ +static MCDProcess *mcd_get_process(uint32_t pid) +{ + int i; + + if (!pid) { + /* 0 means any process, we take the first one */ + return &mcdserver_state.processes[0]; + } + + for (i =3D 0; i < mcdserver_state.process_num; i++) { + if (mcdserver_state.processes[i].pid =3D=3D pid) { + return &mcdserver_state.processes[i]; + } + } + + return NULL; +} + +/** + * mcd_get_cpu_pid() - Returns the process ID of the provided CPU. + * + * @cpu: The CPU state. + */ +static uint32_t mcd_get_cpu_pid(CPUState *cpu) +{ + if (cpu->cluster_index =3D=3D UNASSIGNED_CLUSTER_INDEX) { + /* Return the default process' PID */ + int index =3D mcdserver_state.process_num - 1; + return mcdserver_state.processes[index].pid; + } + return cpu->cluster_index + 1; +} + +/** + * mcd_get_cpu_process() - Returns the process of the provided CPU. + * + * @cpu: The CPU state. + */ +static MCDProcess *mcd_get_cpu_process(CPUState *cpu) +{ + return mcd_get_process(mcd_get_cpu_pid(cpu)); +} + +/** + * mcd_next_attached_cpu() - Returns the first CPU with an attached process + * starting after the + * provided cpu. + * + * @cpu: The CPU to start from. + */ +static CPUState *mcd_next_attached_cpu(CPUState *cpu) +{ + cpu =3D CPU_NEXT(cpu); + + while (cpu) { + if (mcd_get_cpu_process(cpu)->attached) { + break; + } + + cpu =3D CPU_NEXT(cpu); + } + + return cpu; +} + +/** + * mcd_first_attached_cpu() - Returns the first CPU with an attached proce= ss. + */ +static CPUState *mcd_first_attached_cpu(void) +{ + CPUState *cpu =3D first_cpu; + MCDProcess *process =3D mcd_get_cpu_process(cpu); + + if (!process->attached) { + return mcd_next_attached_cpu(cpu); + } + + return cpu; } =20 /** @@ -110,6 +517,21 @@ static void mcd_chr_receive(void *opaque, const uint8_= t *buf, int size) */ static void mcd_chr_event(void *opaque, QEMUChrEvent event) { + int i; + MCDState *s =3D (MCDState *) opaque; + + switch (event) { + case CHR_EVENT_OPENED: + /* Start with first process attached, others detached */ + for (i =3D 0; i < s->process_num; i++) { + s->processes[i].attached =3D !i; + } + + s->c_cpu =3D mcd_first_attached_cpu(); + break; + default: + break; + } } =20 /** --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983251095921.307315731751; Thu, 7 Dec 2023 13:07:31 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLYA-0002o8-7W; Thu, 07 Dec 2023 16:04:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY1-0002kC-61 for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:41 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXw-0005oL-5n for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:39 -0500 Received: (qmail 10418 invoked by uid 484); 7 Dec 2023 21:04:15 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:14 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.077406 secs); 07 Dec 2023 21:04:15 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 10/17] mcdstub: open and close server funcitons added Date: Thu, 7 Dec 2023 22:03:51 +0100 Message-Id: <20231207210358.7409-11-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983253078100002 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 300 ++++++++++++++++++++++++++++------------ 1 file changed, 215 insertions(+), 85 deletions(-) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index f97bccf409..d59c4ac078 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -65,6 +65,91 @@ static void mcd_sigterm_handler(int signal) } #endif =20 +/** + * mcd_get_process() - Returns the process of the provided pid. + * + * @pid: The process ID. + */ +static MCDProcess *mcd_get_process(uint32_t pid) +{ + int i; + + if (!pid) { + /* 0 means any process, we take the first one */ + return &mcdserver_state.processes[0]; + } + + for (i =3D 0; i < mcdserver_state.process_num; i++) { + if (mcdserver_state.processes[i].pid =3D=3D pid) { + return &mcdserver_state.processes[i]; + } + } + + return NULL; +} + +/** + * mcd_get_cpu_pid() - Returns the process ID of the provided CPU. + * + * @cpu: The CPU state. + */ +static uint32_t mcd_get_cpu_pid(CPUState *cpu) +{ + if (cpu->cluster_index =3D=3D UNASSIGNED_CLUSTER_INDEX) { + /* Return the default process' PID */ + int index =3D mcdserver_state.process_num - 1; + return mcdserver_state.processes[index].pid; + } + return cpu->cluster_index + 1; +} + +/** + * mcd_get_cpu_process() - Returns the process of the provided CPU. + * + * @cpu: The CPU state. + */ +static MCDProcess *mcd_get_cpu_process(CPUState *cpu) +{ + return mcd_get_process(mcd_get_cpu_pid(cpu)); +} + +/** + * mcd_next_attached_cpu() - Returns the first CPU with an attached process + * starting after the + * provided cpu. + * + * @cpu: The CPU to start from. + */ +static CPUState *mcd_next_attached_cpu(CPUState *cpu) +{ + cpu =3D CPU_NEXT(cpu); + + while (cpu) { + if (mcd_get_cpu_process(cpu)->attached) { + break; + } + + cpu =3D CPU_NEXT(cpu); + } + + return cpu; +} + +/** + * mcd_first_attached_cpu() - Returns the first CPU with an attached proce= ss. + */ +static CPUState *mcd_first_attached_cpu(void) +{ + CPUState *cpu =3D first_cpu; + MCDProcess *process =3D mcd_get_cpu_process(cpu); + + if (!process->attached) { + return mcd_next_attached_cpu(cpu); + } + + return cpu; +} + /** * mcd_vm_state_change() - Handles a state change of the QEMU VM. * @@ -284,6 +369,117 @@ static void run_cmd_parser(const char *data, const MC= DCmdParseEntry *cmd) } } =20 +/** + * init_resets() - Initializes the resets info. + * + * This function currently only adds all theoretical possible resets to the + * resets GArray. None of the resets work at the moment. The resets are: + * "full_system_reset", "gpr_reset" and "memory_reset". + * @resets: GArray with possible resets. + */ +static int init_resets(GArray *resets) +{ + mcd_reset_st system_reset =3D { .id =3D 0, .name =3D RESET_SYSTEM}; + mcd_reset_st gpr_reset =3D { .id =3D 1, .name =3D RESET_GPR}; + mcd_reset_st memory_reset =3D { .id =3D 2, .name =3D RESET_MEMORY}; + g_array_append_vals(resets, (gconstpointer)&system_reset, 1); + g_array_append_vals(resets, (gconstpointer)&gpr_reset, 1); + g_array_append_vals(resets, (gconstpointer)&memory_reset, 1); + return 0; +} + +/** + * init_trigger() - Initializes the trigger info. + * + * This function adds the types of trigger, their possible options and act= ions + * to the trigger struct. + * @trigger: Struct with all trigger info. + */ +static int init_trigger(mcd_trigger_into_st *trigger) +{ + snprintf(trigger->type, sizeof(trigger->type), + "%d,%d,%d,%d", MCD_BREAKPOINT_HW, MCD_BREAKPOINT_READ, + MCD_BREAKPOINT_WRITE, MCD_BREAKPOINT_RW); + snprintf(trigger->option, sizeof(trigger->option), + "%s", MCD_TRIG_OPT_VALUE); + snprintf(trigger->action, sizeof(trigger->action), + "%s", MCD_TRIG_ACT_BREAK); + /* there can be 16 breakpoints and 16 watchpoints each */ + trigger->nr_trigger =3D 16; + return 0; +} + +/** + * handle_open_server() - Handler for opening the MCD server. + * + * This is the first function that gets called from the MCD Shared Library. + * It initializes core indepent data with the :c:func:`init_resets` and + * \reg init_trigger functions. It also send the TCP_HANDSHAKE_SUCCESS + * packet back to the library to confirm the mcdstub is ready for further + * communication. + * @params: GArray with all TCP packet parameters. + */ +static void handle_open_server(GArray *params, void *user_ctx) +{ + /* initialize core-independent data */ + int return_value =3D 0; + mcdserver_state.resets =3D g_array_new(false, true, sizeof(mcd_reset_s= t)); + return_value =3D init_resets(mcdserver_state.resets); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + return_value =3D init_trigger(&mcdserver_state.trigger); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + + mcd_put_packet(TCP_HANDSHAKE_SUCCESS); +} + +/** + * mcd_vm_start() - Starts all CPUs with the vm_start function. + */ +static void mcd_vm_start(void) +{ + if (!runstate_needs_reset() && !runstate_is_running()) { + vm_start(); + } +} + +/** + * handle_close_server() - Handler for closing the MCD server. + * + * This function detaches the debugger (process) and frees up memory. + * Then it start the QEMU VM with :c:func:`mcd_vm_start`. + * @params: GArray with all TCP packet parameters. + */ +static void handle_close_server(GArray *params, void *user_ctx) +{ + uint32_t pid =3D 1; + MCDProcess *process =3D mcd_get_process(pid); + + /* + * 1. free memory + * TODO: do this only if there are no processes attached anymore! + */ + g_list_free(mcdserver_state.all_memspaces); + g_list_free(mcdserver_state.all_reggroups); + g_list_free(mcdserver_state.all_registers); + g_array_free(mcdserver_state.resets, TRUE); + + /* 2. detach */ + process->attached =3D false; + + /* 3. reset process */ + if (pid =3D=3D mcd_get_cpu_pid(mcdserver_state.c_cpu)) { + mcdserver_state.c_cpu =3D mcd_first_attached_cpu(); + } + if (!mcdserver_state.c_cpu) { + /* no more processes attached */ + mcd_vm_start(); + } +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -302,6 +498,25 @@ static int mcd_handle_packet(const char *line_buf) const MCDCmdParseEntry *cmd_parser =3D NULL; =20 switch (line_buf[0]) { + case TCP_CHAR_OPEN_SERVER: + { + static MCDCmdParseEntry open_server_cmd_desc =3D { + .handler =3D handle_open_server, + }; + open_server_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_OPEN_SERVER,= '\0' }; + cmd_parser =3D &open_server_cmd_desc; + } + break; + case TCP_CHAR_CLOSE_SERVER: + { + static MCDCmdParseEntry close_server_cmd_desc =3D { + .handler =3D handle_close_server, + }; + close_server_cmd_desc.cmd =3D + (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' }; + cmd_parser =3D &close_server_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -422,91 +637,6 @@ static void mcd_chr_receive(void *opaque, const uint8_= t *buf, int size) } } =20 -/** - * mcd_get_process() - Returns the process of the provided pid. - * - * @pid: The process ID. - */ -static MCDProcess *mcd_get_process(uint32_t pid) -{ - int i; - - if (!pid) { - /* 0 means any process, we take the first one */ - return &mcdserver_state.processes[0]; - } - - for (i =3D 0; i < mcdserver_state.process_num; i++) { - if (mcdserver_state.processes[i].pid =3D=3D pid) { - return &mcdserver_state.processes[i]; - } - } - - return NULL; -} - -/** - * mcd_get_cpu_pid() - Returns the process ID of the provided CPU. - * - * @cpu: The CPU state. - */ -static uint32_t mcd_get_cpu_pid(CPUState *cpu) -{ - if (cpu->cluster_index =3D=3D UNASSIGNED_CLUSTER_INDEX) { - /* Return the default process' PID */ - int index =3D mcdserver_state.process_num - 1; - return mcdserver_state.processes[index].pid; - } - return cpu->cluster_index + 1; -} - -/** - * mcd_get_cpu_process() - Returns the process of the provided CPU. - * - * @cpu: The CPU state. - */ -static MCDProcess *mcd_get_cpu_process(CPUState *cpu) -{ - return mcd_get_process(mcd_get_cpu_pid(cpu)); -} - -/** - * mcd_next_attached_cpu() - Returns the first CPU with an attached process - * starting after the - * provided cpu. - * - * @cpu: The CPU to start from. - */ -static CPUState *mcd_next_attached_cpu(CPUState *cpu) -{ - cpu =3D CPU_NEXT(cpu); - - while (cpu) { - if (mcd_get_cpu_process(cpu)->attached) { - break; - } - - cpu =3D CPU_NEXT(cpu); - } - - return cpu; -} - -/** - * mcd_first_attached_cpu() - Returns the first CPU with an attached proce= ss. - */ -static CPUState *mcd_first_attached_cpu(void) -{ - CPUState *cpu =3D first_cpu; - MCDProcess *process =3D mcd_get_cpu_process(cpu); - - if (!process->attached) { - return mcd_next_attached_cpu(cpu); - } - - return cpu; -} - /** * mcd_chr_event() - Handles a TCP client connect. * --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983110438266.1474357971309; Thu, 7 Dec 2023 13:05:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY9-0002o7-Vn; Thu, 07 Dec 2023 16:04:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXt-0002h5-GZ for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:34 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXo-0005oW-Um for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:33 -0500 Received: (qmail 10440 invoked by uid 484); 7 Dec 2023 21:04:17 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:16 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 3e-06 secs); 07 Dec 2023 21:04:17 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 11/17] mcdstub: system and core queries added Date: Thu, 7 Dec 2023 22:03:52 +0100 Message-Id: <20231207210358.7409-12-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983112560100006 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/arm_mcdstub.c | 243 ++++++++++++++++++++ debug/mcdstub/mcdstub.c | 373 ++++++++++++++++++++++++++++++- debug/mcdstub/meson.build | 2 +- include/mcdstub/arm_mcdstub.h | 85 +++++++ include/mcdstub/mcdstub.h | 5 - include/mcdstub/mcdstub_common.h | 19 ++ 6 files changed, 720 insertions(+), 7 deletions(-) diff --git a/debug/mcdstub/arm_mcdstub.c b/debug/mcdstub/arm_mcdstub.c index c24aaf1202..f14e677480 100644 --- a/debug/mcdstub/arm_mcdstub.c +++ b/debug/mcdstub/arm_mcdstub.c @@ -16,3 +16,246 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#include "qemu/osdep.h" +#include "mcdstub/arm_mcdstub.h" + +int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) +{ + int nr_address_spaces =3D cpu->num_ases; + uint32_t mem_space_id =3D 0; + + mem_space_id++; + mcd_mem_space_st non_secure =3D { + .name =3D "Non Secure", + .id =3D mem_space_id, + .type =3D 34, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + .is_secure =3D false, + .is_physical =3D false, + }; + g_array_append_vals(memspaces, (gconstpointer)&non_secure, 1); + mem_space_id++; + mcd_mem_space_st phys_non_secure =3D { + .name =3D "Physical (Non Secure)", + .id =3D mem_space_id, + .type =3D 18, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + .is_secure =3D false, + .is_physical =3D true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); + if (nr_address_spaces > 1) { + mem_space_id++; + mcd_mem_space_st secure =3D { + .name =3D "Secure", + .id =3D mem_space_id, + .type =3D 34, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + .is_secure =3D true, + .is_physical =3D false, + }; + g_array_append_vals(memspaces, (gconstpointer)&secure, 1); + mem_space_id++; + mcd_mem_space_st phys_secure =3D { + .name =3D "Physical (Secure)", + .id =3D mem_space_id, + .type =3D 18, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + .is_secure =3D true, + .is_physical =3D true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); + } + mem_space_id++; + mcd_mem_space_st gpr =3D { + .name =3D "GPR Registers", + .id =3D mem_space_id, + .type =3D 1, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + }; + g_array_append_vals(memspaces, (gconstpointer)&gpr, 1); + mem_space_id++; + mcd_mem_space_st cpr =3D { + .name =3D "CP15 Registers", + .id =3D mem_space_id, + .type =3D 1, + .bits_per_mau =3D 8, + .invariance =3D 1, + .endian =3D 1, + .min_addr =3D 0, + .max_addr =3D -1, + .supported_access_options =3D 0, + }; + g_array_append_vals(memspaces, (gconstpointer)&cpr, 1); + return 0; +} + +int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id) +{ + const char *xml_filename =3D NULL; + const char *current_xml_filename =3D NULL; + const char *xml_content =3D NULL; + int i =3D 0; + + /* 1. get correct file */ + xml_filename =3D cc->gdb_core_xml_file; + for (i =3D 0; ; i++) { + current_xml_filename =3D gdb_static_features[i].xmlname; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) =3D=3D 0 + && strlen(current_xml_filename) =3D=3D strlen(xml_filename))) + break; + } + /* without gpr registers we can do nothing */ + if (!current_xml_filename) { + return -1; + } + + /* 2. add group for gpr registers */ + mcd_reg_group_st gprregs =3D { + .name =3D "GPR Registers", + .id =3D *current_group_id + }; + g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); + *current_group_id =3D *current_group_id + 1; + + /* 3. parse xml */ + /* the offset for gpr is always zero */ + xml_content =3D gdb_static_features[i].xml; + parse_reg_xml(xml_content, strlen(xml_content), registers, + MCD_ARM_REG_TYPE_GPR, 0); + return 0; +} + +int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray *reggroups, + GArray *registers, int *current_group_id) { + const char *xml_filename =3D NULL; + const char *current_xml_filename =3D NULL; + const char *xml_content =3D NULL; + uint8_t reg_type; + CPUClass *cc =3D CPU_GET_CLASS(cpu); + + /* iterate over all gdb xml files*/ + GDBRegisterState *r; + for (guint i =3D 0; i < cpu->gdb_regs->len; i++) { + r =3D &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + + xml_filename =3D r->xml; + xml_content =3D NULL; + + /* 1. get xml content */ + if (cc->gdb_get_dynamic_xml) { + xml_content =3D cc->gdb_get_dynamic_xml(cpu, xml_filename); + } + if (xml_content) { + if (strcmp(xml_filename, "system-registers.xml") =3D=3D 0) { + /* these are the coprocessor register */ + mcd_reg_group_st corprocessorregs =3D { + .name =3D "CP15 Registers", + .id =3D *current_group_id + }; + g_array_append_vals(reggroups, + (gconstpointer)&corprocessorregs, 1); + *current_group_id =3D *current_group_id + 1; + reg_type =3D MCD_ARM_REG_TYPE_CPR; + } + } else { + /* its not a coprocessor xml -> it is a static xml file */ + int j =3D 0; + for (j =3D 0; ; j++) { + current_xml_filename =3D gdb_static_features[j].xmlname; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) =3D=3D 0 + && strlen(current_xml_filename) =3D=3D strlen(xml_file= name))) + break; + } + if (current_xml_filename) { + xml_content =3D gdb_static_features[j].xml; + /* select correct reg_type */ + if (strcmp(current_xml_filename, "arm-vfp.xml") =3D=3D 0) { + reg_type =3D MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, "arm-vfp3.xml") = =3D=3D 0) { + reg_type =3D MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-vfp-sysregs.xml") =3D=3D 0) { + reg_type =3D MCD_ARM_REG_TYPE_VFP_SYS; + } else if (strcmp(current_xml_filename, + "arm-neon.xml") =3D=3D 0) { + reg_type =3D MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-m-profile-mve.xml") =3D=3D 0) { + reg_type =3D MCD_ARM_REG_TYPE_MVE; + } + } else { + continue; + } + } + /* 2. parse xml */ + parse_reg_xml(xml_content, strlen(xml_content), registers, reg_typ= e, + r->base_reg); + } + return 0; +} + +int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *regist= ers, + CPUState *cpu) +{ + mcd_reg_st *current_register; + uint32_t i =3D 0; + + /* iterate over all registers */ + for (i =3D 0; i < registers->len; i++) { + current_register =3D &(g_array_index(registers, mcd_reg_st, i)); + /* add mcd_reg_group_id and mcd_mem_space_id */ + if (strcmp(current_register->group, "cp_regs") =3D=3D 0) { + /* coprocessor registers */ + current_register->mcd_reg_group_id =3D 2; + current_register->mcd_mem_space_id =3D 6; + /* + * get info for opcode + * for 32bit the opcode is only 16 bit long + * for 64bit it is 32 bit long + */ + current_register->opcode |=3D + arm_mcd_get_opcode(cpu, current_register->internal_id); + } else { + /* gpr register */ + current_register->mcd_reg_group_id =3D 1; + current_register->mcd_mem_space_id =3D 5; + } + } + return 0; +} + +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) +{ + /* TODO: not working with current build structure */ + return 0; +} diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index d59c4ac078..48da2e043c 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -34,6 +34,7 @@ =20 #include "mcdstub/mcd_shared_defines.h" #include "mcdstub/mcdstub.h" +#include "mcdstub/arm_mcdstub.h" =20 typedef struct { CharBackend chr; @@ -150,6 +151,25 @@ static CPUState *mcd_first_attached_cpu(void) return cpu; } =20 +/** + * mcd_get_cpu() - Returns the CPU the index i_cpu_index. + * + * @cpu_index: Index of the desired CPU. + */ +static CPUState *mcd_get_cpu(uint32_t cpu_index) +{ + CPUState *cpu =3D first_cpu; + + while (cpu) { + if (cpu->cpu_index =3D=3D cpu_index) { + return cpu; + } + cpu =3D mcd_next_attached_cpu(cpu); + } + + return cpu; +} + /** * mcd_vm_state_change() - Handles a state change of the QEMU VM. * @@ -221,6 +241,15 @@ static int mcd_put_packet(const char *buf) return mcd_put_packet_binary(buf, strlen(buf)); } =20 +/** + * mcd_put_strbuf() - Calls :c:func:`mcd_put_packet` with the str_buf of t= he + * mcdserver_state. + */ +static void mcd_put_strbuf(void) +{ + mcd_put_packet(mcdserver_state.str_buf->str); +} + /** * cmd_parse_params() - Extracts all parameters from a TCP packet. * @@ -480,6 +509,134 @@ static void handle_close_server(GArray *params, void = *user_ctx) } } =20 +/** + * handle_gen_query() - Handler for all TCP query packets. + * + * Calls :c:func:`process_string_cmd` with all query functions in the + * mcd_query_cmds_table. :c:func:`process_string_cmd` then selects the cor= rect + * one. This function just passes on the TCP packet data string from the + * parameters. + * @params: GArray with all TCP packet parameters. + */ +static void handle_gen_query(GArray *params, void *user_ctx) +{ + if (!params->len) { + return; + } + /* iterate over all possible query functions and execute the right one= */ + if (process_string_cmd(NULL, get_param(params, 0)->data, + mcdserver_state.mcd_query_cmds_table, + ARRAY_SIZE(mcdserver_state.mcd_query_cmds_table= ))) { + mcd_put_packet(""); + } +} + +/** + * handle_open_core() - Handler for opening a core. + * + * This function initializes all data for the core with the ID provided in + * the first parameter. In has a swtich case for different architectures. + * Currently only 32-Bit ARM is supported. The data includes memory spaces, + * register groups and registers themselves. They get stored into GLists w= here + * every entry in the list corresponds to one opened core. + * @params: GArray with all TCP packet parameters. + */ +static void handle_open_core(GArray *params, void *user_ctx) +{ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + CPUState *cpu =3D mcd_get_cpu(cpu_id); + mcdserver_state.c_cpu =3D cpu; + CPUClass *cc =3D CPU_GET_CLASS(cpu); + const gchar *arch =3D cc->gdb_arch_name(cpu); + int return_value =3D 0; + + /* prepare data strucutures */ + GArray *memspaces =3D g_array_new(false, true, sizeof(mcd_mem_space_st= )); + GArray *reggroups =3D g_array_new(false, true, sizeof(mcd_reg_group_st= )); + GArray *registers =3D g_array_new(false, true, sizeof(mcd_reg_st)); + + if (strcmp(arch, MCDSTUB_ARCH_ARM) =3D=3D 0) { + /* TODO: make group and memspace ids dynamic */ + int current_group_id =3D 1; + /* 1. store mem spaces */ + return_value =3D arm_mcd_store_mem_spaces(cpu, memspaces); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + /* 2. parse core xml */ + return_value =3D arm_mcd_parse_core_xml_file(cc, reggroups, + registers, ¤t_group_id); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + /* 3. parse other xmls */ + return_value =3D arm_mcd_parse_general_xml_files(cpu, reggroups, + registers, ¤t_group_id); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + /* 4. add additional data the the regs from the xmls */ + return_value =3D arm_mcd_get_additional_register_info(reggroups, + registers, cpu); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + /* 5. store all found data */ + if (g_list_nth(mcdserver_state.all_memspaces, cpu_id)) { + GList *memspaces_ptr =3D + g_list_nth(mcdserver_state.all_memspaces, cpu_id); + memspaces_ptr->data =3D memspaces; + } else { + mcdserver_state.all_memspaces =3D + g_list_insert(mcdserver_state.all_memspaces, memspaces, cp= u_id); + } + if (g_list_nth(mcdserver_state.all_reggroups, cpu_id)) { + GList *reggroups_ptr =3D + g_list_nth(mcdserver_state.all_reggroups, cpu_id); + reggroups_ptr->data =3D reggroups; + } else { + mcdserver_state.all_reggroups =3D + g_list_insert(mcdserver_state.all_reggroups, reggroups, cp= u_id); + } + if (g_list_nth(mcdserver_state.all_registers, cpu_id)) { + GList *registers_ptr =3D + g_list_nth(mcdserver_state.all_registers, cpu_id); + registers_ptr->data =3D registers; + } else { + mcdserver_state.all_registers =3D + g_list_insert(mcdserver_state.all_registers, registers, cp= u_id); + } + } else { + /* we don't support other architectures */ + g_assert_not_reached(); + } +} + +/** + * handle_close_core() - Handler for closing a core. + * + * Frees all memory allocated for core specific information. This includes + * memory spaces, register groups and registers. + * @params: GArray with all TCP packet parameters. + */ +static void handle_close_core(GArray *params, void *user_ctx) +{ + /* free memory for correct core */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + GArray *memspaces =3D g_list_nth_data(mcdserver_state.all_memspaces, c= pu_id); + mcdserver_state.all_memspaces =3D + g_list_remove(mcdserver_state.all_memspaces, memspaces); + g_array_free(memspaces, TRUE); + GArray *reggroups =3D g_list_nth_data(mcdserver_state.all_reggroups, c= pu_id); + mcdserver_state.all_reggroups =3D + g_list_remove(mcdserver_state.all_reggroups, reggroups); + g_array_free(reggroups, TRUE); + GArray *registers =3D g_list_nth_data(mcdserver_state.all_registers, c= pu_id); + mcdserver_state.all_registers =3D + g_list_remove(mcdserver_state.all_registers, registers); + g_array_free(registers, TRUE); +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -517,6 +674,39 @@ static int mcd_handle_packet(const char *line_buf) cmd_parser =3D &close_server_cmd_desc; } break; + case TCP_CHAR_QUERY: + { + static MCDCmdParseEntry query_cmd_desc =3D { + .handler =3D handle_gen_query, + }; + query_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_QUERY, '\0' }; + strcpy(query_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_STRING, '\0' }); + cmd_parser =3D &query_cmd_desc; + } + break; + case TCP_CHAR_OPEN_CORE: + { + static MCDCmdParseEntry open_core_cmd_desc =3D { + .handler =3D handle_open_core, + }; + open_core_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_OPEN_CORE, '\0= ' }; + strcpy(open_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser =3D &open_core_cmd_desc; + } + break; + case TCP_CHAR_CLOSE_CORE: + { + static MCDCmdParseEntry close_core_cmd_desc =3D { + .handler =3D handle_close_core, + }; + close_core_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_CLOSE_CORE, '= \0' }; + strcpy(close_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser =3D &close_core_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -664,6 +854,49 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent e= vent) } } =20 +/** + * handle_query_system() - Handler for the system query. + * + * Sends the system name, which is "qemu-system". + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_system(GArray *params, void *user_ctx) +{ + mcd_put_packet(MCD_SYSTEM_NAME); +} + +/** + * handle_query_cores() - Handler for the core query. + * + * This function sends the type of core and number of cores currently + * simulated by QEMU. It also sends a device name for the MCD data structu= re. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_cores(GArray *params, void *user_ctx) +{ + /* get first cpu */ + CPUState *cpu =3D mcd_first_attached_cpu(); + if (!cpu) { + return; + } + + ObjectClass *oc =3D object_get_class(OBJECT(cpu)); + const char *cpu_model =3D object_class_get_name(oc); + + CPUClass *cc =3D CPU_GET_CLASS(cpu); + const gchar *arch =3D cc->gdb_arch_name(cpu); + + uint32_t nr_cores =3D cpu->nr_cores; + char device_name[ARGUMENT_STRING_LENGTH] =3D {0}; + if (arch) { + snprintf(device_name, sizeof(device_name), "qemu-%s-device", arch); + } + g_string_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%s.%s=3D%u.", + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, + TCP_ARGUMENT_AMOUNT_CORE, nr_cores); + mcd_put_strbuf(); +} + /** * init_query_cmds_table() - Initializes all query functions. * @@ -672,7 +905,24 @@ static void mcd_chr_event(void *opaque, QEMUChrEvent e= vent) * @mcd_query_cmds_table: Lookup table with all query commands. */ static void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) -{} +{ + /* initalizes a list of all query commands */ + int cmd_number =3D 0; + + MCDCmdParseEntry query_system =3D { + .handler =3D handle_query_system, + .cmd =3D QUERY_ARG_SYSTEM, + }; + mcd_query_cmds_table[cmd_number] =3D query_system; + cmd_number++; + + MCDCmdParseEntry query_cores =3D { + .handler =3D handle_query_cores, + .cmd =3D QUERY_ARG_CORES, + }; + mcd_query_cmds_table[cmd_number] =3D query_cores; + cmd_number++; +} =20 /** * mcd_set_stop_cpu() - Sets c_cpu to the just stopped CPU. @@ -923,3 +1173,124 @@ int mcdserver_start(const char *device) =20 return 0; } + +void parse_reg_xml(const char *xml, int size, GArray* registers, + uint8_t reg_type, uint32_t reg_id_offset) +{ + /* iterates over the complete xml file */ + int i, j; + uint32_t current_reg_id =3D reg_id_offset; + uint32_t internal_id; + int still_to_skip =3D 0; + char argument[64] =3D {0}; + char value[64] =3D {0}; + bool is_reg =3D false; + bool is_argument =3D false; + bool is_value =3D false; + GArray *reg_data; + + char c; + char *c_ptr; + + xml_attrib attribute_j; + const char *argument_j; + const char *value_j; + + for (i =3D 0; i < size; i++) { + c =3D xml[i]; + c_ptr =3D &c; + + if (still_to_skip > 0) { + /* skip unwanted chars */ + still_to_skip--; + continue; + } + + if (strncmp(&xml[i], "", 2) =3D=3D 0) { + /* end of register info */ + still_to_skip =3D 1; + is_reg =3D false; + + /* create empty register */ + mcd_reg_st my_register =3D (const struct mcd_reg_st){ 0 }; + + /* add found attribtues */ + for (j =3D 0; j < reg_data->len; j++) { + attribute_j =3D g_array_index(reg_data, xml_attrib, j); + + argument_j =3D attribute_j.argument; + value_j =3D attribute_j.value; + + if (strcmp(argument_j, "name") =3D=3D 0) { + strcpy(my_register.name, value_j); + } else if (strcmp(argument_j, "regnum") =3D=3D 0) { + my_register.id =3D atoi(value_j); + } else if (strcmp(argument_j, "bitsize") =3D=3D 0) { + my_register.bitsize =3D atoi(value_j); + } else if (strcmp(argument_j, "type") =3D=3D 0) { + strcpy(my_register.type, value_j); + } else if (strcmp(argument_j, "group") =3D=3D 0) { + strcpy(my_register.group, value_j); + } + } + /* add reg_type, internal_id and id*/ + my_register.reg_type =3D reg_type; + my_register.internal_id =3D internal_id; + internal_id++; + if (!my_register.id) { + my_register.id =3D current_reg_id; + current_reg_id++; + } else { + /* set correct ID for the next register */ + current_reg_id =3D my_register.id + 1; + } + /* store register */ + g_array_append_vals(registers, (gconstpointer)&my_register= , 1); + /* free memory */ + g_array_free(reg_data, false); + } else { + /* store info for register */ + switch (c) { + case ' ': + break; + case '=3D': + is_argument =3D false; + break; + case '"': + if (is_value) { + /* end of value reached */ + is_value =3D false; + /* store arg-val combo */ + xml_attrib current_attribute; + strcpy(current_attribute.argument, argument); + strcpy(current_attribute.value, value); + g_array_append_vals(reg_data, + (gconstpointer)¤t_attribute, 1); + memset(argument, 0, sizeof(argument)); + memset(value, 0, sizeof(value)); + } else { + /*start of value */ + is_value =3D true; + } + break; + default: + if (is_argument) { + strncat(argument, c_ptr, 1); + } else if (is_value) { + strncat(value, c_ptr, 1); + } else { + is_argument =3D true; + strncat(argument, c_ptr, 1); + } + break; + } + } + } + } +} diff --git a/debug/mcdstub/meson.build b/debug/mcdstub/meson.build index 7e5ae878b0..3051a4e731 100644 --- a/debug/mcdstub/meson.build +++ b/debug/mcdstub/meson.build @@ -1,6 +1,6 @@ # only system emulation is supported over mcd mcd_system_ss =3D ss.source_set() -mcd_system_ss.add(files('mcdstub.c')) +mcd_system_ss.add(files('mcdstub.c', 'arm_mcdstub.c')) mcd_system_ss =3D mcd_system_ss.apply(config_host, strict: false) =20 libmcd_system =3D static_library('mcd_system', diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h index c24aaf1202..9961145f07 100644 --- a/include/mcdstub/arm_mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -16,3 +16,88 @@ * * SPDX-License-Identifier: LGPL-2.0+ */ + +#ifndef ARM_MCDSTUB_H +#define ARM_MCDSTUB_H + +#include "hw/core/cpu.h" +#include "mcdstub_common.h" +/* just used for the register xml files */ +#include "exec/gdbstub.h" + +/* ids for each different type of register */ +enum { + MCD_ARM_REG_TYPE_GPR, + MCD_ARM_REG_TYPE_VFP, + MCD_ARM_REG_TYPE_VFP_SYS, + MCD_ARM_REG_TYPE_MVE, + MCD_ARM_REG_TYPE_CPR, +}; + +/** + * arm_mcd_store_mem_spaces() - Stores all 32-Bit ARM specific memory spac= es. + * + * This function stores the memory spaces into the memspaces GArray. + * It only stores secure memory spaces if the CPU has more than one address + * space. It also stores a GPR and a CP15 register memory space. + * @memspaces: GArray of memory spaces. + * @cpu: CPU state. + */ +int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces); + +/** + * arm_mcd_parse_core_xml_file() - Parses the GPR registers. + * + * This function parses the core XML file, which includes the GPR register= s. + * The regsters get stored in a GArray and a GPR register group is stored = in a + * second GArray. + * @reggroups: GArray of register groups. + * @registers: GArray of registers. + * @cc: The CPU class. + * @current_group_id: The current group ID. It increases after + * each group. + */ +int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id); + +/** + * arm_mcd_parse_general_xml_files() - Parses all but the GPR registers. + * + * This function parses all XML files except for the core XML file. + * The regsters get stored in a GArray and if the system-registers.xml fil= e is + * parsed, it also adds a CP15 register group. + * @reggroups: GArray of register groups. + * @registers: GArray of registers. + * @cpu: The CPU state. + * @current_group_id: The current group ID. It increases after + * each added group. + */ +int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups, + GArray *registers, int *current_group_id); + +/** + * arm_mcd_get_additional_register_info() - Adds additional data to parsed + * registers. + * + * This function is called, after :c:func:`arm_mcd_parse_core_xml_file` and + * :c:func:`arm_mcd_parse_general_xml_files`. It adds additional data for = all + * already parsed registers. The registers get a correct ID, group, memory + * space and opcode, if they are CP15 registers. + * @reggroups: GArray of register groups. + * @registers: GArray of registers. + * @cpu: The CPU state. + */ +int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *regist= ers, + CPUState *cpu); + +/** + * arm_mcd_get_opcode() - Returns the opcode for a coprocessor register. + * + * This function uses the opc1, opc2, crm and crn members of the register = to + * create the opcode. The formular for creating the opcode is determined b= y ARM. + * @n: The register ID of the CP register. + * @cs: CPU state. + */ +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); + +#endif /* ARM_MCDSTUB_H */ diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 9ec9b427bd..52aa9ee18b 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -151,11 +151,6 @@ typedef struct MCDState { /* lives in mcdstub.c */ extern MCDState mcdserver_state; =20 -typedef struct xml_attrib { - char argument[ARGUMENT_STRING_LENGTH]; - char value[ARGUMENT_STRING_LENGTH]; -} xml_attrib; - typedef struct mcd_reset_st { const char *name; uint8_t id; diff --git a/include/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_com= mon.h index b64748c080..d6ff55005e 100644 --- a/include/mcdstub/mcdstub_common.h +++ b/include/mcdstub/mcdstub_common.h @@ -61,4 +61,23 @@ typedef struct mcd_reg_group_st { uint32_t id; } mcd_reg_group_st; =20 +typedef struct xml_attrib { + char argument[ARGUMENT_STRING_LENGTH]; + char value[ARGUMENT_STRING_LENGTH]; +} xml_attrib; + +/** + * parse_reg_xml() - Parses a GDB register XML file + * + * This fuction extracts all registers from the provided xml file and stor= es + * them into the registers GArray. It extracts the register name, bitsize,= type + * and group if they are set. + * @xml: String with contents of the XML file. + * @registers: GArray with stored registers. + * @reg_type: Register type (depending on file). + * @size: Number of characters in the xml string. + */ +void parse_reg_xml(const char *xml, int size, GArray* registers, + uint8_t reg_type, uint32_t reg_id_offset); + #endif /* MCDSTUB_COMMON_H */ --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983200733567.3822606256335; Thu, 7 Dec 2023 13:06:40 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLXv-0002hk-Us; Thu, 07 Dec 2023 16:04:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXt-0002hC-My for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:34 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXq-0005od-Jk for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:33 -0500 Received: (qmail 10466 invoked by uid 484); 7 Dec 2023 21:04:18 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:17 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.15476 secs); 07 Dec 2023 21:04:18 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 12/17] mcdstub: all core specific queries added Date: Thu, 7 Dec 2023 22:03:53 +0100 Message-Id: <20231207210358.7409-13-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983202089100003 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 365 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index 48da2e043c..a5256eeb56 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -897,6 +897,301 @@ static void handle_query_cores(GArray *params, void *= user_ctx) mcd_put_strbuf(); } =20 +/** + * handle_query_reset_f() - Handler for the first reset query. + * + * This function sends the first reset name and ID. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_reset_f(GArray *params, void *user_ctx) +{ + /* 1. check length */ + int nb_resets =3D mcdserver_state.resets->len; + if (nb_resets =3D=3D 1) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); + } + /* 2. send data */ + mcd_reset_st reset =3D g_array_index(mcdserver_state.resets, mcd_reset= _st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%u.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); +} + +/** + * handle_query_reset_c() - Handler for all consecutive reset queries. + * + * This functions sends all consecutive reset names and IDs. It uses the + * query_index parameter to determine which reset is queried next. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_reset_c(GArray *params, void *user_ctx) +{ + /* reset options are the same for every cpu! */ + uint32_t query_index =3D get_param(params, 0)->query_handle; + + /* 1. check weather this was the last mem space */ + int nb_groups =3D mcdserver_state.resets->len; + if (query_index + 1 =3D=3D nb_groups) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); + } + + /* 2. send data */ + mcd_reset_st reset =3D g_array_index(mcdserver_state.resets, + mcd_reset_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%u.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); +} + +/** + * handle_query_trigger() - Handler for trigger query. + * + * Sends data on the different types of trigger and their options and acti= ons. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_trigger(GArray *params, void *user_ctx) +{ + mcd_trigger_into_st trigger =3D mcdserver_state.trigger; + g_string_printf(mcdserver_state.str_buf, "%s=3D%u.%s=3D%s.%s=3D%s.%s= =3D%s.", + TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, + TCP_ARGUMENT_TYPE, trigger.type, + TCP_ARGUMENT_OPTION, trigger.option, + TCP_ARGUMENT_ACTION, trigger.action); + mcd_put_strbuf(); +} + +/** + * handle_query_mem_spaces_f() Handler for the first memory space query. + * + * This function sends the first memory space name, ID, type and accessing + * options. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_mem_spaces_f(GArray *params, void *user_ctx) +{ + /* 1. get correct memspaces and set the query_cpu */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id =3D cpu_id; + GArray *memspaces =3D g_list_nth_data(mcdserver_state.all_memspaces, c= pu_id); + + /* 2. check length */ + int nb_groups =3D memspaces->len; + if (nb_groups =3D=3D 1) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); + } + + /* 3. send data */ + mcd_mem_space_st space =3D g_array_index(memspaces, mcd_mem_space_st, = 0); + g_string_append_printf(mcdserver_state.str_buf, + "%s=3D%s.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%ld.%s=3D%ld= .%s=3D%u.", + TCP_ARGUMENT_NAME, space.name, + TCP_ARGUMENT_ID, space.id, + TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, + TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_opti= ons); + mcd_put_strbuf(); +} + +/** + * handle_query_mem_spaces_c() - Handler for all consecutive memory space + * queries. + * + * This function sends all consecutive memory space names, IDs, types and + * accessing options. + * It uses the query_index parameter to determine + * which memory space is queried next. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_mem_spaces_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all mem spaces except for the first + * 1. get parameter and memspace + */ + uint32_t query_index =3D get_param(params, 0)->query_handle; + uint32_t cpu_id =3D mcdserver_state.query_cpu_id; + GArray *memspaces =3D g_list_nth_data(mcdserver_state.all_memspaces, c= pu_id); + + /* 2. check weather this was the last mem space */ + int nb_groups =3D memspaces->len; + if (query_index + 1 =3D=3D nb_groups) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); + } + + /* 3. send the correct memspace */ + mcd_mem_space_st space =3D g_array_index(memspaces, + mcd_mem_space_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, + "%s=3D%s.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%ld.%s=3D%ld= .%s=3D%u.", + TCP_ARGUMENT_NAME, space.name, + TCP_ARGUMENT_ID, space.id, + TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, + TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_opti= ons); + mcd_put_strbuf(); +} + +/** + * handle_query_reg_groups_f() - Handler for the first register group quer= y. + * + * This function sends the first register group name and ID. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_reg_groups_f(GArray *params, void *user_ctx) +{ + /* 1. get correct reggroups and set the query_cpu */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id =3D cpu_id; + GArray *reggroups =3D g_list_nth_data(mcdserver_state.all_reggroups, c= pu_id); + + /* 2. check length */ + int nb_groups =3D reggroups->len; + if (nb_groups =3D=3D 1) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); + } + /* 3. send data */ + mcd_reg_group_st group =3D g_array_index(reggroups, mcd_reg_group_st, = 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=3D%u.%s=3D%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + mcd_put_strbuf(); +} + +/** + * handle_query_reg_groups_c() - Handler for all consecutive register group + * queries. + * + * This function sends all consecutive register group names and IDs. It us= es + * the query_index parameter to determine which register group is queried = next. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_reg_groups_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all reg groups except for the first + * 1. get parameter and memspace + */ + uint32_t query_index =3D get_param(params, 0)->query_handle; + uint32_t cpu_id =3D mcdserver_state.query_cpu_id; + GArray *reggroups =3D g_list_nth_data(mcdserver_state.all_reggroups, c= pu_id); + + /* 2. check weather this was the last reg group */ + int nb_groups =3D reggroups->len; + if (query_index + 1 =3D=3D nb_groups) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); + } + + /* 3. send the correct reggroup */ + mcd_reg_group_st group =3D g_array_index(reggroups, mcd_reg_group_st, + query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=3D%u.%s=3D%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + mcd_put_strbuf(); +} + +/** + * handle_query_regs_f() - Handler for the first register query. + * + * This function sends the first register with all its information. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_regs_f(GArray *params, void *user_ctx) +{ + /* 1. get correct registers and set the query_cpu */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id =3D cpu_id; + GArray *registers =3D g_list_nth_data(mcdserver_state.all_registers, c= pu_id); + + /* 2. check length */ + int nb_regs =3D registers->len; + if (nb_regs =3D=3D 1) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); + } + /* 3. send data */ + mcd_reg_st my_register =3D g_array_index(registers, mcd_reg_st, 0); + g_string_append_printf(mcdserver_state.str_buf, + "%s=3D%u.%s=3D%s.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.", + TCP_ARGUMENT_ID, my_register.id, + TCP_ARGUMENT_NAME, my_register.name, + TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, + TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id, + TCP_ARGUMENT_OPCODE, my_register.opcode); + mcd_put_strbuf(); +} + +/** + * handle_query_regs_c() - Handler for all consecutive register queries. + * + * This function sends all consecutive registers with all their informatio= n. + * It uses the query_index parameter to determine + * which register is queried next. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_regs_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all regs except for the first + * 1. get parameter and registers + */ + uint32_t query_index =3D get_param(params, 0)->query_handle; + uint32_t cpu_id =3D mcdserver_state.query_cpu_id; + GArray *registers =3D g_list_nth_data(mcdserver_state.all_registers, c= pu_id); + + /* 2. check weather this was the last register */ + int nb_regs =3D registers->len; + if (query_index + 1 =3D=3D nb_regs) { + /* indicates this is the last packet */ + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); + } else { + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); + } + + /* 3. send the correct register */ + mcd_reg_st my_register =3D g_array_index(registers, mcd_reg_st, query_= index); + g_string_append_printf(mcdserver_state.str_buf, + "%s=3D%u.%s=3D%s.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%u.", + TCP_ARGUMENT_ID, my_register.id, + TCP_ARGUMENT_NAME, my_register.name, + TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, + TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id, + TCP_ARGUMENT_OPCODE, my_register.opcode); + mcd_put_strbuf(); +} + /** * init_query_cmds_table() - Initializes all query functions. * @@ -922,6 +1217,76 @@ static void init_query_cmds_table(MCDCmdParseEntry *m= cd_query_cmds_table) }; mcd_query_cmds_table[cmd_number] =3D query_cores; cmd_number++; + + MCDCmdParseEntry query_reset_f =3D { + .handler =3D handle_query_reset_f, + .cmd =3D QUERY_ARG_RESET QUERY_FIRST, + }; + mcd_query_cmds_table[cmd_number] =3D query_reset_f; + cmd_number++; + + MCDCmdParseEntry query_reset_c =3D { + .handler =3D handle_query_reset_c, + .cmd =3D QUERY_ARG_RESET QUERY_CONSEQUTIVE, + }; + strcpy(query_reset_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] =3D query_reset_c; + cmd_number++; + + MCDCmdParseEntry query_trigger =3D { + .handler =3D handle_query_trigger, + .cmd =3D QUERY_ARG_TRIGGER, + }; + mcd_query_cmds_table[cmd_number] =3D query_trigger; + cmd_number++; + + MCDCmdParseEntry query_mem_spaces_f =3D { + .handler =3D handle_query_mem_spaces_f, + .cmd =3D QUERY_ARG_MEMORY QUERY_FIRST, + }; + strcpy(query_mem_spaces_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0'= }); + mcd_query_cmds_table[cmd_number] =3D query_mem_spaces_f; + cmd_number++; + + MCDCmdParseEntry query_mem_spaces_c =3D { + .handler =3D handle_query_mem_spaces_c, + .cmd =3D QUERY_ARG_MEMORY QUERY_CONSEQUTIVE, + }; + strcpy(query_mem_spaces_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\= 0' }); + mcd_query_cmds_table[cmd_number] =3D query_mem_spaces_c; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_f =3D { + .handler =3D handle_query_reg_groups_f, + .cmd =3D QUERY_ARG_REGGROUP QUERY_FIRST, + }; + strcpy(query_reg_groups_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0'= }); + mcd_query_cmds_table[cmd_number] =3D query_reg_groups_f; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_c =3D { + .handler =3D handle_query_reg_groups_c, + .cmd =3D QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE, + }; + strcpy(query_reg_groups_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\= 0' }); + mcd_query_cmds_table[cmd_number] =3D query_reg_groups_c; + cmd_number++; + + MCDCmdParseEntry query_regs_f =3D { + .handler =3D handle_query_regs_f, + .cmd =3D QUERY_ARG_REG QUERY_FIRST, + }; + strcpy(query_regs_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] =3D query_regs_f; + cmd_number++; + + MCDCmdParseEntry query_regs_c =3D { + .handler =3D handle_query_regs_c, + .cmd =3D QUERY_ARG_REG QUERY_CONSEQUTIVE, + }; + strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] =3D query_regs_c; + cmd_number++; } =20 /** --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983188539231.1876174585998; Thu, 7 Dec 2023 13:06:28 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY6-0002mv-8r; Thu, 07 Dec 2023 16:04:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY1-0002k9-2X for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:41 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXw-0005oz-3B for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:38 -0500 Received: (qmail 10536 invoked by uid 484); 7 Dec 2023 21:04:21 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:18 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.139927 secs); 07 Dec 2023 21:04:21 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 13/17] mcdstub: go, step and break added Date: Thu, 7 Dec 2023 22:03:54 +0100 Message-Id: <20231207210358.7409-14-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983189821100011 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 220 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index a5256eeb56..83582f7fa5 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -28,6 +28,7 @@ #include "chardev/char-fe.h" #include "hw/cpu/cluster.h" #include "hw/boards.h" +#include "exec/tb-flush.h" #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "sysemu/runstate.h" @@ -182,6 +183,96 @@ static CPUState *mcd_get_cpu(uint32_t cpu_index) */ static void mcd_vm_state_change(void *opaque, bool running, RunState state) { + CPUState *cpu =3D mcdserver_state.c_cpu; + + if (mcdserver_state.state =3D=3D RS_INACTIVE) { + return; + } + + if (cpu =3D=3D NULL) { + if (running) { + /* + * this is the case if qemu starts the vm + * before a mcd client is connected + */ + const char *mcd_state; + mcd_state =3D CORE_STATE_RUNNING; + const char *info_str; + info_str =3D STATE_STR_INIT_RUNNING; + mcdserver_state.cpu_state.state =3D mcd_state; + mcdserver_state.cpu_state.info_str =3D info_str; + } + return; + } + + const char *mcd_state; + const char *stop_str; + const char *info_str; + uint32_t bp_type =3D 0; + uint64_t bp_address =3D 0; + switch (state) { + case RUN_STATE_RUNNING: + mcd_state =3D CORE_STATE_RUNNING; + info_str =3D STATE_STR_RUNNING(cpu->cpu_index); + stop_str =3D ""; + break; + case RUN_STATE_DEBUG: + mcd_state =3D CORE_STATE_DEBUG; + info_str =3D STATE_STR_DEBUG(cpu->cpu_index); + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { + case BP_MEM_READ: + bp_type =3D MCD_BREAKPOINT_READ; + stop_str =3D STATE_STR_BREAK_READ(cpu->watchpoint_hit->hit= addr); + break; + case BP_MEM_WRITE: + bp_type =3D MCD_BREAKPOINT_WRITE; + stop_str =3D STATE_STR_BREAK_WRITE(cpu->watchpoint_hit->hi= taddr); + break; + case BP_MEM_ACCESS: + bp_type =3D MCD_BREAKPOINT_RW; + stop_str =3D STATE_STR_BREAK_RW(cpu->watchpoint_hit->hitad= dr); + break; + default: + stop_str =3D STATE_STR_BREAK_UNKNOWN; + break; + } + bp_address =3D cpu->watchpoint_hit->hitaddr; + cpu->watchpoint_hit =3D NULL; + } else if (cpu->singlestep_enabled) { + /* we land here when a single step is performed */ + stop_str =3D STATE_STEP_PERFORMED; + } else { + bp_type =3D MCD_BREAKPOINT_HW; + stop_str =3D STATE_STR_BREAK_HW; + tb_flush(cpu); + } + /* deactivate single step */ + cpu_single_step(cpu, 0); + break; + case RUN_STATE_PAUSED: + info_str =3D STATE_STR_HALTED(cpu->cpu_index); + mcd_state =3D CORE_STATE_HALTED; + stop_str =3D ""; + break; + case RUN_STATE_WATCHDOG: + info_str =3D STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state =3D CORE_STATE_UNKNOWN; + stop_str =3D ""; + break; + default: + info_str =3D STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state =3D CORE_STATE_UNKNOWN; + stop_str =3D ""; + break; + } + + /* set state for c_cpu */ + mcdserver_state.cpu_state.state =3D mcd_state; + mcdserver_state.cpu_state.bp_type =3D bp_type; + mcdserver_state.cpu_state.bp_address =3D bp_address; + mcdserver_state.cpu_state.stop_str =3D stop_str; + mcdserver_state.cpu_state.info_str =3D info_str; } =20 /** @@ -637,6 +728,104 @@ static void handle_close_core(GArray *params, void *u= ser_ctx) g_array_free(registers, TRUE); } =20 +/** + * mcd_cpu_start() - Starts the selected CPU with the cpu_resume function. + * + * @cpu: The CPU about to be started. + */ +static void mcd_cpu_start(CPUState *cpu) +{ + if (!runstate_needs_reset() && !runstate_is_running() && + !vm_prepare_start(false)) { + mcdserver_state.c_cpu =3D cpu; + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + cpu_resume(cpu); + } +} + +/** + * mcd_cpu_sstep() - Performes a step on the selected CPU. + * + * This function first sets the correct single step flags for the CPU with + * cpu_single_step and then starts the CPU with cpu_resume. + * @cpu: The CPU about to be stepped. + */ +static int mcd_cpu_sstep(CPUState *cpu) +{ + mcdserver_state.c_cpu =3D cpu; + cpu_single_step(cpu, mcdserver_state.sstep_flags); + if (!runstate_needs_reset() && !runstate_is_running() && + !vm_prepare_start(true)) { + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + cpu_resume(cpu); + } + return 0; +} + +/** + * mcd_vm_stop() - Brings all CPUs in debug state with the vm_stop functio= n. + */ +static void mcd_vm_stop(void) +{ + if (runstate_is_running()) { + vm_stop(RUN_STATE_DEBUG); + } +} + +/** + * handle_vm_start() - Handler for the VM start TCP packet. + * + * Evaluates whether all cores or just a perticular core should get starte= d and + * calls :c:func:`mcd_vm_start` or :c:func:`mcd_cpu_start` respectively. + * @params: GArray with all TCP packet parameters. + */ +static void handle_vm_start(GArray *params, void *user_ctx) +{ + uint32_t global =3D get_param(params, 0)->data_uint32_t; + if (global =3D=3D 1) { + mcd_vm_start(); + } else{ + uint32_t cpu_id =3D get_param(params, 1)->cpu_id; + CPUState *cpu =3D mcd_get_cpu(cpu_id); + mcd_cpu_start(cpu); + } +} + +/** + * handle_vm_step() - Handler for the VM step TCP packet. + * + * Calls :c:func:`mcd_cpu_sstep` for the CPU which sould be stepped. + * Stepping all CPUs is currently not supported. + * @params: GArray with all TCP packet parameters. + */ +static void handle_vm_step(GArray *params, void *user_ctx) +{ + uint32_t global =3D get_param(params, 0)->data_uint32_t; + if (global =3D=3D 1) { + /* TODO: add multicore support */ + } else{ + uint32_t cpu_id =3D get_param(params, 1)->cpu_id; + CPUState *cpu =3D mcd_get_cpu(cpu_id); + int return_value =3D mcd_cpu_sstep(cpu); + if (return_value !=3D 0) { + g_assert_not_reached(); + } + } +} + +/** + * handle_vm_stop() - Handler for the VM stop TCP packet. + * + * Always calls :c:func:`mcd_vm_stop` and stops all cores. Stopping indivi= dual + * cores is currently not supported. + * @params: GArray with all TCP packet parameters. + */ +static void handle_vm_stop(GArray *params, void *user_ctx) +{ + /* TODO: add core dependant break option */ + mcd_vm_stop(); +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -707,6 +896,37 @@ static int mcd_handle_packet(const char *line_buf) cmd_parser =3D &close_core_cmd_desc; } break; + case TCP_CHAR_GO: + { + static MCDCmdParseEntry go_cmd_desc =3D { + .handler =3D handle_vm_start, + }; + go_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_GO, '\0' }; + strcpy(go_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser =3D &go_cmd_desc; + } + break; + case TCP_CHAR_STEP: + { + static MCDCmdParseEntry step_cmd_desc =3D { + .handler =3D handle_vm_step, + }; + step_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_STEP, '\0' }; + strcpy(step_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser =3D &step_cmd_desc; + } + break; + case TCP_CHAR_BREAK: + { + static MCDCmdParseEntry break_cmd_desc =3D { + .handler =3D handle_vm_stop, + }; + break_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_BREAK, '\0' }; + cmd_parser =3D &break_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983111939792.6618885689384; Thu, 7 Dec 2023 13:05:11 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLYB-0002oe-9Q; Thu, 07 Dec 2023 16:04:51 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY1-0002kB-5Y for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:41 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXw-0005pG-PJ for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:40 -0500 Received: (qmail 10670 invoked by uid 484); 7 Dec 2023 21:04:24 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:21 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 3e-06 secs); 07 Dec 2023 21:04:24 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 14/17] mcdstub: state query added Date: Thu, 7 Dec 2023 22:03:55 +0100 Message-Id: <20231207210358.7409-15-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983114179100015 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index 83582f7fa5..794e7d1312 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -1412,6 +1412,43 @@ static void handle_query_regs_c(GArray *params, void= *user_ctx) mcd_put_strbuf(); } =20 +/** + * handle_query_state() - Handler for the state query. + * + * This function collects all data stored in the + * cpu_state member of the mcdserver_state and formats and sends it to the + * library. + * @params: GArray with all TCP packet parameters. + */ +static void handle_query_state(GArray *params, void *user_ctx) +{ + /* + * TODO: multicore support + * get state info + */ + mcd_cpu_state_st state_info =3D mcdserver_state.cpu_state; + /* TODO: add event information */ + uint32_t event =3D 0; + /* send data */ + g_string_printf(mcdserver_state.str_buf, + "%s=3D%s.%s=3D%u.%s=3D%u.%s=3D%u.%s=3D%lu.%s=3D%s.%s=3D%s.", + TCP_ARGUMENT_STATE, state_info.state, + TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0, + TCP_ARGUMENT_TYPE, state_info.bp_type, + TCP_ARGUMENT_ADDRESS, state_info.bp_address, + TCP_ARGUMENT_STOP_STRING, state_info.stop_str, + TCP_ARGUMENT_INFO_STRING, state_info.info_str); + mcd_put_strbuf(); + + /* reset debug info after first query */ + if (strcmp(state_info.state, CORE_STATE_DEBUG) =3D=3D 0) { + mcdserver_state.cpu_state.stop_str =3D ""; + mcdserver_state.cpu_state.info_str =3D ""; + mcdserver_state.cpu_state.bp_type =3D 0; + mcdserver_state.cpu_state.bp_address =3D 0; + } +} + /** * init_query_cmds_table() - Initializes all query functions. * @@ -1507,6 +1544,13 @@ static void init_query_cmds_table(MCDCmdParseEntry *= mcd_query_cmds_table) strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] =3D query_regs_c; cmd_number++; + + MCDCmdParseEntry query_state =3D { + .handler =3D handle_query_state, + .cmd =3D QUERY_ARG_STATE, + }; + strcpy(query_state.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] =3D query_state; } =20 /** --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983185236237.76764353393116; Thu, 7 Dec 2023 13:06:25 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLYC-0002pk-Ax; Thu, 07 Dec 2023 16:04:52 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY2-0002lK-I1 for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:42 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLXz-0005ra-Rd for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:42 -0500 Received: (qmail 10774 invoked by uid 484); 7 Dec 2023 21:04:27 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:24 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.088762 secs); 07 Dec 2023 21:04:27 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 15/17] mcdstub: skeleton for reset handling added Date: Thu, 7 Dec 2023 22:03:56 +0100 Message-Id: <20231207210358.7409-16-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983185749100001 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index 794e7d1312..cc1587396d 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -826,6 +826,37 @@ static void handle_vm_stop(GArray *params, void *user_= ctx) mcd_vm_stop(); } =20 +/** + * mcd_exit() - Terminates QEMU. + * + * If the mcdserver_state has not been initialized the function exits befo= re + * terminating QEMU. Terminting is done with the qemu_chr_fe_deinit functi= on. + * @code: An exitcode, which can be used in the future. + */ +static void mcd_exit(int code) +{ + /* terminate qemu */ + if (!mcdserver_state.init) { + return; + } + + qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); +} + +/** + * handle_reset() - Handler for performing resets. + * + * This function is currently not in use. + * @params: GArray with all TCP packet parameters. + */ +static void handle_reset(GArray *params, void *user_ctx) +{ + /* + * int reset_id =3D get_param(params, 0)->data_int; + * TODO: implement resets + */ +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -927,6 +958,21 @@ static int mcd_handle_packet(const char *line_buf) cmd_parser =3D &break_cmd_desc; } break; + case TCP_CHAR_KILLQEMU: + /* kill qemu completely */ + error_report("QEMU: Terminated via MCDstub"); + mcd_exit(0); + exit(0); + case TCP_CHAR_RESET: + { + static MCDCmdParseEntry reset_cmd_desc =3D { + .handler =3D handle_reset, + }; + reset_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_RESET, '\0' }; + strcpy(reset_cmd_desc.schema, (char[2]) { ARG_SCHEMA_INT, '\0'= }); + cmd_parser =3D &reset_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983330847808.882301068541; Thu, 7 Dec 2023 13:08:50 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLY7-0002n0-95; Thu, 07 Dec 2023 16:04:47 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY4-0002mm-Oj for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:44 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY2-0005vI-59 for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:44 -0500 Received: (qmail 10835 invoked by uid 484); 7 Dec 2023 21:04:29 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:27 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.085884 secs); 07 Dec 2023 21:04:29 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 16/17] mcdstub: register access added Date: Thu, 7 Dec 2023 22:03:57 +0100 Message-Id: <20231207210358.7409-17-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983332608100003 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/arm_mcdstub.c | 28 +++ debug/mcdstub/mcdstub.c | 369 ++++++++++++++++++++++++++++++++++ include/mcdstub/arm_mcdstub.h | 15 ++ 3 files changed, 412 insertions(+) diff --git a/debug/mcdstub/arm_mcdstub.c b/debug/mcdstub/arm_mcdstub.c index f14e677480..6d46e1bd7a 100644 --- a/debug/mcdstub/arm_mcdstub.c +++ b/debug/mcdstub/arm_mcdstub.c @@ -18,6 +18,7 @@ */ =20 #include "qemu/osdep.h" +#include "exec/memory.h" #include "mcdstub/arm_mcdstub.h" =20 int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) @@ -259,3 +260,30 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) /* TODO: not working with current build structure */ return 0; } + +AddressSpace *arm_mcd_get_address_space(uint32_t cpu_id, + mcd_mem_space_st mem_space) +{ + /* get correct address space name */ + char as_name[ARGUMENT_STRING_LENGTH] =3D {0}; + if (mem_space.is_secure) { + sprintf(as_name, "cpu-secure-memory-%u", cpu_id); + } else { + sprintf(as_name, "cpu-memory-%u", cpu_id); + } + /* return correct address space */ + AddressSpace *as =3D mcd_find_address_space(as_name); + return as; +} + +MemTxAttrs arm_mcd_get_memtxattrs(mcd_mem_space_st mem_space) +{ + MemTxAttrs attributes =3D {0}; + if (mem_space.is_secure) { + attributes.secure =3D 1; + attributes.space =3D 2; + } else { + attributes.space =3D 1; + } + return attributes; +} diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index cc1587396d..e5fd575834 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -857,6 +857,326 @@ static void handle_reset(GArray *params, void *user_c= tx) */ } =20 +/** + * mcd_memtohex() - Converts a byte array into a hex string. + * + * @mem: Pointer to byte array. + * @buf: Pointer to hex string. + * @len: Number of bytes. + */ +static void mcd_memtohex(GString *buf, const uint8_t *mem, int len) +{ + int i, c; + for (i =3D 0; i < len; i++) { + c =3D mem[i]; + g_string_append_c(buf, nibble_to_hexchar(c >> 4)); + g_string_append_c(buf, nibble_to_hexchar(c & 0xf)); + } + g_string_append_c(buf, '\0'); +} + +/** + * mcd_hextomem() - Converts a hex string into a byte array. + * + * @mem: Pointer to byte array. + * @buf: Pointer to hex string. + * @len: Number of bytes. + */ +static void mcd_hextomem(GByteArray *mem, const char *buf, int len) +{ + int i; + + for (i =3D 0; i < len; i++) { + guint8 byte =3D hexchar_to_nibble(buf[0]) << 4 | + hexchar_to_nibble(buf[1]); + g_byte_array_append(mem, &byte, 1); + buf +=3D 2; + } +} + +/** + * mcd_read_register() - Reads a registers data and stores it into the buf. + * + * This function collects the register type and internal ID + * (depending on the XML file). Then it calls the architecture specific + * read function. For ARM this is :c:func:`arm_mcd_read_register`. + * @cpu: CPU to which the register belongs. + * @buf: Byte array with register data. + * @reg: General ID of the register. + */ +static int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) +{ + CPUClass *cc =3D CPU_GET_CLASS(cpu); + CPUArchState *env =3D cpu_env(cpu); + GDBRegisterState *r; + + if (reg < cc->gdb_num_core_regs) { + return cc->gdb_read_register(cpu, buf, reg); + } + + for (guint i =3D 0; i < cpu->gdb_regs->len; i++) { + r =3D &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + if (r->base_reg <=3D reg && reg < r->base_reg + r->num_regs) { + return r->get_reg(env, buf, reg - r->base_reg); + } + } + return 0; +} + +/** + * mcd_write_register() - Writes data from the buf to a register. + * + * This function collects the register type and internal ID + * (depending on the XML file). Then it calls the architecture specific + * write function. For ARM this is :c:func:`arm_mcd_write_register`. + * @cpu: CPU to which the register belongs. + * @mem_buf: Byte array with register data. + * @reg: General ID of the register. + */ +static int mcd_write_register(CPUState *cpu, uint8_t *mem_buf, int reg) +{ + CPUClass *cc =3D CPU_GET_CLASS(cpu); + CPUArchState *env =3D cpu_env(cpu); + GDBRegisterState *r; + + if (reg < cc->gdb_num_core_regs) { + return cc->gdb_write_register(cpu, mem_buf, reg); + } + + for (guint i =3D 0; i < cpu->gdb_regs->len; i++) { + r =3D &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + if (r->base_reg <=3D reg && reg < r->base_reg + r->num_regs) { + return r->set_reg(env, mem_buf, reg - r->base_reg); + } + } + return 0; +} + +/** + * handle_read_register() - Handler for reading a register. + * + * This function calls :c:func:`mcd_read_register` to read a register. The + * register data gets stored in the mem_buf byte array. The data then gets + * converted into a hex string with :c:func:`mcd_memtohex` and then send. + * @params: GArray with all TCP packet parameters. + */ +static void handle_read_register(GArray *params, void *user_ctx) +{ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint64_t reg_num =3D get_param(params, 1)->data_uint64_t; + int reg_size; + + CPUState *cpu =3D mcd_get_cpu(cpu_id); + reg_size =3D mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num); + mcd_memtohex(mcdserver_state.str_buf, + mcdserver_state.mem_buf->data, reg_size); + mcd_put_strbuf(); +} + +/** + * handle_write_register() - Handler for writing a register. + * + * This function converts the incoming hex string data into a byte array w= ith + * :c:func:`mcd_hextomem`. Then it calls :c:func:`mcd_write_register` to w= rite + * to the register. + * @params: GArray with all TCP packet parameters. + */ +static void handle_write_register(GArray *params, void *user_ctx) +{ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint64_t reg_num =3D get_param(params, 1)->data_uint64_t; + uint32_t reg_size =3D get_param(params, 2)->data_uint32_t; + + CPUState *cpu =3D mcd_get_cpu(cpu_id); + mcd_hextomem(mcdserver_state.mem_buf, + mcdserver_state.str_buf->str, reg_size); + if (mcd_write_register(cpu, mcdserver_state.mem_buf->data, reg_num) = =3D=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} + +/** + * mcd_read_write_physical_memory() - Reades or writes from/to a logical + * memory address. + * @address_space: Desired QEMU address space (e.g. secure/non-secure) + * @attributes: Access attributes + * @addr: (physical) memory address + * @buf: Buffer for memory data + * @len: Length of the memory access + * @is_write: True for writing and false for reading + */ +static int mcd_read_write_physical_memory(AddressSpace *address_space, + MemTxAttrs attributes, hwaddr addr, uint8_t *buf, int len, bool is_wri= te) +{ + if (is_write) { + return address_space_write_rom(address_space, addr, attributes, bu= f, + len); + } else { + return address_space_read_full(address_space, addr, attributes, bu= f, + len); + } +} + +/** + * mcd_read_write_memory() - Reades or writes from/to a logical memory add= ress. + * @cpu: CPUState + * @address_space: Desired QEMU address space (e.g. secure/non-secure) + * @attributes: Access attributes + * @addr: (logical) memory address + * @buf: Buffer for memory data + * @len: Length of the memory access + * @is_write: True for writing and false for reading + */ +static int mcd_read_write_memory(CPUState *cpu, AddressSpace *address_spac= e, + MemTxAttrs attributes, vaddr addr, uint8_t *buf, uint64_t len, + bool is_write) +{ + /* get physical address */ + if (cpu_memory_get_physical_address(cpu, &addr, &len) !=3D 0) { + return -1; + } + /* read memory */ + return mcd_read_write_physical_memory(address_space, attributes, addr,= buf, + len, is_write); +} + +/** + * mcd_get_address_space() - Returnes the correct QEMU address space name + * @cpu: CPUState + * @cpu_id: Correct CPU ID + * @mem_space: Desired mcd specific memory space. + */ +static AddressSpace *mcd_get_address_space(CPUState *cpu, uint32_t cpu_id, + mcd_mem_space_st mem_space) +{ + CPUClass *cc =3D CPU_GET_CLASS(cpu); + const gchar *arch =3D cc->gdb_arch_name(cpu); + if (strcmp(arch, MCDSTUB_ARCH_ARM) =3D=3D 0) { + return arm_mcd_get_address_space(cpu_id, mem_space); + } else { + g_assert_not_reached(); + } +} + +/** + * mcd_get_memtxattrs() - Returnes the correct QEMU address space access + * attributes + * @cpu: CPUState + * @mem_space: Desired mcd specific memory space. + */ +static MemTxAttrs mcd_get_memtxattrs(CPUState *cpu, mcd_mem_space_st mem_s= pace) +{ + CPUClass *cc =3D CPU_GET_CLASS(cpu); + const gchar *arch =3D cc->gdb_arch_name(cpu); + if (strcmp(arch, MCDSTUB_ARCH_ARM) =3D=3D 0) { + return arm_mcd_get_memtxattrs(mem_space); + } else { + g_assert_not_reached(); + } +} + +/** + * handle_read_memory() - Handler for reading memory. + * + * First, this function checks whether reading a secure memory space is + * requested and changes the access mode with :c:func:`arm_mcd_set_scr`. + * Then it calls :c:func:`mcd_read_memory` to read memory. The collected + * data gets stored in the mem_buf byte array. The data then gets converted + * into a hex string with :c:func:`mcd_memtohex` and then send. + * @params: GArray with all TCP packet parameters. + */ +static void handle_read_memory(GArray *params, void *user_ctx) +{ + /* read input parameters */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint32_t mem_space_id =3D get_param(params, 1)->data_uint32_t; + uint64_t mem_address =3D get_param(params, 2)->data_uint64_t; + uint32_t len =3D get_param(params, 3)->data_uint32_t; + /* check which memory space was requested */ + CPUState *cpu =3D mcd_get_cpu(cpu_id); + GArray *memspaces =3D + g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space =3D g_array_index(memspaces, mcd_mem_space_st, + mem_space_id - 1); + /* get data in the QEMU address space and access attributes */ + AddressSpace *address_space =3D mcd_get_address_space(cpu, cpu_id, spa= ce); + MemTxAttrs attributes =3D mcd_get_memtxattrs(cpu, space); + /* read memory data */ + g_byte_array_set_size(mcdserver_state.mem_buf, len); + if (space.is_physical) { + /* physical memory */ + if (mcd_read_write_physical_memory(address_space, attributes, + mem_address, mcdserver_state.mem_buf->data, + mcdserver_state.mem_buf->len, false) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } else { + /* user space memory */ + if (mcd_read_write_memory(cpu, address_space, attributes, mem_addr= ess, + mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len, + false) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } + /* send data */ + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, + mcdserver_state.mem_buf->len); + mcd_put_strbuf(); +} + +/** + * handle_write_memory() - Handler for writing memory. + * + * First, this function checks whether reading a secure memory space is + * requested and changes the access mode with :c:func:`arm_mcd_set_scr`. + * Then it converts the incoming hex string data into a byte array with + * :c:func:`mcd_hextomem`. Then it calls :c:func:`mcd_write_memory` to wri= te to + * the register. + * @params: GArray with all TCP packet parameters. + */ +static void handle_write_memory(GArray *params, void *user_ctx) +{ + /* read input parameters */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint32_t mem_space_id =3D get_param(params, 1)->data_uint32_t; + uint64_t mem_address =3D get_param(params, 2)->data_uint64_t; + uint32_t len =3D get_param(params, 3)->data_uint32_t; + /* check which memory space was requested */ + CPUState *cpu =3D mcd_get_cpu(cpu_id); + GArray *memspaces =3D + g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space =3D g_array_index(memspaces, mcd_mem_space_st, + mem_space_id - 1); + /* get data in the QEMU address space and access attributes */ + AddressSpace *address_space =3D mcd_get_address_space(cpu, cpu_id, spa= ce); + MemTxAttrs attributes =3D mcd_get_memtxattrs(cpu, space); + /* write memory data */ + mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, le= n); + if (space.is_physical) { + /* physical memory */ + if (mcd_read_write_physical_memory(address_space, attributes, + mem_address, mcdserver_state.mem_buf->data, + mcdserver_state.mem_buf->len, true) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } else { + /* user space memory */ + if (mcd_read_write_memory(cpu, address_space, attributes, mem_addr= ess, + mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len, + true) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } + /* send acknowledge */ + mcd_put_packet(TCP_EXECUTION_SUCCESS); +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -973,6 +1293,55 @@ static int mcd_handle_packet(const char *line_buf) cmd_parser =3D &reset_cmd_desc; } break; + case TCP_CHAR_READ_REGISTER: + { + static MCDCmdParseEntry read_reg_cmd_desc =3D { + .handler =3D handle_read_register, + }; + read_reg_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_READ_REGISTER, = '\0' }; + strcpy(read_reg_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, '\0' = }); + cmd_parser =3D &read_reg_cmd_desc; + } + break; + case TCP_CHAR_WRITE_REGISTER: + { + static MCDCmdParseEntry write_reg_cmd_desc =3D { + .handler =3D handle_write_register, + }; + write_reg_cmd_desc.cmd =3D + (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' }; + strcpy(write_reg_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, + ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); + cmd_parser =3D &write_reg_cmd_desc; + } + break; + case TCP_CHAR_READ_MEMORY: + { + static MCDCmdParseEntry read_mem_cmd_desc =3D { + .handler =3D handle_read_memory, + }; + read_mem_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_READ_MEMORY, '\= 0' }; + strcpy(read_mem_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, '\0' }); + cmd_parser =3D &read_mem_cmd_desc; + } + break; + case TCP_CHAR_WRITE_MEMORY: + { + static MCDCmdParseEntry write_mem_cmd_desc =3D { + .handler =3D handle_write_memory, + }; + write_mem_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_WRITE_MEMORY, = '\0' }; + strcpy(write_mem_cmd_desc.schema, + (char[6]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, + ARG_SCHEMA_HEXDATA, '\0' }); + cmd_parser =3D &write_mem_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h index 9961145f07..69f6e2d487 100644 --- a/include/mcdstub/arm_mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -100,4 +100,19 @@ int arm_mcd_get_additional_register_info(GArray *reggr= oups, GArray *registers, */ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); =20 +/** + * arm_mcd_get_address_space() - Returnes the correct QEMU address space n= ame + * @cpu_id: Correct CPU ID + * @mem_space: Desired mcd specific memory space. + */ +AddressSpace *arm_mcd_get_address_space(uint32_t cpu_id, + mcd_mem_space_st mem_space); + +/** + * arm_mcd_get_memtxattrs() - Returnes the correct QEMU address space acce= ss + * attributes + * @mem_space: Desired mcd specific memory space. + */ +MemTxAttrs arm_mcd_get_memtxattrs(mcd_mem_space_st mem_space); + #endif /* ARM_MCDSTUB_H */ --=20 2.34.1 From nobody Wed Nov 27 00:44:13 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1701983148519189.2850752017141; Thu, 7 Dec 2023 13:05:48 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rBLYE-0002qG-0j; Thu, 07 Dec 2023 16:04:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLYB-0002pR-OS for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:51 -0500 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rBLY9-00060e-OD for qemu-devel@nongnu.org; Thu, 07 Dec 2023 16:04:51 -0500 Received: (qmail 10894 invoked by uid 484); 7 Dec 2023 21:04:35 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 7 Dec 2023 21:04:29 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 6e-06 secs); 07 Dec 2023 21:04:35 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , "Christian Boenig" , =?UTF-8?q?Alex=20Benn=C3=A9e?= Subject: [PATCH v4 17/17] mcdstub: break/watchpoints added Date: Thu, 7 Dec 2023 22:03:58 +0100 Message-Id: <20231207210358.7409-18-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207210358.7409-1-nicolas.eder@lauterbach.com> References: <20231207210358.7409-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1701983148810100005 Content-Type: text/plain; charset="utf-8" --- debug/mcdstub/mcdstub.c | 154 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/debug/mcdstub/mcdstub.c b/debug/mcdstub/mcdstub.c index e5fd575834..dadd79034b 100644 --- a/debug/mcdstub/mcdstub.c +++ b/debug/mcdstub/mcdstub.c @@ -1177,6 +1177,134 @@ static void handle_write_memory(GArray *params, voi= d *user_ctx) mcd_put_packet(TCP_EXECUTION_SUCCESS); } =20 +/** + * mcd_breakpoint_insert() - Inserts a break- or watchpoint. + * + * This function evaluates the received breakpoint type and translates it + * to a known GDB breakpoint type. + * Then it calls cpu_breakpoint_insert or cpu_watchpoint_insert depending = on + * the type. + * @cpu: CPU to which the breakpoint should be added. + * @addr: Address of the breakpoint. + * @type: Breakpoint type. + */ +static int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr) +{ + /* translate the type to known gdb types and function call*/ + int bp_type =3D 0; + CPUClass *cc =3D CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + /* bp_type |=3D BP_STOP_BEFORE_ACCESS; */ + } + int return_value =3D 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value =3D cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |=3D BP_GDB | BP_MEM_READ; + return_value =3D cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL= ); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |=3D BP_GDB | BP_MEM_WRITE; + return_value =3D cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL= ); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |=3D BP_GDB | BP_MEM_ACCESS; + return_value =3D cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL= ); + return return_value; + default: + return -ENOSYS; + } +} + +/** + * mcd_breakpoint_remove() - Removes a break- or watchpoint. + * + * This function evaluates the received breakpoint type and translates it + * to a known GDB breakpoint type. + * Then it calls cpu_breakpoint_remove or cpu_watchpoint_remove depending = on + * the type. + * @cpu: CPU from which the breakpoint should be removed. + * @addr: Address of the breakpoint. + * @type: Breakpoint type. + */ +static int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr) +{ + /* translate the type to known gdb types and function call*/ + int bp_type =3D 0; + CPUClass *cc =3D CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + /* bp_type |=3D BP_STOP_BEFORE_ACCESS; */ + } + int return_value =3D 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value =3D cpu_breakpoint_remove(cpu, addr, BP_GDB); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |=3D BP_GDB | BP_MEM_READ; + return_value =3D cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |=3D BP_GDB | BP_MEM_WRITE; + return_value =3D cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |=3D BP_GDB | BP_MEM_ACCESS; + return_value =3D cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + default: + return -ENOSYS; + } +} + +/** + * handle_breakpoint_insert() - Handler for inserting a break- or watchpoi= nt. + * + * This function extracts the CPU, breakpoint type and address from the + * parameters and calls :c:func:`mcd_breakpoint_insert` to insert the + * breakpoint. + * @params: GArray with all TCP packet parameters. + */ +static void handle_breakpoint_insert(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint32_t type =3D get_param(params, 1)->data_uint32_t; + uint64_t address =3D get_param(params, 2)->data_uint64_t; + /* 2. insert breakpoint and send reply */ + CPUState *cpu =3D mcd_get_cpu(cpu_id); + if (mcd_breakpoint_insert(cpu, type, address) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} + +/** + * handle_breakpoint_remove() - Handler for inserting a break- or watchpoi= nt. + * + * This function extracts the CPU, breakpoint type and address from the + * parameters and calls :c:func:`mcd_breakpoint_remove` to insert the + * breakpoint. + * @params: GArray with all TCP packet parameters. + */ +static void handle_breakpoint_remove(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint32_t type =3D get_param(params, 1)->data_uint32_t; + uint64_t address =3D get_param(params, 2)->data_uint64_t; + /* 2. remove breakpoint and send reply */ + CPUState *cpu =3D mcd_get_cpu(cpu_id); + if (mcd_breakpoint_remove(cpu, type, address) !=3D 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} + /** * mcd_handle_packet() - Evaluates the type of received packet and chooses= the * correct handler. @@ -1342,6 +1470,32 @@ static int mcd_handle_packet(const char *line_buf) cmd_parser =3D &write_mem_cmd_desc; } break; + case TCP_CHAR_BREAKPOINT_INSERT: + { + static MCDCmdParseEntry handle_breakpoint_insert_cmd_desc =3D { + .handler =3D handle_breakpoint_insert, + }; + handle_breakpoint_insert_cmd_desc.cmd =3D + (char[2]) { TCP_CHAR_BREAKPOINT_INSERT, '\0' }; + strcpy(handle_breakpoint_insert_cmd_desc.schema, + (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, '\0' }); + cmd_parser =3D &handle_breakpoint_insert_cmd_desc; + } + break; + case TCP_CHAR_BREAKPOINT_REMOVE: + { + static MCDCmdParseEntry handle_breakpoint_remove_cmd_desc =3D { + .handler =3D handle_breakpoint_remove, + }; + handle_breakpoint_remove_cmd_desc.cmd =3D + (char[2]) { TCP_CHAR_BREAKPOINT_REMOVE, '\0' }; + strcpy(handle_breakpoint_remove_cmd_desc.schema, + (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, '\0' }); + cmd_parser =3D &handle_breakpoint_remove_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); --=20 2.34.1