From patchwork Tue Nov 7 13:03:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448598 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3A3FAC4167D for ; Tue, 7 Nov 2023 13:04:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LkN-00088Z-3Y; Tue, 07 Nov 2023 08:03:59 -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 1r0LkJ-00088H-Sh for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:55 -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 1r0LkG-0005j6-Ku for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:55 -0500 Received: (qmail 30802 invoked by uid 484); 7 Nov 2023 13:03:32 -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.09664 secs); 07 Nov 2023 13:03:32 -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 Nov 2023 13:03:31 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 01/20] mcdstub: initial file structure for new mcdstub created. -mcd QEMU startup option added. Functions for initializing the mcdstub added. Basic helper functions for processes/cpus in the mcdstub added Date: Tue, 7 Nov 2023 14:03:04 +0100 Message-Id: <20231107130323.4126-2-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/arm_mcdstub.h | 10 + include/mcdstub/mcdstub.h | 239 +++++++++++++++++++ include/mcdstub/mcdstub_common.h | 7 + mcdstub/mcdstub.c | 383 +++++++++++++++++++++++++++++++ qemu-options.hx | 18 ++ system/vl.c | 13 ++ 6 files changed, 670 insertions(+) create mode 100644 include/mcdstub/arm_mcdstub.h create mode 100644 include/mcdstub/mcdstub.h create mode 100644 include/mcdstub/mcdstub_common.h create mode 100644 mcdstub/mcdstub.c diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h new file mode 100644 index 0000000000..a57aa8e9f2 --- /dev/null +++ b/include/mcdstub/arm_mcdstub.h @@ -0,0 +1,10 @@ +#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" + + +#endif /* ARM_MCDSTUB_H */ diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h new file mode 100644 index 0000000000..36058157ae --- /dev/null +++ b/include/mcdstub/mcdstub.h @@ -0,0 +1,239 @@ +#ifndef MCDSTUB_INTERNALS_H +#define MCDSTUB_INTERNALS_H + +#include "exec/cpu-common.h" +#include "chardev/char.h" +#include "hw/core/cpu.h" +#include "mcdstub_common.h" + +#define MAX_PACKET_LENGTH 1024 +/* 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" + +typedef struct MCDProcess { + uint32_t pid; + bool attached; + + char target_xml[1024]; +} MCDProcess; + +#define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) + +enum RSState { + RS_INACTIVE, + RS_IDLE, + RS_GETLINE, + RS_DATAEND, +}; + +typedef struct MCDState { + bool init; /* have we been initialised? */ + CPUState *c_cpu; /* current CPU for everything */ + enum RSState state; /* parsing state */ + char line_buf[MAX_PACKET_LENGTH]; + int line_buf_index; + int line_sum; /* running checksum */ + int line_csum; /* checksum at the end of the packet */ + 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 main mcdstub.c */ +extern MCDState mcdserver_state; + +#ifndef _WIN32 +void mcd_sigterm_handler(int signal); +#endif + +/** + * mcdserver_start() - initializes the mcdstub and opens a TCP port + * @device: TCP port (e.g. tcp::1235) + */ +int mcdserver_start(const char *device); + +/** + * 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`. + */ +void mcd_init_mcdserver_state(void); + +/** + * 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. + */ +void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table); +/** + * 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. + */ +void create_processes(MCDState *s); + +/** + * mcd_create_default_process() - Creates a default process for debugging. + * + * This function creates a new, not yet attached, process with an ID one above + * the previous maximum ID. + * @s: A MCDState object. + */ +void mcd_create_default_process(MCDState *s); + +/** + * 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. + */ +int find_cpu_clusters(Object *child, void *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. + */ +int pid_order(const void *a, const void *b); + +/** + * mcd_chr_can_receive() - Returns the maximum packet length of a TCP packet. + */ +int mcd_chr_can_receive(void *opaque); + +/** + * 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. + */ +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 opened + * TCP port. It attaches the first process. From here on TCP packets can be + * exchanged. + * @event: Type of event. + */ +void mcd_chr_event(void *opaque, QEMUChrEvent event); + +/** + * mcd_supports_guest_debug() - Returns true if debugging the selected + * accelerator is supported. + */ +bool mcd_supports_guest_debug(void); + +/** + * mcd_vm_state_change() - Handles a state change of the QEMU VM. + * + * This function is called when the QEMU VM goes through a state transition. + * 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. + */ +void mcd_vm_state_change(void *opaque, bool running, RunState state); +/** + * mcd_get_cpu_process() - Returns the process of the provided CPU. + * + * @cpu: The CPU state. + */ +MCDProcess *mcd_get_cpu_process(CPUState *cpu); + +/** + * mcd_set_stop_cpu() - Sets c_cpu to the just stopped CPU. + * + * @cpu: The CPU state. + */ +void mcd_set_stop_cpu(CPUState *cpu); + +/** + * mcd_get_cpu_pid() - Returns the process ID of the provided CPU. + * + * @cpu: The CPU state. + */ +uint32_t mcd_get_cpu_pid(CPUState *cpu); + +/** + * mcd_get_process() - Returns the process of the provided pid. + * + * @pid: The process ID. + */ +MCDProcess *mcd_get_process(uint32_t pid); + +/** + * mcd_first_attached_cpu() - Returns the first CPU with an attached process. + */ +CPUState *mcd_first_attached_cpu(void); + +/** + * mcd_next_attached_cpu() - Returns the first CPU with an attached process + * starting after the + * provided cpu. + * + * @cpu: The CPU to start from. + */ +CPUState *mcd_next_attached_cpu(CPUState *cpu); + +/** + * mcd_get_cpu() - Returns the CPU the index i_cpu_index. + * + * @cpu_index: Index of the desired CPU. + */ +CPUState *mcd_get_cpu(uint32_t cpu_index); +/** + * get_first_cpu_in_process() - Returns the first CPU in the provided process. + * + * @process: The process to look in. + */ +CPUState *get_first_cpu_in_process(MCDProcess *process); + +/** + * find_cpu() - Returns the CPU with an index equal to the thread_id. + * + * @thread_id: ID of the desired CPU. + */ +CPUState *find_cpu(uint32_t thread_id); diff --git a/include/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_common.h new file mode 100644 index 0000000000..3bae2c3b6f --- /dev/null +++ b/include/mcdstub/mcdstub_common.h @@ -0,0 +1,7 @@ +#ifndef MCDSTUB_COMMON_H +#define MCDSTUB_COMMON_H + +#define ARGUMENT_STRING_LENGTH 64 +#define TCP_CONFIG_STRING_LENGTH 128 + +#endif /* MCDSTUB_COMMON_H */ diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c new file mode 100644 index 0000000000..4cdf2e42ed --- /dev/null +++ b/mcdstub/mcdstub.c @@ -0,0 +1,383 @@ +/* + * This is the main mcdstub. + */ + +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "qemu/debug.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "qapi/error.h" +#include "exec/tb-flush.h" +#include "sysemu/cpus.h" +#include "sysemu/replay.h" +#include "chardev/char.h" +#include "chardev/char-fe.h" +#include "monitor/monitor.h" +#include "cutils.h" + +/* mcdstub header files */ +#include "mcdstub/mcd_shared_defines.h" +#include "mcdstub/mcdstub.h" + +/* architecture specific stubs */ +#include "mcdstub/arm_mcdstub.h" + +typedef struct { + CharBackend chr; +} MCDSystemState; + +MCDSystemState mcdserver_system_state; + +MCDState mcdserver_state; + +void mcd_init_mcdserver_state(void) +{ + g_assert(!mcdserver_state.init); + memset(&mcdserver_state, 0, sizeof(MCDState)); + mcdserver_state.init = true; + mcdserver_state.str_buf = g_string_new(NULL); + mcdserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH); + mcdserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 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 = + accel_supported_gdbstub_sstep_flags(); + mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; + mcdserver_state.sstep_flags &= 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 = { + .state = CORE_STATE_HALTED, + .info_str = STATE_STR_INIT_HALTED, + }; + mcdserver_state.cpu_state = cpu_state; + + /* create new debug object */ + mcd_init_debug_class(); + } + +void mcd_set_stop_cpu(CPUState *cpu) +{ + mcdserver_state.c_cpu = cpu; +} + +void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) +{ + /* initalizes a list of all query commands */ + int cmd_number = 0; +} +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); +} + +void mcd_create_default_process(MCDState *s) +{ + MCDProcess *process; + int max_pid = 0; + + if (mcdserver_state.process_num) { + max_pid = s->processes[s->process_num - 1].pid; + } + + s->processes = g_renew(MCDProcess, s->processes, ++s->process_num); + process = &s->processes[s->process_num - 1]; + + /* We need an available PID slot for this process */ + assert(max_pid < UINT32_MAX); + + process->pid = max_pid + 1; + process->attached = false; + process->target_xml[0] = '\0'; +} + +int find_cpu_clusters(Object *child, void *opaque) +{ + if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) { + MCDState *s = (MCDState *) opaque; + CPUClusterState *cluster = CPU_CLUSTER(child); + MCDProcess *process; + + s->processes = g_renew(MCDProcess, s->processes, ++s->process_num); + + process = &s->processes[s->process_num - 1]; + assert(cluster->cluster_id != UINT32_MAX); + process->pid = cluster->cluster_id + 1; + process->attached = false; + process->target_xml[0] = '\0'; + + return 0; + } + + return object_child_foreach(child, find_cpu_clusters, opaque); +} + +int pid_order(const void *a, const void *b) +{ + MCDProcess *pa = (MCDProcess *) a; + MCDProcess *pb = (MCDProcess *) b; + + if (pa->pid < pb->pid) { + return -1; + } else if (pa->pid > pb->pid) { + return 1; + } else { + return 0; + } +} + +int mcdserver_start(const char *device) +{ + char mcd_device_config[TCP_CONFIG_STRING_LENGTH]; + char mcd_tcp_port[TCP_CONFIG_STRING_LENGTH]; + Chardev *chr = 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 == default -> set tcp_port = tcp:: */ + if (strcmp(device, "default") == 0) { + snprintf(mcd_tcp_port, sizeof(mcd_tcp_port), "tcp::%s", + MCD_DEFAULT_TCP_PORT); + device = mcd_tcp_port; + } + + if (strcmp(device, "none") != 0) { + if (strstart(device, "tcp:", NULL)) { + /* enforce required TCP attributes */ + snprintf(mcd_device_config, sizeof(mcd_device_config), + "%s,wait=off,nodelay=on,server=on", device); + device = mcd_device_config; + } +#ifndef _WIN32 + else if (strcmp(device, "stdio") == 0) { + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = mcd_sigterm_handler; + sigaction(SIGINT, &act, NULL); + strcpy(mcd_device_config, device); + } +#endif + chr = 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 = chr ? RS_IDLE : RS_INACTIVE; + + return 0; +} + +int mcd_chr_can_receive(void *opaque) +{ + return MAX_PACKET_LENGTH; +} + +void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) +{ + int i; + + for (i = 0; i < size; i++) { + mcd_read_byte(buf[i]); + if (buf[i] == 0) { + break; + } + } +} + + +void mcd_chr_event(void *opaque, QEMUChrEvent event) +{ + int i; + MCDState *s = (MCDState *) opaque; + + switch (event) { + case CHR_EVENT_OPENED: + /* Start with first process attached, others detached */ + for (i = 0; i < s->process_num; i++) { + s->processes[i].attached = !i; + } + + s->c_cpu = mcd_first_attached_cpu(); + break; + default: + break; + } +} + +bool mcd_supports_guest_debug(void) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->supports_guest_debug) { + return ops->supports_guest_debug(); + } + return false; +} + +#ifndef _WIN32 +void mcd_sigterm_handler(int signal) +{ + if (runstate_is_running()) { + vm_stop(RUN_STATE_PAUSED); + } +} +#endif + +uint32_t mcd_get_cpu_pid(CPUState *cpu) +{ + if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { + /* Return the default process' PID */ + int index = mcdserver_state.process_num - 1; + return mcdserver_state.processes[index].pid; + } + return cpu->cluster_index + 1; +} + +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 = 0; i < mcdserver_state.process_num; i++) { + if (mcdserver_state.processes[i].pid == pid) { + return &mcdserver_state.processes[i]; + } + } + + return NULL; +} + +CPUState *mcd_get_cpu(uint32_t cpu_index) +{ + CPUState *cpu = first_cpu; + + while (cpu) { + if (cpu->cpu_index == cpu_index) { + return cpu; + } + cpu = mcd_next_attached_cpu(cpu); + } + + return cpu; +} + +CPUState *mcd_first_attached_cpu(void) +{ + CPUState *cpu = first_cpu; + MCDProcess *process = mcd_get_cpu_process(cpu); + + if (!process->attached) { + return mcd_next_attached_cpu(cpu); + } + + return cpu; +} + +CPUState *mcd_next_attached_cpu(CPUState *cpu) +{ + cpu = CPU_NEXT(cpu); + + while (cpu) { + if (mcd_get_cpu_process(cpu)->attached) { + break; + } + + cpu = CPU_NEXT(cpu); + } + + return cpu; +} + +int mcd_get_cpu_index(CPUState *cpu) +{ + return cpu->cpu_index + 1; +} + +CPUState *get_first_cpu_in_process(MCDProcess *process) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (mcd_get_cpu_pid(cpu) == process->pid) { + return cpu; + } + } + + return NULL; +} + +CPUState *find_cpu(uint32_t thread_id) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (mcd_get_cpu_index(cpu) == thread_id) { + return cpu; + } + } + + return NULL; +} + diff --git a/qemu-options.hx b/qemu-options.hx index e26230bac5..accf92642c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4430,6 +4430,24 @@ SRST (see the :ref:`GDB usage` chapter in the System Emulation Users Guide). ERST +DEF("mcd", HAS_ARG, QEMU_OPTION_mcd, \ + "-mcd dev accept mcd connection on 'dev'. (QEMU defaults to starting\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 92d29bf521..b657c77ea4 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" @@ -1266,6 +1267,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; @@ -2673,6 +2675,14 @@ 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 != VGA_NONE) { warn_report("A -vga option was passed but this machine " @@ -3028,6 +3038,9 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_gdb: add_device_config(DEV_GDB, optarg); break; + case QEMU_OPTION_mcd: + add_device_config(DEV_MCD, optarg); + break; case QEMU_OPTION_L: if (is_help_option(optarg)) { list_data_dirs = true; From patchwork Tue Nov 7 13:03:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448620 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 139F1C4167B for ; Tue, 7 Nov 2023 13:07:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlA-0000Dm-50; Tue, 07 Nov 2023 08:04:48 -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 1r0LkM-00088l-3c for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:59 -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 1r0LkI-0005lm-Ng for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:56 -0500 Received: (qmail 30837 invoked by uid 484); 7 Nov 2023 13:03:35 -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 Nov 2023 13:03: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 Nov 2023 13:03:32 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 02/20] mcdstub gdbstub: new DebugClass and DebugState introduced. They are used to abstract the debugger details behind a QOM. This is currently used in the cpu_handle_guest_debug function Date: Tue, 7 Nov 2023 14:03:05 +0100 Message-Id: <20231107130323.4126-3-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- debug/debug-common.c | 42 +++++++++++++++++++++++++++++++++++++++++ debug/debug-gdb.c | 24 +++++++++++++++++++++++ debug/debug-mcd.c | 25 ++++++++++++++++++++++++ gdbstub/meson.build | 4 ++-- gdbstub/system.c | 4 ++++ gdbstub/user.c | 2 ++ include/exec/gdbstub.h | 5 +++++ include/hw/boards.h | 1 + include/qemu/debug.h | 19 +++++++++++++++++++ include/qemu/typedefs.h | 2 ++ system/cpus.c | 9 ++++++++- 11 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 debug/debug-common.c create mode 100644 debug/debug-gdb.c create mode 100644 debug/debug-mcd.c create mode 100644 include/qemu/debug.h diff --git a/debug/debug-common.c b/debug/debug-common.c new file mode 100644 index 0000000000..8f41b4e6cb --- /dev/null +++ b/debug/debug-common.c @@ -0,0 +1,42 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.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 = { + .name = TYPE_DEBUG, + .parent = TYPE_OBJECT, + .instance_size = sizeof(DebugState), + .instance_init = debug_instance_init, + .instance_finalize = debug_finalize, + .class_size = sizeof(DebugClass), + .class_init = debug_class_init +}; + +static void debug_register_types(void) +{ + type_register_static(&debug_info); +} + +type_init(debug_register_types); diff --git a/debug/debug-gdb.c b/debug/debug-gdb.c new file mode 100644 index 0000000000..9c7bcda95f --- /dev/null +++ b/debug/debug-gdb.c @@ -0,0 +1,24 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "exec/gdbstub.h" +#include "qemu/debug.h" + +void gdb_init_debug_class(void) +{ + Object *obj; + obj = object_new(TYPE_DEBUG); + DebugState *ds = DEBUG(obj); + DebugClass *dc = DEBUG_GET_CLASS(ds); + dc->set_stop_cpu = gdb_set_stop_cpu; + MachineState *ms = MACHINE(qdev_get_machine()); + ms->debug_state = ds; +} diff --git a/debug/debug-mcd.c b/debug/debug-mcd.c new file mode 100644 index 0000000000..2d3a31be15 --- /dev/null +++ b/debug/debug-mcd.c @@ -0,0 +1,25 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "mcdstub/mcdstub.h" +#include "qemu/debug.h" +#include "qom/object_interfaces.h" + +void mcd_init_debug_class(void) +{ + Object *obj; + obj = object_new(TYPE_DEBUG); + DebugState *ds = DEBUG(obj); + DebugClass *dc = DEBUG_GET_CLASS(ds); + dc->set_stop_cpu = mcd_set_stop_cpu; + MachineState *ms = MACHINE(qdev_get_machine()); + ms->debug_state = ds; +} diff --git a/gdbstub/meson.build b/gdbstub/meson.build index e5bccba34e..359234595a 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -11,8 +11,8 @@ gdb_user_ss = ss.source_set() gdb_system_ss = ss.source_set() # We build two versions of gdbstub, one for each mode -gdb_user_ss.add(files('gdbstub.c', 'user.c')) -gdb_system_ss.add(files('gdbstub.c', 'system.c')) +gdb_user_ss.add(files('gdbstub.c', 'user.c', '../debug/debug-gdb.c')) +gdb_system_ss.add(files('gdbstub.c', 'system.c', '../debug/debug-gdb.c')) gdb_user_ss = gdb_user_ss.apply(config_targetos, strict: false) gdb_system_ss = gdb_system_ss.apply(config_targetos, strict: false) diff --git a/gdbstub/system.c b/gdbstub/system.c index 783ac140b9..02ec4875f5 100644 --- a/gdbstub/system.c +++ b/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" @@ -405,6 +406,9 @@ int gdbserver_start(const char *device) gdbserver_system_state.mon_chr = mon_chr; gdb_syscall_reset(); + /* create new debug object */ + gdb_init_debug_class(); + return 0; } diff --git a/gdbstub/user.c b/gdbstub/user.c index dbe1d9b887..f8207aa9ef 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -332,8 +332,10 @@ int gdbserver_start(const char *port_or_path) } if (port > 0 && gdb_accept_tcp(gdb_fd)) { + gdb_init_debug_class(); return 0; } else if (gdb_accept_socket(gdb_fd)) { + gdb_init_debug_class(); gdbserver_user_state.socket_path = g_strdup(port_or_path); return 0; } diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 1a01c35f8e..f696e29477 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -48,4 +48,9 @@ void gdb_set_stop_cpu(CPUState *cpu); /* in gdbstub-xml.c, generated by scripts/feature_to_c.py */ extern const GDBFeature gdb_static_features[]; +/** + * gdb_init_debug_class() - initialize gdb-specific DebugClass + */ +void gdb_init_debug_class(void); + #endif diff --git a/include/hw/boards.h b/include/hw/boards.h index a735999298..ffc7756b89 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; }; #define DEFINE_MACHINE(namestr, machine_initfn) \ diff --git a/include/qemu/debug.h b/include/qemu/debug.h new file mode 100644 index 0000000000..870f3ea152 --- /dev/null +++ b/include/qemu/debug.h @@ -0,0 +1,19 @@ +#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 0848e0dbdb..734173096a 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" @@ -306,7 +307,13 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - gdb_set_stop_cpu(cpu); + MachineState *ms = MACHINE(qdev_get_machine()); + DebugState *ds = ms->debug_state; + DebugClass *dc = DEBUG_GET_CLASS(ds); + + if (dc->set_stop_cpu) { + dc->set_stop_cpu(cpu); + } qemu_system_debug_request(); cpu->stopped = true; } From patchwork Tue Nov 7 13:03:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448627 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4278DC4332F for ; Tue, 7 Nov 2023 13:10:10 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmq-0002cM-0T; Tue, 07 Nov 2023 08:06:32 -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 1r0LkN-00089N-R4 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:01 -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 1r0LkM-0005nQ-15 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:59 -0500 Received: (qmail 30874 invoked by uid 484); 7 Nov 2023 13:03:37 -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.142005 secs); 07 Nov 2023 13:03:37 -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 Nov 2023 13:03:35 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 03/20] gdbstub: moving code so that it can be easier accessed from outside the gdbstub: fromhex and tohex functions moved to a cutils header. GDBRegisterState moved to gdbstub.h Date: Tue, 7 Nov 2023 14:03:06 +0100 Message-Id: <20231107130323.4126-4-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- gdbstub/gdbstub.c | 9 +-------- gdbstub/internals.h | 26 -------------------------- include/cutils.h | 30 ++++++++++++++++++++++++++++++ include/exec/gdbstub.h | 9 ++++++++- 4 files changed, 39 insertions(+), 35 deletions(-) create mode 100644 include/cutils.h diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 1e96a71c0c..c43ff89393 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -44,14 +44,7 @@ #include "exec/hwaddr.h" #include "internals.h" - -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; +#include "cutils.h" GDBState gdbserver_state; diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 465c24b36e..011e6f1858 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -74,32 +74,6 @@ typedef struct GDBState { /* lives in main gdbstub.c */ extern GDBState gdbserver_state; -/* - * Inline utility function, convert from int to hex and back - */ - -static inline int fromhex(int v) -{ - if (v >= '0' && v <= '9') { - return v - '0'; - } else if (v >= 'A' && v <= 'F') { - return v - 'A' + 10; - } else if (v >= 'a' && v <= '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/cutils.h b/include/cutils.h new file mode 100644 index 0000000000..a6b8dc3690 --- /dev/null +++ b/include/cutils.h @@ -0,0 +1,30 @@ +#ifndef CUTILS_H +#define CUTILS_H + +/* + * Inline utility function, convert from int to hex and back + */ + +static inline int fromhex(int v) +{ + if (v >= '0' && v <= '9') { + return v - '0'; + } else if (v >= 'A' && v <= 'F') { + return v - 'A' + 10; + } else if (v >= 'a' && v <= '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'; + } +} + +#endif /* CUTILS_H */ diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index f696e29477..cb70ebd7b4 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -15,11 +15,18 @@ typedef struct GDBFeature { const char *xml; } GDBFeature; - /* Get or set a register. Returns the size of the register. */ 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); +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 From patchwork Tue Nov 7 13:03:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448621 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E5144C4167B for ; Tue, 7 Nov 2023 13:07:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmt-0002j4-ML; Tue, 07 Nov 2023 08:06:35 -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 1r0Lkq-0008Pc-Fa for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lkg-0005rX-DK for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:28 -0500 Received: (qmail 31007 invoked by uid 484); 7 Nov 2023 13:03:45 -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.272829 secs); 07 Nov 2023 13:03:45 -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 Nov 2023 13:03:38 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 04/20] mcdstub: added header with defines specific to the mcd tcp packet communication Date: Tue, 7 Nov 2023 14:03:07 +0100 Message-Id: <20231107130323.4126-5-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcd_shared_defines.h | 108 +++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 include/mcdstub/mcd_shared_defines.h diff --git a/include/mcdstub/mcd_shared_defines.h b/include/mcdstub/mcd_shared_defines.h new file mode 100644 index 0000000000..fa1adb5c77 --- /dev/null +++ b/include/mcdstub/mcd_shared_defines.h @@ -0,0 +1,108 @@ +/* + *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 From patchwork Tue Nov 7 13:03:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448604 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2D6F3C4167D for ; Tue, 7 Nov 2023 13:06:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Llk-0001CA-Ji; Tue, 07 Nov 2023 08:05:28 -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 1r0Lkl-0008JL-Ep for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:26 -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 1r0Lkg-0005rk-DL for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:23 -0500 Received: (qmail 31068 invoked by uid 484); 7 Nov 2023 13:03:47 -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 9e-06 secs); 07 Nov 2023 13:03:47 -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 Nov 2023 13:03:46 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 05/20] mcdstub: tcp packet processing added Date: Tue, 7 Nov 2023 14:03:08 +0100 Message-Id: <20231107130323.4126-6-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 144 ++++++++++++++++++++ mcdstub/mcdstub.c | 277 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 421 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 36058157ae..1461d0e1cb 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -25,6 +25,21 @@ typedef struct MCDProcess { char target_xml[1024]; } 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 { @@ -176,6 +191,35 @@ bool mcd_supports_guest_debug(void); * @state: The new (and active) VM run state. */ void mcd_vm_state_change(void *opaque, bool running, RunState state); + +/** + * mcd_put_packet() - Calls :c:func:`mcd_put_packet_binary` with buf and length + * of buf. + * + * @buf: TCP packet data. + */ +int mcd_put_packet(const char *buf); + +/** + * 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 complete 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. + */ +int mcd_put_packet_binary(const char *buf, int len); + +/** + * mcd_put_buffer() - Sends the buf as TCP packet with qemu_chr_fe_write_all. + * + * @buf: TCP packet data. + * @len: TCP packet length. + */ +void mcd_put_buffer(const uint8_t *buf, int len); + /** * mcd_get_cpu_process() - Returns the process of the provided CPU. * @@ -218,6 +262,82 @@ CPUState *mcd_first_attached_cpu(void); */ CPUState *mcd_next_attached_cpu(CPUState *cpu); +/** + * mcd_read_byte() - Resends the last packet if not acknowledged and extracts + * 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. + */ +void mcd_read_byte(uint8_t ch); + +/** + * 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 parameter + * schema. With this info it calls :c:func:`run_cmd_parser`. + * @line_buf: TCP packet data. + */ +int mcd_handle_packet(const char *line_buf); + +/** + * mcd_put_strbuf() - Calls :c:func:`mcd_put_packet` with the str_buf of the + * mcdserver_state. + */ +void mcd_put_strbuf(void); + +/** + * run_cmd_parser() - Prepares the mcdserver_state before executing TCP packet + * 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). + */ +void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); + +/** + * 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 function. + * This function selects the command in the cmds array, which fits the start 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. + */ +int process_string_cmd(void *user_ctx, const char *data, + const MCDCmdParseEntry *cmds, int num_cmds); + +/** + * cmd_parse_params() - Extracts all parameters from a TCP packet. + * + * This function uses the schema parameter to determine which type of parameter + * 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. + */ +int cmd_parse_params(const char *data, const char *schema, GArray *params); +/** + * mcd_get_cpu_index() - Returns the internal CPU index plus one. + * + * @cpu: CPU of interest. + */ +int mcd_get_cpu_index(CPUState *cpu); + /** * mcd_get_cpu() - Returns the CPU the index i_cpu_index. * @@ -237,3 +357,27 @@ CPUState *get_first_cpu_in_process(MCDProcess *process); * @thread_id: ID of the desired CPU. */ CPUState *find_cpu(uint32_t thread_id); +/* helpers */ + +/** + * int_cmp() - Compares a and b and returns zero if they are equal. + * + * @a: Pointer to integer a. + * @b: Pointer to integer b. + */ +int int_cmp(gconstpointer a, gconstpointer b); +/** + * atouint64_t() - Converts a string into a unsigned 64 bit integer. + * + * @in: Pointer to input string. + */ +uint64_t atouint64_t(const char *in); + +/** + * atouint32_t() - Converts a string into a unsigned 32 bit integer. + * + * @in: Pointer to input string. + */ +uint32_t atouint32_t(const char *in); + +#endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 4cdf2e42ed..6900dcd0ea 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -80,7 +80,14 @@ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) { /* initalizes a list of all query commands */ int cmd_number = 0; + +void reset_mcdserver_state(void) +{ + g_free(mcdserver_state.processes); + mcdserver_state.processes = NULL; + mcdserver_state.process_num = 0; } + void create_processes(MCDState *s) { object_child_foreach(object_get_root(), find_cpu_clusters, s); @@ -243,6 +250,228 @@ void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) } } +void mcd_read_byte(uint8_t ch) +{ + uint8_t reply; + + if (mcdserver_state.last_packet->len) { + if (ch == 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 == TCP_ACKNOWLEDGED) { + /* the previous packet was acknowledged */ + } + + if (ch == TCP_ACKNOWLEDGED || ch == 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 != TCP_COMMAND_START) { + /* skip to the next char */ + return; + } + } + + switch (mcdserver_state.state) { + case RS_IDLE: + if (ch == TCP_COMMAND_START) { + /* start of command packet */ + mcdserver_state.line_buf_index = 0; + mcdserver_state.line_sum = 0; + mcdserver_state.state = RS_GETLINE; + } + break; + case RS_GETLINE: + if (ch == TCP_COMMAND_END) { + /* end of command */ + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; + mcdserver_state.state = RS_DATAEND; + } else if (mcdserver_state.line_buf_index >= + sizeof(mcdserver_state.line_buf) - 1) { + /* the input string is too long for the linebuffer! */ + mcdserver_state.state = RS_IDLE; + } else { + /* copy the content to the line_buf */ + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch; + mcdserver_state.line_sum += ch; + } + break; + case RS_DATAEND: + if (ch == TCP_WAS_NOT_LAST) { + reply = TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); + } else if (ch == TCP_WAS_LAST) { + reply = TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); + } else { + /* not acknowledged! */ + reply = TCP_NOT_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + /* waiting for package to get resent */ + mcdserver_state.state = RS_IDLE; + } + break; + default: + abort(); + } +} + +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 = 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; +} +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(""); + } +} + +uint64_t atouint64_t(const char *in) +{ + uint64_t res = 0; + for (int i = 0; i < strlen(in); ++i) { + const char c = in[i]; + res *= 10; + res += c - '0'; + } + + return res; +} + +uint32_t atouint32_t(const char *in) +{ + uint32_t res = 0; + for (int i = 0; i < strlen(in); ++i) { + const char c = in[i]; + res *= 10; + res += c - '0'; + } + + return res; +} + +int cmd_parse_params(const char *data, const char *schema, GArray *params) +{ + + char data_buffer[64] = {0}; + const char *remaining_data = data; + + for (int i = 0; i < strlen(schema); i++) { + /* get correct part of data */ + char *separator = strchr(remaining_data, ARGUMENT_SEPARATOR); + + if (separator) { + /* multiple arguments */ + int seperator_index = (int)(separator - remaining_data); + strncpy(data_buffer, remaining_data, seperator_index); + data_buffer[seperator_index] = 0; + /* update remaining data for the next run */ + remaining_data = &(remaining_data[seperator_index + 1]); + } else { + strncpy(data_buffer, remaining_data, strlen(remaining_data)); + data_buffer[strlen(remaining_data)] = 0; + } + + /* store right data */ + MCDCmdVariant this_param; + switch (schema[i]) { + case ARG_SCHEMA_STRING: + /* this has to be the last argument */ + this_param.data = 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: + this_param.data_uint32_t = atouint32_t(data_buffer); + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_UINT64_T: + this_param.data_uint64_t = atouint64_t(data_buffer); + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_QRYHANDLE: + this_param.query_handle = atouint32_t(data_buffer); + g_array_append_val(params, this_param); + break; + case ARG_SCHEMA_CORENUM: + this_param.cpu_id = atouint32_t(data_buffer); + g_array_append_val(params, this_param); + break; + default: + return -1; + } + } + return 0; +} + +int process_string_cmd(void *user_ctx, const char *data, + const MCDCmdParseEntry *cmds, int num_cmds) +{ + int i; + g_autoptr(GArray) params = g_array_new(false, true, sizeof(MCDCmdVariant)); + + if (!cmds) { + return -1; + } + + for (i = 0; i < num_cmds; i++) { + const MCDCmdParseEntry *cmd = &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, params)) + { + return -1; + } + } + + /* call handler */ + cmd->handler(params, user_ctx); + return 0; + } + + return -1; +} void mcd_chr_event(void *opaque, QEMUChrEvent event) { @@ -281,6 +510,43 @@ void mcd_sigterm_handler(int signal) } #endif +int mcd_put_packet(const char *buf) +{ + return mcd_put_packet_binary(buf, strlen(buf)); +} + +void mcd_put_strbuf(void) +{ + mcd_put_packet(mcdserver_state.str_buf->str); +} + +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; +} + +void mcd_put_buffer(const uint8_t *buf, int len) +{ + qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len); +} + +MCDProcess *mcd_get_cpu_process(CPUState *cpu) +{ + return mcd_get_process(mcd_get_cpu_pid(cpu)); +} + uint32_t mcd_get_cpu_pid(CPUState *cpu) { if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { @@ -381,3 +647,14 @@ CPUState *find_cpu(uint32_t thread_id) return NULL; } + +int int_cmp(gconstpointer a, gconstpointer b) +{ + int int_a = *(int *)a; + int int_b = *(int *)b; + if (int_a == int_b) { + return 0; + } else { + return 1; + } +} From patchwork Tue Nov 7 13:03:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448605 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5ECF8C4332F for ; Tue, 7 Nov 2023 13:06:36 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LmF-0001v0-2c; Tue, 07 Nov 2023 08:05:58 -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 1r0Lkl-0008Gn-0W for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:26 -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 1r0Lkg-0005sV-DI for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:22 -0500 Received: (qmail 31102 invoked by uid 484); 7 Nov 2023 13:03:50 -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.151891 secs); 07 Nov 2023 13:03:50 -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 Nov 2023 13:03:47 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 06/20] mcdstub: open/close server functions and trigger/reset data added. User for initial connection with an mcd client Date: Tue, 7 Nov 2023 14:03:09 +0100 Message-Id: <20231107130323.4126-7-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 84 ++++++++++++++++++++++++++++++++++++ mcdstub/mcdstub.c | 90 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 1461d0e1cb..c7e34673a6 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -7,6 +7,24 @@ #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 @@ -49,6 +67,13 @@ enum RSState { RS_DATAEND, }; +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 MCDState { bool init; /* have we been initialised? */ CPUState *c_cpu; /* current CPU for everything */ @@ -81,6 +106,11 @@ typedef struct MCDState { /* lives in main mcdstub.c */ extern MCDState mcdserver_state; +typedef struct mcd_reset_st { + const char *name; + uint8_t id; +} mcd_reset_st; + #ifndef _WIN32 void mcd_sigterm_handler(int signal); #endif @@ -109,6 +139,38 @@ void mcd_init_mcdserver_state(void); * @mcd_query_cmds_table: Lookup table with all query commands. */ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table); + +/** + * 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. + */ +int init_resets(GArray *resets); + +/** + * init_trigger() - Initializes the trigger info. + * + * This function adds the types of trigger, their possible options and actions + * to the trigger struct. + * @trigger: Struct with all trigger info. + */ +int init_trigger(mcd_trigger_into_st *trigger); + +/** + * mcd_init_debug_class() - initialize mcd-specific DebugClass + */ +void mcd_init_debug_class(void); + +/** + * reset_mcdserver_state() - Resets the mcdserver_state struct. + * + * This function deletes all processes connected to the mcdserver_state. + */ +void reset_mcdserver_state(void); + /** * create_processes() - Sorts all processes and calls * :c:func:`mcd_create_default_process`. @@ -357,6 +419,28 @@ CPUState *get_first_cpu_in_process(MCDProcess *process); * @thread_id: ID of the desired CPU. */ CPUState *find_cpu(uint32_t thread_id); + +/** + * 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. + */ +void handle_close_server(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_open_server(GArray *params, void *user_ctx); + /* helpers */ /** diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 6900dcd0ea..d2f6df04c0 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -331,6 +331,25 @@ int mcd_handle_packet(const char *line_buf) const MCDCmdParseEntry *cmd_parser = NULL; switch (line_buf[0]) { + case TCP_CHAR_OPEN_SERVER: + { + static MCDCmdParseEntry open_server_cmd_desc = { + .handler = handle_open_server, + }; + open_server_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_SERVER, '\0' }; + cmd_parser = &open_server_cmd_desc; + } + break; + case TCP_CHAR_CLOSE_SERVER: + { + static MCDCmdParseEntry close_server_cmd_desc = { + .handler = handle_close_server, + }; + close_server_cmd_desc.cmd = + (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' }; + cmd_parser = &close_server_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -658,3 +677,74 @@ int int_cmp(gconstpointer a, gconstpointer b) return 1; } } + +int init_resets(GArray *resets) +{ + mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM}; + mcd_reset_st gpr_reset = { .id = 1, .name = RESET_GPR}; + mcd_reset_st memory_reset = { .id = 2, .name = 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; +} + +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 = 16; + return 0; +} + +void handle_open_server(GArray *params, void *user_ctx) +{ + /* initialize core-independent data */ + int return_value = 0; + mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st)); + return_value = init_resets(mcdserver_state.resets); + if (return_value != 0) { + g_assert_not_reached(); + } + return_value = init_trigger(&mcdserver_state.trigger); + if (return_value != 0) { + g_assert_not_reached(); + } + + mcd_put_packet(TCP_HANDSHAKE_SUCCESS); +} + + +void handle_close_server(GArray *params, void *user_ctx) +{ + uint32_t pid = 1; + MCDProcess *process = 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 = false; + + /* 3. reset process */ + if (pid == mcd_get_cpu_pid(mcdserver_state.c_cpu)) { + mcdserver_state.c_cpu = mcd_first_attached_cpu(); + } + if (!mcdserver_state.c_cpu) { + /* no more processes attached */ + mcd_vm_start(); + } +} + From patchwork Tue Nov 7 13:03:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448597 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2852FC4332F for ; Tue, 7 Nov 2023 13:04:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LkU-00089O-0M; Tue, 07 Nov 2023 08:04:07 -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 1r0LkJ-00088I-T8 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:55 -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 1r0LkH-0005us-KF for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:03:55 -0500 Received: (qmail 31123 invoked by uid 484); 7 Nov 2023 13:03:51 -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.071698 secs); 07 Nov 2023 13:03:51 -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 Nov 2023 13:03:50 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 07/20] mcdstub: quitting QEMU via mcd command added Date: Tue, 7 Nov 2023 14:03:10 +0100 Message-Id: <20231107130323.4126-8-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 9 +++++++++ mcdstub/mcdstub.c | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index c7e34673a6..c3e9c7e9dc 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -356,6 +356,15 @@ int mcd_handle_packet(const char *line_buf); */ void mcd_put_strbuf(void); +/** + * mcd_exit() - Terminates QEMU. + * + * If the mcdserver_state has not been initialized the function exits before + * terminating QEMU. Terminting is done with the qemu_chr_fe_deinit function. + * @code: An exitcode, which can be used in the future. + */ +void mcd_exit(int code); + /** * run_cmd_parser() - Prepares the mcdserver_state before executing TCP packet * functions. diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index d2f6df04c0..858e79632b 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -340,6 +340,11 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &open_server_cmd_desc; } break; + case TCP_CHAR_KILLQEMU: + /* kill qemu completely */ + error_report("QEMU: Terminated via MCDstub"); + mcd_exit(0); + exit(0); case TCP_CHAR_CLOSE_SERVER: { static MCDCmdParseEntry close_server_cmd_desc = { @@ -492,6 +497,16 @@ int process_string_cmd(void *user_ctx, const char *data, return -1; } +void mcd_exit(int code) +{ + /* terminate qemu */ + if (!mcdserver_state.init) { + return; + } + + qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); +} + void mcd_chr_event(void *opaque, QEMUChrEvent event) { int i; From patchwork Tue Nov 7 13:03:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448624 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4ED06C4332F for ; Tue, 7 Nov 2023 13:09:25 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlK-0000WR-8j; Tue, 07 Nov 2023 08:04:59 -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 1r0Lkg-0008GN-I1 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:24 -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 1r0LkK-0005vg-MG for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:07 -0500 Received: (qmail 31185 invoked by uid 484); 7 Nov 2023 13:03:54 -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 1.9e-05 secs); 07 Nov 2023 13:03:54 -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 Nov 2023 13:03:52 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 08/20] mcdstub: query packet processing added and core/system querie added Date: Tue, 7 Nov 2023 14:03:11 +0100 Message-Id: <20231107130323.4126-9-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 30 +++++++++++++++++ mcdstub/mcdstub.c | 70 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index c3e9c7e9dc..c4370bb177 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -402,6 +402,18 @@ int process_string_cmd(void *user_ctx, const char *data, * @params: GArray with all extracted parameters. */ int cmd_parse_params(const char *data, const char *schema, GArray *params); + +/** + * 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 correct + * one. This function just passes on the TCP packet data string from the + * parameters. + * @params: GArray with all TCP packet parameters. + */ +void handle_gen_query(GArray *params, void *user_ctx); + /** * mcd_get_cpu_index() - Returns the internal CPU index plus one. * @@ -415,6 +427,24 @@ int mcd_get_cpu_index(CPUState *cpu); * @cpu_index: Index of the desired CPU. */ CPUState *mcd_get_cpu(uint32_t cpu_index); + +/** + * 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 structure. + * @params: GArray with all TCP packet parameters. + */ +void handle_query_cores(GArray *params, void *user_ctx); + +/** + * handle_query_system() - Handler for the system query. + * + * Sends the system name, which is "qemu-system". + * @params: GArray with all TCP packet parameters. + */ +void handle_query_system(GArray *params, void *user_ctx); + /** * get_first_cpu_in_process() - Returns the first CPU in the provided process. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 858e79632b..a090268e70 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -81,6 +81,20 @@ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) /* initalizes a list of all query commands */ int cmd_number = 0; + MCDCmdParseEntry query_system = { + .handler = handle_query_system, + .cmd = QUERY_ARG_SYSTEM, + }; + mcd_query_cmds_table[cmd_number] = query_system; + cmd_number++; + + MCDCmdParseEntry query_cores = { + .handler = handle_query_cores, + .cmd = QUERY_ARG_CORES, + }; + mcd_query_cmds_table[cmd_number] = query_cores; + cmd_number++; + void reset_mcdserver_state(void) { g_free(mcdserver_state.processes); @@ -345,6 +359,17 @@ int mcd_handle_packet(const char *line_buf) error_report("QEMU: Terminated via MCDstub"); mcd_exit(0); exit(0); + case TCP_CHAR_QUERY: + { + static MCDCmdParseEntry query_cmd_desc = { + .handler = handle_gen_query, + }; + query_cmd_desc.cmd = (char[2]) { TCP_CHAR_QUERY, '\0' }; + strcpy(query_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_STRING, '\0' }); + cmd_parser = &query_cmd_desc; + } + break; case TCP_CHAR_CLOSE_SERVER: { static MCDCmdParseEntry close_server_cmd_desc = { @@ -368,6 +393,20 @@ int mcd_handle_packet(const char *line_buf) return RS_IDLE; } + +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(""); + } +} + void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) { if (!data) { @@ -735,6 +774,37 @@ void handle_open_server(GArray *params, void *user_ctx) mcd_put_packet(TCP_HANDSHAKE_SUCCESS); } +void handle_query_system(GArray *params, void *user_ctx) +{ + mcd_put_packet(MCD_SYSTEM_NAME); +} + +void handle_query_cores(GArray *params, void *user_ctx) +{ + /* get first cpu */ + CPUState *cpu = mcd_first_attached_cpu(); + if (!cpu) { + return; + } + + ObjectClass *oc = object_get_class(OBJECT(cpu)); + const char *cpu_model = object_class_get_name(oc); + + CPUClass *cc = CPU_GET_CLASS(cpu); + const gchar *arch = cc->gdb_arch_name(cpu); + + uint32_t nr_cores = cpu->nr_cores; + char device_name[ARGUMENT_STRING_LENGTH] = {0}; + if (arch) { + snprintf(device_name, sizeof(device_name), "%s", + DEVICE_NAME_TEMPLATE(arch)); + } + g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%u.", + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, + TCP_ARGUMENT_AMOUNT_CORE, nr_cores); + mcd_put_strbuf(); +} + void handle_close_server(GArray *params, void *user_ctx) { From patchwork Tue Nov 7 13:03:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448600 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 46451C4332F for ; Tue, 7 Nov 2023 13:05:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlH-0000Ox-2Q; Tue, 07 Nov 2023 08:04:55 -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 1r0LkQ-00089u-BJ for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:05 -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 1r0LkM-0005x9-1B for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:01 -0500 Received: (qmail 31207 invoked by uid 484); 7 Nov 2023 13:03:54 -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.072978 secs); 07 Nov 2023 13:03:54 -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 Nov 2023 13:03:54 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 09/20] mcdstub: open/close core added. This includes core specific data preparation: memory spaces, register groups and registers. This data preparation is done in the arm mcdstub Date: Tue, 7 Nov 2023 14:03:12 +0100 Message-Id: <20231107130323.4126-10-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/arm_mcdstub.h | 81 +++++++++ include/mcdstub/mcdstub.h | 26 +++ include/mcdstub/mcdstub_common.h | 52 ++++++ mcdstub/mcdstub.c | 111 ++++++++++++ target/arm/mcdstub.c | 278 +++++++++++++++++++++++++++++++ 5 files changed, 548 insertions(+) create mode 100644 target/arm/mcdstub.c diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h index a57aa8e9f2..c71f6c3356 100644 --- a/include/mcdstub/arm_mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -6,5 +6,86 @@ /* 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_get_dynamic_xml() - Returns the contents of the desired XML file. + * + * @xmlname: Name of the desired XML file. + * @cs: CPU state. + */ +const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); + +/** + * 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 by ARM. + * @n: The register ID of the CP register. + * @cs: CPU state. + */ +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); + +/** + * arm_mcd_store_mem_spaces() - Stores all 32-Bit ARM specific memory spaces. + * + * 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 registers. + * 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 file 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 *registers, #endif /* ARM_MCDSTUB_H */ diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index c4370bb177..d38106e973 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -106,6 +106,11 @@ typedef struct MCDState { /* lives in main 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; @@ -459,6 +464,18 @@ CPUState *get_first_cpu_in_process(MCDProcess *process); */ CPUState *find_cpu(uint32_t thread_id); +/** + * 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 where + * every entry in the list corresponds to one opened core. + * @params: GArray with all TCP packet parameters. + */ +void handle_open_core(GArray *params, void *user_ctx); + /** * handle_close_server() - Handler for closing the MCD server. * @@ -468,6 +485,15 @@ CPUState *find_cpu(uint32_t thread_id); */ void handle_close_server(GArray *params, void *user_ctx); +/** + * 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. + */ +void handle_close_core(GArray *params, void *user_ctx); + /** * handle_open_server() - Handler for opening the MCD server. * diff --git a/include/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_common.h index 3bae2c3b6f..633d9b0f70 100644 --- a/include/mcdstub/mcdstub_common.h +++ b/include/mcdstub/mcdstub_common.h @@ -4,4 +4,56 @@ #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; + +/** + * parse_reg_xml() - Parses a GDB register XML file + * + * This fuction extracts all registers from the provided xml file and stores + * 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 */ diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index a090268e70..ca98d01ee7 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -370,6 +370,17 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &query_cmd_desc; } break; + case TCP_CHAR_OPEN_CORE: + { + static MCDCmdParseEntry open_core_cmd_desc = { + .handler = handle_open_core, + }; + open_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_CORE, '\0' }; + strcpy(open_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &open_core_cmd_desc; + } + break; case TCP_CHAR_CLOSE_SERVER: { static MCDCmdParseEntry close_server_cmd_desc = { @@ -380,6 +391,17 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &close_server_cmd_desc; } break; + case TCP_CHAR_CLOSE_CORE: + { + static MCDCmdParseEntry close_core_cmd_desc = { + .handler = handle_close_core, + }; + close_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_CLOSE_CORE, '\0' }; + strcpy(close_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &close_core_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -805,6 +827,95 @@ void handle_query_cores(GArray *params, void *user_ctx) mcd_put_strbuf(); } +void handle_open_core(GArray *params, void *user_ctx) +{ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcdserver_state.c_cpu = cpu; + CPUClass *cc = CPU_GET_CLASS(cpu); + const gchar *arch = cc->gdb_arch_name(cpu); + int return_value = 0; + + /* prepare data strucutures */ + GArray *memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); + GArray *reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + GArray *registers = g_array_new(false, true, sizeof(mcd_reg_st)); + + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { + /* TODO: make group and memspace ids dynamic */ + int current_group_id = 1; + /* 1. store mem spaces */ + return_value = arm_mcd_store_mem_spaces(cpu, memspaces); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 2. parse core xml */ + return_value = arm_mcd_parse_core_xml_file(cc, reggroups, + registers, ¤t_group_id); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 3. parse other xmls */ + return_value = arm_mcd_parse_general_xml_files(cpu, reggroups, + registers, ¤t_group_id); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 4. add additional data the the regs from the xmls */ + return_value = arm_mcd_get_additional_register_info(reggroups, + registers, cpu); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 5. store all found data */ + if (g_list_nth(mcdserver_state.all_memspaces, cpu_id)) { + GList *memspaces_ptr = + g_list_nth(mcdserver_state.all_memspaces, cpu_id); + memspaces_ptr->data = memspaces; + } else { + mcdserver_state.all_memspaces = + g_list_insert(mcdserver_state.all_memspaces, memspaces, cpu_id); + } + if (g_list_nth(mcdserver_state.all_reggroups, cpu_id)) { + GList *reggroups_ptr = + g_list_nth(mcdserver_state.all_reggroups, cpu_id); + reggroups_ptr->data = reggroups; + } else { + mcdserver_state.all_reggroups = + g_list_insert(mcdserver_state.all_reggroups, reggroups, cpu_id); + } + if (g_list_nth(mcdserver_state.all_registers, cpu_id)) { + GList *registers_ptr = + g_list_nth(mcdserver_state.all_registers, cpu_id); + registers_ptr->data = registers; + } else { + mcdserver_state.all_registers = + g_list_insert(mcdserver_state.all_registers, registers, cpu_id); + } + } else { + /* we don't support other architectures */ + g_assert_not_reached(); + } +} + + +void handle_close_core(GArray *params, void *user_ctx) +{ + /* free memory for correct core */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcdserver_state.all_memspaces = + g_list_remove(mcdserver_state.all_memspaces, memspaces); + g_array_free(memspaces, TRUE); + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + mcdserver_state.all_reggroups = + g_list_remove(mcdserver_state.all_reggroups, reggroups); + g_array_free(reggroups, TRUE); + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + mcdserver_state.all_registers = + g_list_remove(mcdserver_state.all_registers, registers); + g_array_free(registers, TRUE); +} void handle_close_server(GArray *params, void *user_ctx) { diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c new file mode 100644 index 0000000000..ff1350831b --- /dev/null +++ b/target/arm/mcdstub.c @@ -0,0 +1,278 @@ +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/memory.h" +#include "sysemu/tcg.h" +#include "internals.h" +#include "cpregs.h" +#include "qemu/debug.h" +#include "mcdstub/arm_mcdstub.h" + +const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname) +{ + ARMCPU *cpu = ARM_CPU(cs); + + if (strcmp(xmlname, "system-registers.xml") == 0) { + return cpu->dyn_sysreg_xml.desc; + } else if (strcmp(xmlname, "sve-registers.xml") == 0) { + return cpu->dyn_svereg_xml.desc; + } else if (strcmp(xmlname, "arm-m-system.xml") == 0) { + return cpu->dyn_m_systemreg_xml.desc; +#ifndef CONFIG_USER_ONLY + } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) { + return cpu->dyn_m_secextreg_xml.desc; +#endif + } + return NULL; +} + +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) +{ + /*gets the opcode for a cp register*/ + ARMCPU *cpu = ARM_CPU(cs); + const ARMCPRegInfo *ri; + uint32_t key; + + key = cpu->dyn_sysreg_xml.data.cpregs.keys[n]; + ri = get_arm_cp_reginfo(cpu->cp_regs, key); + if (ri) { + uint16_t opcode = 0; + opcode |= ri->opc1 << 14; + opcode |= ri->opc2 << 10; + opcode |= ri->crm << 7; + opcode |= ri->crn << 3; + return opcode; + } + return 0; +} + +int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) +{ + int nr_address_spaces = cpu->num_ases; + uint32_t mem_space_id = 0; + + mem_space_id++; + mcd_mem_space_st non_secure = { + .name = "Non Secure", + .id = mem_space_id, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = false, + .is_physical = false, + }; + g_array_append_vals(memspaces, (gconstpointer)&non_secure, 1); + mem_space_id++; + mcd_mem_space_st phys_non_secure = { + .name = "Physical (Non Secure)", + .id = mem_space_id, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = false, + .is_physical = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); + if (nr_address_spaces > 1) { + mem_space_id++; + mcd_mem_space_st secure = { + .name = "Secure", + .id = mem_space_id, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + .is_physical = false, + }; + g_array_append_vals(memspaces, (gconstpointer)&secure, 1); + mem_space_id++; + mcd_mem_space_st phys_secure = { + .name = "Physical (Secure)", + .id = mem_space_id, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + .is_physical = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); + } + mem_space_id++; + mcd_mem_space_st gpr = { + .name = "GPR Registers", + .id = mem_space_id, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(memspaces, (gconstpointer)&gpr, 1); + mem_space_id++; + mcd_mem_space_st cpr = { + .name = "CP15 Registers", + .id = mem_space_id, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 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 = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + int i = 0; + + /* 1. get correct file */ + xml_filename = cc->gdb_core_xml_file; + for (i = 0; ; i++) { + current_xml_filename = gdb_static_features[i].xmlname; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == 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 = { + .name = "GPR Registers", + .id = *current_group_id + }; + g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); + *current_group_id = *current_group_id + 1; + + /* 3. parse xml */ + /* the offset for gpr is always zero */ + xml_content = 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 = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + uint8_t reg_type; + + /* iterate over all gdb xml files*/ + GDBRegisterState *r; + for (guint i = 0; i < cpu->gdb_regs->len; i++) { + r = &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + + xml_filename = r->xml; + xml_content = NULL; + + /* 1. get xml content */ + xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); + if (xml_content) { + if (strcmp(xml_filename, "system-registers.xml") == 0) { + /* these are the coprocessor register */ + mcd_reg_group_st corprocessorregs = { + .name = "CP15 Registers", + .id = *current_group_id + }; + g_array_append_vals(reggroups, + (gconstpointer)&corprocessorregs, 1); + *current_group_id = *current_group_id + 1; + reg_type = MCD_ARM_REG_TYPE_CPR; + } + } else { + /* its not a coprocessor xml -> it is a static xml file */ + int j = 0; + for (j = 0; ; j++) { + current_xml_filename = gdb_static_features[j].xmlname; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == strlen(xml_filename))) + break; + } + if (current_xml_filename) { + xml_content = gdb_static_features[j].xml; + /* select correct reg_type */ + if (strcmp(current_xml_filename, "arm-vfp.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, "arm-vfp3.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-vfp-sysregs.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP_SYS; + } else if (strcmp(current_xml_filename, + "arm-neon.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-m-profile-mve.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_MVE; + } + } else { + continue; + } + } + /* 2. parse xml */ + parse_reg_xml(xml_content, strlen(xml_content), registers, reg_type, + r->base_reg); + } + return 0; +} + +int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu) +{ + mcd_reg_st *current_register; + uint32_t i = 0; + + /* iterate over all registers */ + for (i = 0; i < registers->len; i++) { + current_register = &(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") == 0) { + /* coprocessor registers */ + current_register->mcd_reg_group_id = 2; + current_register->mcd_mem_space_id = 6; + /* + * get info for opcode + * for 32bit the opcode is only 16 bit long + * for 64bit it is 32 bit long + */ + current_register->opcode |= + arm_mcd_get_opcode(cpu, current_register->internal_id); + } else { + /* gpr register */ + current_register->mcd_reg_group_id = 1; + current_register->mcd_mem_space_id = 5; + } + } + return 0; +} + From patchwork Tue Nov 7 13:03:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448599 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 13003C4332F for ; Tue, 7 Nov 2023 13:04:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lku-0008Jz-63; Tue, 07 Nov 2023 08:04:38 -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 1r0LkP-00089d-H3 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:05 -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 1r0LkN-0005xn-5O for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:01 -0500 Received: (qmail 31228 invoked by uid 484); 7 Nov 2023 13:03:56 -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.073425 secs); 07 Nov 2023 13:03:56 -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 Nov 2023 13:03:55 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 10/20] mcdstub: state query added: this query collects information about the state of a specific core. This commit also includes mcd_vm_state_change, which is called when the cpu state changes because it collects data for the query Date: Tue, 7 Nov 2023 14:03:13 +0100 Message-Id: <20231107130323.4126-11-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 41 +++++++++++++++ mcdstub/mcdstub.c | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index d38106e973..eb46917d00 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -36,6 +36,20 @@ /* 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; @@ -67,6 +81,12 @@ enum RSState { 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]; @@ -74,6 +94,17 @@ typedef struct mcd_trigger_into_st { 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; /* have we been initialised? */ CPUState *c_cpu; /* current CPU for everything */ @@ -506,6 +537,16 @@ void handle_close_core(GArray *params, void *user_ctx); */ void handle_open_server(GArray *params, void *user_ctx); +/** + * 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. + */ +void handle_query_state(GArray *params, void *user_ctx); + /* helpers */ /** diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index ca98d01ee7..657f80d2a2 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -95,6 +95,15 @@ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) mcd_query_cmds_table[cmd_number] = query_cores; cmd_number++; + + MCDCmdParseEntry query_state = { + .handler = handle_query_state, + .cmd = QUERY_ARG_STATE, + }; + strcpy(query_state.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_state; +} + void reset_mcdserver_state(void) { g_free(mcdserver_state.processes); @@ -605,6 +614,100 @@ void mcd_sigterm_handler(int signal) } #endif +void mcd_vm_state_change(void *opaque, bool running, RunState state) +{ + CPUState *cpu = mcdserver_state.c_cpu; + + if (mcdserver_state.state == RS_INACTIVE) { + return; + } + + if (cpu == NULL) { + if (running) { + /* + * this is the case if qemu starts the vm + * before a mcd client is connected + */ + const char *mcd_state; + mcd_state = CORE_STATE_RUNNING; + const char *info_str; + info_str = STATE_STR_INIT_RUNNING; + mcdserver_state.cpu_state.state = mcd_state; + mcdserver_state.cpu_state.info_str = info_str; + } + return; + } + + const char *mcd_state; + const char *stop_str; + const char *info_str; + uint32_t bp_type = 0; + uint64_t bp_address = 0; + switch (state) { + case RUN_STATE_RUNNING: + mcd_state = CORE_STATE_RUNNING; + info_str = STATE_STR_RUNNING(cpu->cpu_index); + stop_str = ""; + break; + case RUN_STATE_DEBUG: + mcd_state = CORE_STATE_DEBUG; + info_str = STATE_STR_DEBUG(cpu->cpu_index); + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { + case BP_MEM_READ: + bp_type = MCD_BREAKPOINT_READ; + stop_str = STATE_STR_BREAK_READ(cpu->watchpoint_hit->hitaddr); + break; + case BP_MEM_WRITE: + bp_type = MCD_BREAKPOINT_WRITE; + stop_str = STATE_STR_BREAK_WRITE(cpu->watchpoint_hit->hitaddr); + break; + case BP_MEM_ACCESS: + bp_type = MCD_BREAKPOINT_RW; + stop_str = STATE_STR_BREAK_RW(cpu->watchpoint_hit->hitaddr); + break; + default: + stop_str = STATE_STR_BREAK_UNKNOWN; + break; + } + bp_address = cpu->watchpoint_hit->hitaddr; + cpu->watchpoint_hit = NULL; + } else if (cpu->singlestep_enabled) { + /* we land here when a single step is performed */ + stop_str = STATE_STEP_PERFORMED; + } else { + bp_type = MCD_BREAKPOINT_HW; + stop_str = STATE_STR_BREAK_HW; + tb_flush(cpu); + } + /* deactivate single step */ + cpu_single_step(cpu, 0); + break; + case RUN_STATE_PAUSED: + info_str = STATE_STR_HALTED(cpu->cpu_index); + mcd_state = CORE_STATE_HALTED; + stop_str = ""; + break; + case RUN_STATE_WATCHDOG: + info_str = STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state = CORE_STATE_UNKNOWN; + stop_str = ""; + break; + default: + info_str = STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state = CORE_STATE_UNKNOWN; + stop_str = ""; + break; + } + + /* set state for c_cpu */ + mcdserver_state.cpu_state.state = mcd_state; + mcdserver_state.cpu_state.bp_type = bp_type; + mcdserver_state.cpu_state.bp_address = bp_address; + mcdserver_state.cpu_state.stop_str = stop_str; + mcdserver_state.cpu_state.info_str = info_str; +} + int mcd_put_packet(const char *buf) { return mcd_put_packet_binary(buf, strlen(buf)); From patchwork Tue Nov 7 13:03:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448623 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4A2D8C4332F for ; Tue, 7 Nov 2023 13:09:06 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlX-0000uC-RP; Tue, 07 Nov 2023 08:05:12 -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 1r0Lkg-0008GO-M2 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:24 -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 1r0LkO-0005z4-I7 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:16 -0500 Received: (qmail 31250 invoked by uid 484); 7 Nov 2023 13:03:58 -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.071896 secs); 07 Nov 2023 13:03:58 -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 Nov 2023 13:03:56 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 11/20] mcdstub: reset and trigger queries added Date: Tue, 7 Nov 2023 14:03:14 +0100 Message-Id: <20231107130323.4126-12-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 25 ++++++++++++++ mcdstub/mcdstub.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index eb46917d00..62394e7c12 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -507,6 +507,23 @@ CPUState *find_cpu(uint32_t thread_id); */ void handle_open_core(GArray *params, void *user_ctx); +/** + * 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. + */ +void handle_query_reset_f(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_query_reset_c(GArray *params, void *user_ctx); + /** * handle_close_server() - Handler for closing the MCD server. * @@ -525,6 +542,14 @@ void handle_close_server(GArray *params, void *user_ctx); */ void handle_close_core(GArray *params, void *user_ctx); +/** + * handle_query_trigger() - Handler for trigger query. + * + * Sends data on the different types of trigger and their options and actions. + * @params: GArray with all TCP packet parameters. + */ +void handle_query_trigger(GArray *params, void *user_ctx); + /** * handle_open_server() - Handler for opening the MCD server. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 657f80d2a2..d71dff633a 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -95,6 +95,27 @@ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) mcd_query_cmds_table[cmd_number] = query_cores; cmd_number++; + MCDCmdParseEntry query_reset_f = { + .handler = handle_query_reset_f, + .cmd = QUERY_ARG_RESET QUERY_FIRST, + }; + mcd_query_cmds_table[cmd_number] = query_reset_f; + cmd_number++; + + MCDCmdParseEntry query_reset_c = { + .handler = handle_query_reset_c, + .cmd = QUERY_ARG_RESET QUERY_CONSEQUTIVE, + }; + strcpy(query_reset_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reset_c; + cmd_number++; + + MCDCmdParseEntry query_trigger = { + .handler = handle_query_trigger, + .cmd = QUERY_ARG_TRIGGER, + }; + mcd_query_cmds_table[cmd_number] = query_trigger; + cmd_number++; MCDCmdParseEntry query_state = { .handler = handle_query_state, @@ -1001,6 +1022,44 @@ void handle_open_core(GArray *params, void *user_ctx) } } +void handle_query_reset_f(GArray *params, void *user_ctx) +{ + /* 1. check length */ + int nb_resets = mcdserver_state.resets->len; + if (nb_resets == 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 = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); +} + +void handle_query_reset_c(GArray *params, void *user_ctx) +{ + /* reset options are the same for every cpu! */ + uint32_t query_index = get_param(params, 0)->query_handle; + + /* 1. check weather this was the last mem space */ + int nb_groups = mcdserver_state.resets->len; + if (query_index + 1 == 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 = g_array_index(mcdserver_state.resets, + mcd_reset_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); +} void handle_close_core(GArray *params, void *user_ctx) { @@ -1047,3 +1106,13 @@ void handle_close_server(GArray *params, void *user_ctx) } } +void handle_query_trigger(GArray *params, void *user_ctx) +{ + mcd_trigger_into_st trigger = mcdserver_state.trigger; + g_string_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.%s=%s.%s=%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(); +} From patchwork Tue Nov 7 13:03:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448603 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0571AC4332F for ; Tue, 7 Nov 2023 13:06:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lm9-0001qM-Gj; Tue, 07 Nov 2023 08:05:53 -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 1r0Lko-0008KI-LT for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:28 -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 1r0Lkg-000602-DK for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:25 -0500 Received: (qmail 31271 invoked by uid 484); 7 Nov 2023 13:04:01 -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.071439 secs); 07 Nov 2023 13: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 Nov 2023 13:03:59 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 12/20] mcdstub: missing parse_reg_xml function for parsing gdb register xml files added Date: Tue, 7 Nov 2023 14:03:15 +0100 Message-Id: <20231107130323.4126-13-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- mcdstub/mcdstub.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index d71dff633a..3e87378b45 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -867,6 +867,127 @@ CPUState *find_cpu(uint32_t thread_id) } +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 = reg_id_offset; + uint32_t internal_id; + int still_to_skip = 0; + char argument[64] = {0}; + char value[64] = {0}; + bool is_reg = false; + bool is_argument = false; + bool is_value = false; + GArray *reg_data; + + char c; + char *c_ptr; + + xml_attrib attribute_j; + const char *argument_j; + const char *value_j; + + for (i = 0; i < size; i++) { + c = xml[i]; + c_ptr = &c; + + if (still_to_skip > 0) { + /* skip unwanted chars */ + still_to_skip--; + continue; + } + + if (strncmp(&xml[i], "", 2) == 0) { + /* end of register info */ + still_to_skip = 1; + is_reg = false; + + /* create empty register */ + mcd_reg_st my_register = (const struct mcd_reg_st){ 0 }; + + /* add found attribtues */ + for (j = 0; j < reg_data->len; j++) { + attribute_j = g_array_index(reg_data, xml_attrib, j); + + argument_j = attribute_j.argument; + value_j = attribute_j.value; + + if (strcmp(argument_j, "name") == 0) { + strcpy(my_register.name, value_j); + } else if (strcmp(argument_j, "regnum") == 0) { + my_register.id = atoi(value_j); + } else if (strcmp(argument_j, "bitsize") == 0) { + my_register.bitsize = atoi(value_j); + } else if (strcmp(argument_j, "type") == 0) { + strcpy(my_register.type, value_j); + } else if (strcmp(argument_j, "group") == 0) { + strcpy(my_register.group, value_j); + } + } + /* add reg_type, internal_id and id*/ + my_register.reg_type = reg_type; + my_register.internal_id = internal_id; + internal_id++; + if (!my_register.id) { + my_register.id = current_reg_id; + current_reg_id++; + } else { + /* set correct ID for the next register */ + current_reg_id = 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 '=': + is_argument = false; + break; + case '"': + if (is_value) { + /* end of value reached */ + is_value = 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 = true; + } + break; + default: + if (is_argument) { + strncat(argument, c_ptr, 1); + } else if (is_value) { + strncat(value, c_ptr, 1); + } else { + is_argument = true; + strncat(argument, c_ptr, 1); + } + break; + } + } + } + } +} + int int_cmp(gconstpointer a, gconstpointer b) { int int_a = *(int *)a; From patchwork Tue Nov 7 13:03:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448602 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4A42CC4167D for ; Tue, 7 Nov 2023 13:05:22 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlR-0000kT-Iq; Tue, 07 Nov 2023 08:05:07 -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 1r0Lkr-0008QN-Ni for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lko-00060g-Gt for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:29 -0500 Received: (qmail 31306 invoked by uid 484); 7 Nov 2023 13: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 1.6e-05 secs); 07 Nov 2023 13: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 Nov 2023 13:04:01 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 13/20] mcdstub: added queries for memory spaces, register groups and registers Date: Tue, 7 Nov 2023 14:03:16 +0100 Message-Id: <20231107130323.4126-14-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 57 ++++++++++ mcdstub/mcdstub.c | 229 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 62394e7c12..85ca8b3b62 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -550,6 +550,63 @@ void handle_close_core(GArray *params, void *user_ctx); */ void handle_query_trigger(GArray *params, void *user_ctx); +/** + * handle_query_reg_groups_f() - Handler for the first register group query. + * + * This function sends the first register group name and ID. + * @params: GArray with all TCP packet parameters. + */ +void handle_query_reg_groups_f(GArray *params, void *user_ctx); + +/** + * handle_query_reg_groups_c() - Handler for all consecutive register group + * queries. + * + * This function sends all consecutive register group names and IDs. It uses + * the query_index parameter to determine which register group is queried next. + * @params: GArray with all TCP packet parameters. + */ +void handle_query_reg_groups_c(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_query_mem_spaces_f(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_query_mem_spaces_c(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_query_regs_f(GArray *params, void *user_ctx); + +/** + * handle_query_regs_c() - Handler for all consecutive register queries. + * + * This function sends all consecutive registers with all their information. + * It uses the query_index parameter to determine + * which register is queried next. + * @params: GArray with all TCP packet parameters. + */ +void handle_query_regs_c(GArray *params, void *user_ctx); + /** * handle_open_server() - Handler for opening the MCD server. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 3e87378b45..56854c4c76 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -117,6 +117,54 @@ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) mcd_query_cmds_table[cmd_number] = query_trigger; cmd_number++; + MCDCmdParseEntry query_mem_spaces_f = { + .handler = handle_query_mem_spaces_f, + .cmd = QUERY_ARG_MEMORY QUERY_FIRST, + }; + strcpy(query_mem_spaces_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_mem_spaces_f; + cmd_number++; + + MCDCmdParseEntry query_mem_spaces_c = { + .handler = handle_query_mem_spaces_c, + .cmd = QUERY_ARG_MEMORY QUERY_CONSEQUTIVE, + }; + strcpy(query_mem_spaces_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_mem_spaces_c; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_f = { + .handler = handle_query_reg_groups_f, + .cmd = QUERY_ARG_REGGROUP QUERY_FIRST, + }; + strcpy(query_reg_groups_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reg_groups_f; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_c = { + .handler = handle_query_reg_groups_c, + .cmd = QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE, + }; + strcpy(query_reg_groups_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reg_groups_c; + cmd_number++; + + MCDCmdParseEntry query_regs_f = { + .handler = handle_query_regs_f, + .cmd = QUERY_ARG_REG QUERY_FIRST, + }; + strcpy(query_regs_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_regs_f; + cmd_number++; + + MCDCmdParseEntry query_regs_c = { + .handler = handle_query_regs_c, + .cmd = QUERY_ARG_REG QUERY_CONSEQUTIVE, + }; + strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_regs_c; + cmd_number++; + MCDCmdParseEntry query_state = { .handler = handle_query_state, .cmd = QUERY_ARG_STATE, @@ -1237,3 +1285,184 @@ void handle_query_trigger(GArray *params, void *user_ctx) TCP_ARGUMENT_ACTION, trigger.action); mcd_put_strbuf(); } + +void handle_query_mem_spaces_f(GArray *params, void *user_ctx) +{ + /* 1. get correct memspaces and set the query_cpu */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + + /* 2. check length */ + int nb_groups = memspaces->len; + if (nb_groups == 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 = g_array_index(memspaces, mcd_mem_space_st, 0); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%ld.%s=%ld.%s=%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_options); + mcd_put_strbuf(); +} + +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 = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + + /* 2. check weather this was the last mem space */ + int nb_groups = memspaces->len; + if (query_index + 1 == 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 = g_array_index(memspaces, + mcd_mem_space_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%ld.%s=%ld.%s=%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_options); + mcd_put_strbuf(); +} + +void handle_query_reg_groups_f(GArray *params, void *user_ctx) +{ + /* 1. get correct reggroups and set the query_cpu */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + + /* 2. check length */ + int nb_groups = reggroups->len; + if (nb_groups == 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 = g_array_index(reggroups, mcd_reg_group_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + mcd_put_strbuf(); +} + +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 = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + + /* 2. check weather this was the last reg group */ + int nb_groups = reggroups->len; + if (query_index + 1 == 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 = g_array_index(reggroups, mcd_reg_group_st, + query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + mcd_put_strbuf(); +} + +void handle_query_regs_f(GArray *params, void *user_ctx) +{ + /* 1. get correct registers and set the query_cpu */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + + /* 2. check length */ + int nb_regs = registers->len; + if (nb_regs == 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 = g_array_index(registers, mcd_reg_st, 0); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%u.%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%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(); +} + +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 = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + + /* 2. check weather this was the last register */ + int nb_regs = registers->len; + if (query_index + 1 == 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 = g_array_index(registers, mcd_reg_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%u.%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%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(); +} From patchwork Tue Nov 7 13:03:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448618 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 139C4C4332F for ; Tue, 7 Nov 2023 13:07:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmh-0002NH-GT; Tue, 07 Nov 2023 08:06:23 -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 1r0Ll2-00009L-5K for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lkr-00061B-V0 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:33 -0500 Received: (qmail 31355 invoked by uid 484); 7 Nov 2023 13:04:06 -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.16659 secs); 07 Nov 2023 13:04:06 -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 Nov 2023 13:04:04 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 14/20] mcdstub: missing handle_query_state function added Date: Tue, 7 Nov 2023 14:03:17 +0100 Message-Id: <20231107130323.4126-15-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- mcdstub/mcdstub.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 56854c4c76..cd2f5db8e4 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -1466,3 +1466,32 @@ void handle_query_regs_c(GArray *params, void *user_ctx) TCP_ARGUMENT_OPCODE, my_register.opcode); mcd_put_strbuf(); } + +void handle_query_state(GArray *params, void *user_ctx) +{ + /* + * TODO: multicore support + * get state info + */ + mcd_cpu_state_st state_info = mcdserver_state.cpu_state; + /* TODO: add event information */ + uint32_t event = 0; + /* send data */ + g_string_printf(mcdserver_state.str_buf, + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%lu.%s=%s.%s=%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) == 0) { + mcdserver_state.cpu_state.stop_str = ""; + mcdserver_state.cpu_state.info_str = ""; + mcdserver_state.cpu_state.bp_type = 0; + mcdserver_state.cpu_state.bp_address = 0; + } +} From patchwork Tue Nov 7 13:03:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448626 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F1D5DC4332F for ; Tue, 7 Nov 2023 13:09:47 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmx-0002pb-BD; Tue, 07 Nov 2023 08:06:39 -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 1r0Ll2-00009H-3G for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lkr-00061V-QS for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:34 -0500 Received: (qmail 31401 invoked by uid 484); 7 Nov 2023 13: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 0.316025 secs); 07 Nov 2023 13: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 Nov 2023 13:04:07 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 15/20] mcdstub: added go, break and step functionality and all corresponding functions Date: Tue, 7 Nov 2023 14:03:18 +0100 Message-Id: <20231107130323.4126-16-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 53 ++++++++++++++++++++ mcdstub/mcdstub.c | 101 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 85ca8b3b62..0375cf7311 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -439,6 +439,33 @@ int process_string_cmd(void *user_ctx, const char *data, */ int cmd_parse_params(const char *data, const char *schema, GArray *params); +/** + * handle_vm_start() - Handler for the VM start TCP packet. + * + * Evaluates whether all cores or just a perticular core should get started and + * calls :c:func:`mcd_vm_start` or :c:func:`mcd_cpu_start` respectively. + * @params: GArray with all TCP packet parameters. + */ +void handle_vm_start(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_vm_step(GArray *params, void *user_ctx); + +/** + * handle_vm_stop() - Handler for the VM stop TCP packet. + * + * Always calls :c:func:`mcd_vm_stop` and stops all cores. Stopping individual + * cores is currently not supported. + * @params: GArray with all TCP packet parameters. + */ +void handle_vm_stop(GArray *params, void *user_ctx); + /** * handle_gen_query() - Handler for all TCP query packets. * @@ -550,6 +577,32 @@ void handle_close_core(GArray *params, void *user_ctx); */ void handle_query_trigger(GArray *params, void *user_ctx); +/** + * mcd_vm_start() - Starts all CPUs with the vm_start function. + */ +void mcd_vm_start(void); + +/** + * mcd_cpu_start() - Starts the selected CPU with the cpu_resume function. + * + * @cpu: The CPU about to be started. + */ +void mcd_cpu_start(CPUState *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. + */ +int mcd_cpu_sstep(CPUState *cpu); + +/** + * mcd_vm_stop() - Brings all CPUs in debug state with the vm_stop function. + */ +void mcd_vm_stop(void); + /** * handle_query_reg_groups_f() - Handler for the first register group query. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index cd2f5db8e4..6313459bac 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -432,6 +432,37 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &open_server_cmd_desc; } break; + case TCP_CHAR_GO: + { + static MCDCmdParseEntry go_cmd_desc = { + .handler = handle_vm_start, + }; + go_cmd_desc.cmd = (char[2]) { TCP_CHAR_GO, '\0' }; + strcpy(go_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &go_cmd_desc; + } + break; + case TCP_CHAR_STEP: + { + static MCDCmdParseEntry step_cmd_desc = { + .handler = handle_vm_step, + }; + step_cmd_desc.cmd = (char[2]) { TCP_CHAR_STEP, '\0' }; + strcpy(step_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &step_cmd_desc; + } + break; + case TCP_CHAR_BREAK: + { + static MCDCmdParseEntry break_cmd_desc = { + .handler = handle_vm_stop, + }; + break_cmd_desc.cmd = (char[2]) { TCP_CHAR_BREAK, '\0' }; + cmd_parser = &break_cmd_desc; + } + break; case TCP_CHAR_KILLQEMU: /* kill qemu completely */ error_report("QEMU: Terminated via MCDstub"); @@ -494,6 +525,40 @@ int mcd_handle_packet(const char *line_buf) return RS_IDLE; } +void handle_vm_start(GArray *params, void *user_ctx) +{ + uint32_t global = get_param(params, 0)->data_uint32_t; + if (global == 1) { + mcd_vm_start(); + } else{ + uint32_t cpu_id = get_param(params, 1)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_cpu_start(cpu); + } +} + +void handle_vm_step(GArray *params, void *user_ctx) +{ + uint32_t global = get_param(params, 0)->data_uint32_t; + if (global == 1) { + /* TODO: add multicore support */ + } else{ + uint32_t cpu_id = get_param(params, 1)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + int return_value = mcd_cpu_sstep(cpu); + if (return_value != 0) { + g_assert_not_reached(); + } + } +} + + +void handle_vm_stop(GArray *params, void *user_ctx) +{ + /* TODO: add core dependant break option */ + mcd_vm_stop(); +} + void handle_gen_query(GArray *params, void *user_ctx) { if (!params->len) { @@ -1286,6 +1351,42 @@ void handle_query_trigger(GArray *params, void *user_ctx) mcd_put_strbuf(); } +void mcd_vm_start(void) +{ + if (!runstate_needs_reset() && !runstate_is_running()) { + vm_start(); + } +} + +void mcd_cpu_start(CPUState *cpu) +{ + if (!runstate_needs_reset() && !runstate_is_running() && + !vm_prepare_start(false)) { + mcdserver_state.c_cpu = cpu; + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + cpu_resume(cpu); + } +} + +int mcd_cpu_sstep(CPUState *cpu) +{ + mcdserver_state.c_cpu = 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; +} + +void mcd_vm_stop(void) +{ + if (runstate_is_running()) { + vm_stop(RUN_STATE_DEBUG); + } +} + void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { /* 1. get correct memspaces and set the query_cpu */ From patchwork Tue Nov 7 13:03:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448625 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 68E9EC4332F for ; Tue, 7 Nov 2023 13:09:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmq-0002fS-UE; Tue, 07 Nov 2023 08:06: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 1r0Ll2-00009J-3u for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lkr-00062I-Qr for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:33 -0500 Received: (qmail 31443 invoked by uid 484); 7 Nov 2023 13:04:12 -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.093115 secs); 07 Nov 2023 13:04:12 -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 Nov 2023 13:04:10 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 16/20] mcdstub: function construct for resets added Date: Tue, 7 Nov 2023 14:03:19 +0100 Message-Id: <20231107130323.4126-17-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 8 ++++++++ mcdstub/mcdstub.c | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 0375cf7311..000d832a39 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -672,6 +672,14 @@ void handle_query_regs_c(GArray *params, void *user_ctx); */ void handle_open_server(GArray *params, void *user_ctx); +/** + * handle_reset() - Handler for performing resets. + * + * This function is currently not in use. + * @params: GArray with all TCP packet parameters. + */ +void handle_reset(GArray *params, void *user_ctx); + /** * handle_query_state() - Handler for the state query. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 6313459bac..1a10bc6c98 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -511,6 +511,16 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &close_core_cmd_desc; } break; + case TCP_CHAR_RESET: + { + static MCDCmdParseEntry reset_cmd_desc = { + .handler = handle_reset, + }; + reset_cmd_desc.cmd = (char[2]) { TCP_CHAR_RESET, '\0' }; + strcpy(reset_cmd_desc.schema, (char[2]) { ARG_SCHEMA_INT, '\0' }); + cmd_parser = &reset_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -1568,6 +1578,14 @@ void handle_query_regs_c(GArray *params, void *user_ctx) mcd_put_strbuf(); } +void handle_reset(GArray *params, void *user_ctx) +{ + /* + * int reset_id = get_param(params, 0)->data_int; + * TODO: implement resets + */ +} + void handle_query_state(GArray *params, void *user_ctx) { /* From patchwork Tue Nov 7 13:03:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448622 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CD69DC4332F for ; Tue, 7 Nov 2023 13:07:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lml-0002UI-1t; Tue, 07 Nov 2023 08:06:27 -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 1r0Lkm-0008Ju-Lh for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:27 -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 1r0Lkg-00062M-Hq for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:24 -0500 Received: (qmail 31470 invoked by uid 484); 7 Nov 2023 13: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.244438 secs); 07 Nov 2023 13: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 Nov 2023 13:04:13 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 17/20] mcdstub: reading/writing registers added Date: Tue, 7 Nov 2023 14:03:20 +0100 Message-Id: <20231107130323.4126-18-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 62 +++++++++++++++++++++ mcdstub/mcdstub.c | 113 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 000d832a39..6b2249f8fb 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -690,6 +690,49 @@ void handle_reset(GArray *params, void *user_ctx); */ void handle_query_state(GArray *params, void *user_ctx); +/** + * 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. + */ +void handle_read_register(GArray *params, void *user_ctx); + +/** + * handle_write_register() - Handler for writing a register. + * + * This function converts the incoming hex string data into a byte array with + * :c:func:`mcd_hextomem`. Then it calls :c:func:`mcd_write_register` to write + * to the register. + * @params: GArray with all TCP packet parameters. + */ +void handle_write_register(GArray *params, void *user_ctx); +/** + * 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. + */ +int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); + +/** + * 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. + */ +int mcd_write_register(CPUState *cpu, uint8_t *mem_buf, int reg); + /* helpers */ /** @@ -699,6 +742,25 @@ void handle_query_state(GArray *params, void *user_ctx); * @b: Pointer to integer b. */ int int_cmp(gconstpointer a, gconstpointer b); + +/** + * mcd_memtohex() - Converts a byte array into a hex string. + * + * @mem: Pointer to byte array. + * @buf: Pointer to hex string. + * @len: Number of bytes. + */ +void mcd_memtohex(GString *buf, const uint8_t *mem, int len); + +/** + * mcd_hextomem() - Converts a hex string into a byte array. + * + * @mem: Pointer to byte array. + * @buf: Pointer to hex string. + * @len: Number of bytes. + */ +void mcd_hextomem(GByteArray *mem, const char *buf, int len); + /** * atouint64_t() - Converts a string into a unsigned 64 bit integer. * diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 1a10bc6c98..018900e914 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -521,6 +521,30 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &reset_cmd_desc; } break; + case TCP_CHAR_READ_REGISTER: + { + static MCDCmdParseEntry read_reg_cmd_desc = { + .handler = handle_read_register, + }; + read_reg_cmd_desc.cmd = (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 = &read_reg_cmd_desc; + } + break; + case TCP_CHAR_WRITE_REGISTER: + { + static MCDCmdParseEntry write_reg_cmd_desc = { + .handler = handle_write_register, + }; + write_reg_cmd_desc.cmd = + (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 = &write_reg_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -1614,3 +1638,92 @@ void handle_query_state(GArray *params, void *user_ctx) mcdserver_state.cpu_state.bp_address = 0; } } + +int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + CPUArchState *env = cpu_env(cpu); + GDBRegisterState *r; + + if (reg < cc->gdb_num_core_regs) { + return cc->gdb_read_register(cpu, buf, reg); + } + + for (guint i = 0; i < cpu->gdb_regs->len; i++) { + r = &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) { + return r->get_reg(env, buf, reg - r->base_reg); + } + } + return 0; +} + +int mcd_write_register(CPUState *cpu, uint8_t *mem_buf, int reg) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + CPUArchState *env = cpu_env(cpu); + GDBRegisterState *r; + + if (reg < cc->gdb_num_core_regs) { + return cc->gdb_write_register(cpu, mem_buf, reg); + } + + for (guint i = 0; i < cpu->gdb_regs->len; i++) { + r = &g_array_index(cpu->gdb_regs, GDBRegisterState, i); + if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) { + return r->set_reg(env, mem_buf, reg - r->base_reg); + } + } + return 0; +} + +void mcd_memtohex(GString *buf, const uint8_t *mem, int len) +{ + int i, c; + for (i = 0; i < len; i++) { + c = mem[i]; + g_string_append_c(buf, tohex(c >> 4)); + g_string_append_c(buf, tohex(c & 0xf)); + } + g_string_append_c(buf, '\0'); +} + +void mcd_hextomem(GByteArray *mem, const char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]); + g_byte_array_append(mem, &byte, 1); + buf += 2; + } +} + +void handle_read_register(GArray *params, void *user_ctx) +{ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint64_t reg_num = get_param(params, 1)->data_uint64_t; + int reg_size; + + CPUState *cpu = mcd_get_cpu(cpu_id); + reg_size = 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(); +} + +void handle_write_register(GArray *params, void *user_ctx) +{ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint64_t reg_num = get_param(params, 1)->data_uint64_t; + uint32_t reg_size = get_param(params, 2)->data_uint32_t; + + CPUState *cpu = 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) == 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} From patchwork Tue Nov 7 13:03:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448601 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 48478C4708E for ; Tue, 7 Nov 2023 13:05:14 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlG-0000OQ-Ow; Tue, 07 Nov 2023 08:04:55 -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 1r0Ll2-00009I-3Q for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08: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 1r0Lkr-00062c-V0 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:32 -0500 Received: (qmail 31491 invoked by uid 484); 7 Nov 2023 13: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 0.125942 secs); 07 Nov 2023 13:04:16 -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 Nov 2023 13:04:15 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 18/20] mcdstub: read/write to memory added: This also includes various helper functions in the QEMU memory code Date: Tue, 7 Nov 2023 14:03:21 +0100 Message-Id: <20231107130323.4126-19-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/exec/cpu-common.h | 2 + include/exec/memory.h | 9 ++ include/mcdstub/arm_mcdstub.h | 16 ++++ include/mcdstub/mcdstub.h | 69 +++++++++++++++ mcdstub/mcdstub.c | 153 ++++++++++++++++++++++++++++++++++ system/memory.c | 11 +++ system/physmem.c | 26 ++++++ target/arm/mcdstub.c | 26 ++++++ 8 files changed, 312 insertions(+) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 30c376a4de..86b3176de5 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -185,6 +185,8 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length); int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, void *ptr, size_t len, bool is_write); +int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *len); + /* vl.c */ void list_cpus(void); diff --git a/include/exec/memory.h b/include/exec/memory.h index 9087d02769..ff8642d883 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -3110,6 +3110,15 @@ bool ram_block_discard_is_disabled(void); */ bool ram_block_discard_is_required(void); +/* + * mcd_find_address_space() - Find the address spaces with the corresponding + * name. + * + * Currently only used by the mcd debugger. + * @as_name: Name to look for. + */ +AddressSpace *mcd_find_address_space(const char *as_name); + #endif #endif diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h index c71f6c3356..fb9abaaf7d 100644 --- a/include/mcdstub/arm_mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -87,5 +87,21 @@ int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups, * @cpu: The CPU state. */ int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu); + +/** + * arm_mcd_get_address_space() - Returnes the correct QEMU address space name + * @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 access + * attributes + * @mem_space: Desired mcd specific memory space. + */ +MemTxAttrs arm_mcd_get_memtxattrs(mcd_mem_space_st mem_space); #endif /* ARM_MCDSTUB_H */ diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 6b2249f8fb..c55d52d2a7 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -709,6 +709,31 @@ void handle_read_register(GArray *params, void *user_ctx); * @params: GArray with all TCP packet parameters. */ void handle_write_register(GArray *params, void *user_ctx); + +/** + * 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. + */ +void handle_read_memory(GArray *params, void *user_ctx); + +/** + * 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 write to + * the register. + * @params: GArray with all TCP packet parameters. + */ +void handle_write_memory(GArray *params, void *user_ctx); + /** * mcd_read_register() - Reads a registers data and stores it into the buf. * @@ -733,6 +758,50 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); */ int mcd_write_register(CPUState *cpu, uint8_t *mem_buf, int reg); +/** + * 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 + */ +int mcd_read_write_physical_memory(AddressSpace *address_space, + MemTxAttrs attributes, hwaddr addr, uint8_t *buf, int len, bool is_write); + +/** + * mcd_read_write_memory() - Reades or writes from/to a logical memory address. + * @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 + */ +int mcd_read_write_memory(CPUState *cpu, AddressSpace *address_space, + MemTxAttrs attributes, vaddr addr, uint8_t *buf, uint64_t len, + bool 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. + */ +AddressSpace *mcd_get_address_space(CPUState *cpu, uint32_t cpu_id, + mcd_mem_space_st mem_space); + +/** + * mcd_get_memtxattrs() - Returnes the correct QEMU address space access + * attributes + * @cpu: CPUState + * @mem_space: Desired mcd specific memory space. + */ +MemTxAttrs mcd_get_memtxattrs(CPUState *cpu, mcd_mem_space_st mem_space); + /* helpers */ /** diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 018900e914..8dc1e6a71d 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -545,6 +545,31 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &write_reg_cmd_desc; } break; + case TCP_CHAR_READ_MEMORY: + { + static MCDCmdParseEntry read_mem_cmd_desc = { + .handler = handle_read_memory, + }; + read_mem_cmd_desc.cmd = (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 = &read_mem_cmd_desc; + } + break; + case TCP_CHAR_WRITE_MEMORY: + { + static MCDCmdParseEntry write_mem_cmd_desc = { + .handler = handle_write_memory, + }; + write_mem_cmd_desc.cmd = (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 = &write_mem_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -1727,3 +1752,131 @@ void handle_write_register(GArray *params, void *user_ctx) mcd_put_packet(TCP_EXECUTION_SUCCESS); } } + +int mcd_read_write_physical_memory(AddressSpace *address_space, + MemTxAttrs attributes, hwaddr addr, uint8_t *buf, int len, bool is_write) +{ + if (is_write) { + return address_space_write_rom(address_space, addr, attributes, buf, + len); + } else { + return address_space_read_full(address_space, addr, attributes, buf, + len); + } +} + +int mcd_read_write_memory(CPUState *cpu, AddressSpace *address_space, + 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) != 0) { + return -1; + } + /* read memory */ + return mcd_read_write_physical_memory(address_space, attributes, addr, buf, + len, is_write); +} + +AddressSpace *mcd_get_address_space(CPUState *cpu, uint32_t cpu_id, + mcd_mem_space_st mem_space) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + const gchar *arch = cc->gdb_arch_name(cpu); + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { + return arm_mcd_get_address_space(cpu_id, mem_space); + } else { + g_assert_not_reached(); + } +} + +MemTxAttrs mcd_get_memtxattrs(CPUState *cpu, mcd_mem_space_st mem_space) +{ + CPUClass *cc = CPU_GET_CLASS(cpu); + const gchar *arch = cc->gdb_arch_name(cpu); + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { + return arm_mcd_get_memtxattrs(mem_space); + } else { + g_assert_not_reached(); + } +} + +void handle_read_memory(GArray *params, void *user_ctx) +{ + /* read input parameters */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + uint64_t mem_address = get_param(params, 2)->data_uint64_t; + uint32_t len = get_param(params, 3)->data_uint32_t; + /* check which memory space was requested */ + CPUState *cpu = mcd_get_cpu(cpu_id); + GArray *memspaces = + g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space = 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 = mcd_get_address_space(cpu, cpu_id, space); + MemTxAttrs attributes = 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) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } else { + /* user space memory */ + if (mcd_read_write_memory(cpu, address_space, attributes, mem_address, + mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len, + false) != 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(); +} + +void handle_write_memory(GArray *params, void *user_ctx) +{ + /* read input parameters */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + uint64_t mem_address = get_param(params, 2)->data_uint64_t; + uint32_t len = get_param(params, 3)->data_uint32_t; + /* check which memory space was requested */ + CPUState *cpu = mcd_get_cpu(cpu_id); + GArray *memspaces = + g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space = 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 = mcd_get_address_space(cpu, cpu_id, space); + MemTxAttrs attributes = mcd_get_memtxattrs(cpu, space); + /* write memory data */ + mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, 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, true) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } else { + /* user space memory */ + if (mcd_read_write_memory(cpu, address_space, attributes, mem_address, + mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len, + true) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + } + /* send acknowledge */ + mcd_put_packet(TCP_EXECUTION_SUCCESS); +} diff --git a/system/memory.c b/system/memory.c index 4928f2525d..bb3d2067c4 100644 --- a/system/memory.c +++ b/system/memory.c @@ -3577,6 +3577,17 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) } } +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) == 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 fc2b0fee01..60c15546f8 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -3400,6 +3400,32 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, return 0; } +int cpu_memory_get_physical_address(CPUState *cpu, vaddr *addr, size_t *len) +{ + hwaddr phys_addr; + vaddr l, page; + + cpu_synchronize_state(cpu); + MemTxAttrs attrs; + + page = *addr & TARGET_PAGE_MASK; + phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, &attrs); + /* if no physical page mapped, return an error */ + if (phys_addr == -1) { + return -1; + } + l = (page + TARGET_PAGE_SIZE) - *addr; + if (l > *len) { + l = *len; + } + phys_addr += (*addr & ~TARGET_PAGE_MASK); + + /* set output values */ + *addr = phys_addr; + *len = l; + return 0; +} + /* * Allows code that needs to deal with migration bitmaps etc to still be built * target independent. diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index ff1350831b..c87e0e4784 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -276,3 +276,29 @@ int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, 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] = {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 = mcd_find_address_space(as_name); + return as; +} + +MemTxAttrs arm_mcd_get_memtxattrs(mcd_mem_space_st mem_space) +{ + MemTxAttrs attributes = {0}; + if (mem_space.is_secure) { + attributes.secure = 1; + attributes.space = 2; + } else { + attributes.space = 1; + } + return attributes; +} From patchwork Tue Nov 7 13:03:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448628 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1A2D2C4167B for ; Tue, 7 Nov 2023 13:10:13 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0Lmg-0002KU-VS; Tue, 07 Nov 2023 08:06:23 -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 1r0Ll2-0000Ch-VH for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:43 -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 1r0Lkt-00063P-5t for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:40 -0500 Received: (qmail 31517 invoked by uid 484); 7 Nov 2023 13: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.073339 secs); 07 Nov 2023 13: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 Nov 2023 13:04:16 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 19/20] mcdstub: break/watchpoints added Date: Tue, 7 Nov 2023 14:03:22 +0100 Message-Id: <20231107130323.4126-20-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- include/mcdstub/mcdstub.h | 46 +++++++++++++++ mcdstub/mcdstub.c | 116 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index c55d52d2a7..53e5926ff5 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -785,6 +785,52 @@ int mcd_read_write_memory(CPUState *cpu, AddressSpace *address_space, MemTxAttrs attributes, vaddr addr, uint8_t *buf, uint64_t len, bool is_write); +/** + * handle_breakpoint_insert() - Handler for inserting a break- or watchpoint. + * + * 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. + */ +void handle_breakpoint_insert(GArray *params, void *user_ctx); + +/** + * handle_breakpoint_remove() - Handler for inserting a break- or watchpoint. + * + * 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. + */ +void handle_breakpoint_remove(GArray *params, void *user_ctx); + +/** + * 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. + */ +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr); + +/** + * 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. + */ +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr); + /** * mcd_get_address_space() - Returnes the correct QEMU address space name * @cpu: CPUState diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 8dc1e6a71d..68e9cdf531 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -570,6 +570,32 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &write_mem_cmd_desc; } break; + case TCP_CHAR_BREAKPOINT_INSERT: + { + static MCDCmdParseEntry handle_breakpoint_insert_cmd_desc = { + .handler = handle_breakpoint_insert, + }; + handle_breakpoint_insert_cmd_desc.cmd = + (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 = &handle_breakpoint_insert_cmd_desc; + } + break; + case TCP_CHAR_BREAKPOINT_REMOVE: + { + static MCDCmdParseEntry handle_breakpoint_remove_cmd_desc = { + .handler = handle_breakpoint_remove, + }; + handle_breakpoint_remove_cmd_desc.cmd = + (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 = &handle_breakpoint_remove_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -1880,3 +1906,93 @@ void handle_write_memory(GArray *params, void *user_ctx) /* send acknowledge */ mcd_put_packet(TCP_EXECUTION_SUCCESS); } + +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr) +{ + /* translate the type to known gdb types and function call*/ + int bp_type = 0; + CPUClass *cc = CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + /* bp_type |= BP_STOP_BEFORE_ACCESS; */ + } + int return_value = 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |= BP_GDB | BP_MEM_READ; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |= BP_GDB | BP_MEM_WRITE; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |= BP_GDB | BP_MEM_ACCESS; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + default: + return -ENOSYS; + } +} + +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr) +{ + /* translate the type to known gdb types and function call*/ + int bp_type = 0; + CPUClass *cc = CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + /* bp_type |= BP_STOP_BEFORE_ACCESS; */ + } + int return_value = 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value = cpu_breakpoint_remove(cpu, addr, BP_GDB); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |= BP_GDB | BP_MEM_READ; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |= BP_GDB | BP_MEM_WRITE; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |= BP_GDB | BP_MEM_ACCESS; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + default: + return -ENOSYS; + } +} + +void handle_breakpoint_insert(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t type = get_param(params, 1)->data_uint32_t; + uint64_t address = get_param(params, 2)->data_uint64_t; + /* 2. insert breakpoint and send reply */ + CPUState *cpu = mcd_get_cpu(cpu_id); + if (mcd_breakpoint_insert(cpu, type, address) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} + +void handle_breakpoint_remove(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t type = get_param(params, 1)->data_uint32_t; + uint64_t address = get_param(params, 2)->data_uint64_t; + /* 2. remove breakpoint and send reply */ + CPUState *cpu = mcd_get_cpu(cpu_id); + if (mcd_breakpoint_remove(cpu, type, address) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} From patchwork Tue Nov 7 13:03:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 13448619 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36F8BC4167D for ; Tue, 7 Nov 2023 13:07:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0LlR-0000kU-If; Tue, 07 Nov 2023 08:05:06 -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 1r0Ll3-0000Ck-Pl for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:43 -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 1r0Lku-00063f-F0 for qemu-devel@nongnu.org; Tue, 07 Nov 2023 08:04:41 -0500 Received: (qmail 31538 invoked by uid 484); 7 Nov 2023 13:04:20 -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.072201 secs); 07 Nov 2023 13:04:20 -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 Nov 2023 13:04:18 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: "Nicolas Eder" , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Philippe_M?= =?utf-8?q?athieu-Daud=C3=A9?= , "Christian Boenig" Subject: [PATCH v3 20/20] mcdstub: updated MAINTAINERS file and fully activated the mcdstub in the meson build system Date: Tue, 7 Nov 2023 14:03:23 +0100 Message-Id: <20231107130323.4126-21-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107130323.4126-1-nicolas.eder@lauterbach.com> References: <20231107130323.4126-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --- MAINTAINERS | 11 +++++++++++ mcdstub/meson.build | 15 +++++++++++++++ meson.build | 1 + target/arm/meson.build | 1 + 4 files changed, 28 insertions(+) create mode 100644 mcdstub/meson.build diff --git a/MAINTAINERS b/MAINTAINERS index cd8d6b140f..58decd218c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2908,6 +2908,17 @@ F: tests/tcg/multiarch/gdbstub/ F: scripts/feature_to_c.py F: scripts/probe-gdb-support.py +MCD stub +M: Nicolas Eder +R: Alex BennĂ©e +S: Maintained +F: mcdstub/* +F: include/mcdstub/* +F: include/qemu/debug.h +F: debug/debug-common.c +F: debug/debug-mcd.c +F: target/arm/mcdstub.c + Memory API M: Paolo Bonzini M: Peter Xu diff --git a/mcdstub/meson.build b/mcdstub/meson.build new file mode 100644 index 0000000000..1f9315f9f5 --- /dev/null +++ b/mcdstub/meson.build @@ -0,0 +1,15 @@ +# only system emulation is supported over mcd +mcd_system_ss = ss.source_set() +mcd_system_ss.add(files('mcdstub.c', '../debug/debug-mcd.c')) +mcd_system_ss = mcd_system_ss.apply(config_host, strict: false) + +libmcd_system = static_library('mcd_system', + mcd_system_ss.sources() + genh, + name_suffix: 'fa', + build_by_default: have_system) + +mcd_system = declare_dependency(link_whole: libmcd_system) +system_ss.add(mcd_system) + +# used for gdb (user/system) and mcd: +common_ss.add(files('../debug/debug-common.c')) diff --git a/meson.build b/meson.build index dcef8b1e79..6dfa49160c 100644 --- a/meson.build +++ b/meson.build @@ -3348,6 +3348,7 @@ subdir('crypto') subdir('ui') subdir('hw') subdir('gdbstub') +subdir('mcdstub') if enable_modules libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') diff --git a/target/arm/meson.build b/target/arm/meson.build index 5d04a8e94f..84fedbc6e1 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -3,6 +3,7 @@ arm_ss.add(files( 'cpu.c', 'debug_helper.c', 'gdbstub.c', + 'mcdstub.c', 'helper.c', 'vfp_helper.c', ))