@@ -2839,6 +2839,9 @@ S: Maintained
F: mcdstub/*
F: include/exec/mcdstub.h
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
new file mode 100644
@@ -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);
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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;
+}
@@ -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', 'softmmu.c'))
+gdb_user_ss.add(files('gdbstub.c', 'user.c', '../debug/debug-gdb.c'))
+gdb_system_ss.add(files('gdbstub.c', 'softmmu.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)
@@ -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;
}
@@ -326,8 +326,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;
}
@@ -51,4 +51,9 @@ bool gdb_has_xml(void);
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
extern const char *const xml_builtin[][2];
+/**
+ * gdb_init_debug_class() - initialize gdb-specific DebugClass
+ */
+void gdb_init_debug_class(void);
+
#endif
@@ -380,6 +380,7 @@ struct MachineState {
CpuTopology smp;
struct NVDIMMState *nvdimms_state;
struct NumaState *numa_state;
+ DebugState *debug_state;
};
#define DEFINE_MACHINE(namestr, machine_initfn) \
@@ -37,14 +37,14 @@ enum {
/**
* \brief Returns the contents of the desired XML file.
- *
+ *
* @param[in] xmlname Name of the desired XML file.
* @param[in] cs CPU state.
*/
const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname);
/**
* \brief Calls the correct read function which writes data into the mem_buf.
- *
+ *
* Depending on the reg_type of the register one of the following functions
* will get called: arm_mcd_read_gpr_register, arm_mcd_read_vfp_register,
* arm_mcd_read_vfp_sys_register, arm_mcd_read_mve_register and
@@ -60,7 +60,7 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type,
uint32_t n);
/**
* \brief Calls the correct write function which writes data from the mem_buf.
- *
+ *
* Depending on the reg_type of the register one of the following functions
* will get called: arm_mcd_write_gpr_register, arm_mcd_write_vfp_register,
* arm_mcd_write_vfp_sys_register, arm_mcd_write_mve_register and
@@ -75,25 +75,16 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type,
uint32_t n);
/**
* \brief 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.
* @param[in] n The register ID of the CP register.
* @param[in] cs CPU state.
*/
uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n);
-/**
- * \brief Sets the scr_el3 register according to the secure parameter.
- *
- * If secure is true, the first bit of the scr_el3 register gets set to 0,
- * if not it gets set to 1.
- * @param[in] secure True when secure is requested.
- * @param[in] cs CPU state.
- */
-int arm_mcd_set_scr(CPUState *cs, bool secure);
/**
* \brief 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.
@@ -103,7 +94,7 @@ int arm_mcd_set_scr(CPUState *cs, bool secure);
int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces);
/**
* \brief 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.
@@ -117,7 +108,7 @@ int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups,
GArray *registers, int *current_group_id);
/**
* \brief 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.
@@ -131,7 +122,7 @@ int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups,
GArray *registers, int *current_group_id);
/**
* \brief Adds additional data to parsed registers.
- *
+ *
* This function is called, after \ref arm_mcd_parse_core_xml_file and
* \ref arm_mcd_parse_core_xml_file. It adds additional data for all already
* parsed registers. The registers get a correct ID, group, memory space and
@@ -217,6 +217,10 @@ int init_resets(GArray *resets);
* @param[out] 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);
/**
* \brief Resets the mcdserver_state struct.
*
@@ -251,7 +255,7 @@ int find_cpu_clusters(Object *child, void *opaque);
*
* 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.
+ * returned.
* @param[in] a Process a.
* @param[in] b Process b.
*/
@@ -262,7 +266,7 @@ int pid_order(const void *a, const void *b);
int mcd_chr_can_receive(void *opaque);
/**
* \brief Handles receiving a TCP packet.
- *
+ *
* This function gets called by QEMU when a TCP packet is received.
* It iterates over that packet an calls \ref mcd_read_byte for each char
* of the packet.
@@ -272,7 +276,7 @@ int mcd_chr_can_receive(void *opaque);
void mcd_chr_receive(void *opaque, const uint8_t *buf, int size);
/**
* \brief 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.
@@ -285,7 +289,7 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event);
bool mcd_supports_guest_debug(void);
/**
* \brief 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
* \c RUN_STATE_DEBUG it collects additional data on what watchpoint was hit.
@@ -296,13 +300,13 @@ bool mcd_supports_guest_debug(void);
void mcd_vm_state_change(void *opaque, bool running, RunState state);
/**
* \brief Calls \ref mcd_put_packet_binary with buf and length of buf.
- *
+ *
* @param[in] buf TCP packet data.
*/
int mcd_put_packet(const char *buf);
/**
* \brief 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 \ref mcd_put_buffer function.
@@ -316,26 +320,30 @@ int mcd_put_packet_binary(const char *buf, int len);
bool mcd_got_immediate_ack(void);
/**
* \brief Sends the buf as TCP packet with qemu_chr_fe_write_all.
- *
+ *
* @param[in] buf TCP packet data.
* @param[in] len TCP packet length.
*/
void mcd_put_buffer(const uint8_t *buf, int len);
/**
* \brief Returns the process of the provided CPU.
- *
+ *
* @param[in] cpu The CPU state.
*/
MCDProcess *mcd_get_cpu_process(CPUState *cpu);
+/**
+ * \brief Sets c_cpu to the just stopped CPU.
+ */
+void mcd_set_stop_cpu(CPUState *cpu);
/**
* \brief Returns the process ID of the provided CPU.
- *
+ *
* @param[in] cpu The CPU state.
*/
uint32_t mcd_get_cpu_pid(CPUState *cpu);
/**
* \brief Returns the process of the provided pid.
- *
+ *
* @param[in] pid The process ID.
*/
MCDProcess *mcd_get_process(uint32_t pid);
@@ -344,16 +352,16 @@ MCDProcess *mcd_get_process(uint32_t pid);
*/
CPUState *mcd_first_attached_cpu(void);
/**
- * \brief Returns the first CPU with an attached process starting after the
+ * \brief Returns the first CPU with an attached process starting after the
* provided cpu.
- *
+ *
* @param[in] cpu The CPU to start from.
*/
CPUState *mcd_next_attached_cpu(CPUState *cpu);
/**
* \brief 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
@@ -366,7 +374,7 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu);
void mcd_read_byte(uint8_t ch);
/**
* \brief 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 \ref run_cmd_parser.
@@ -379,7 +387,7 @@ int mcd_handle_packet(const char *line_buf);
void mcd_put_strbuf(void);
/**
* \brief 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.
* @param[in] code An exitcode, which can be used in the future.
@@ -387,7 +395,7 @@ void mcd_put_strbuf(void);
void mcd_exit(int code);
/**
* \brief 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 \ref process_string_cmd. In case this function fails, an empty
* TCP packet is sent back the MCD Shared Library.
@@ -397,7 +405,7 @@ void mcd_exit(int code);
void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd);
/**
* \brief Collects all parameters from the data and calls the correct handler.
- *
+ *
* The parameters are extracted with the \ref 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.
@@ -409,7 +417,7 @@ int process_string_cmd(void *user_ctx, const char *data,
const MCDCmdParseEntry *cmds, int num_cmds);
/**
* \brief 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.
@@ -420,7 +428,7 @@ int process_string_cmd(void *user_ctx, const char *data,
int cmd_parse_params(const char *data, const char *schema, GArray *params);
/**
* \brief Handler for the VM start TCP packet.
- *
+ *
* Evaluates whether all cores or just a perticular core should get started and
* calls \ref mcd_vm_start or \ref mcd_cpu_start respectively.
* @param[in] params GArray with all TCP packet parameters.
@@ -428,7 +436,7 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params);
void handle_vm_start(GArray *params, void *user_ctx);
/**
* \brief Handler for the VM step TCP packet.
- *
+ *
* Calls \ref mcd_cpu_sstep for the CPU which sould be stepped. Stepping all
* CPUs is currently not supported.
* @param[in] params GArray with all TCP packet parameters.
@@ -436,7 +444,7 @@ void handle_vm_start(GArray *params, void *user_ctx);
void handle_vm_step(GArray *params, void *user_ctx);
/**
* \brief Handler for the VM stop TCP packet.
- *
+ *
* Always calls \ref mcd_vm_stop and stops all cores. Stopping individual cores
* is currently not supported
* @param[in] params GArray with all TCP packet parameters.
@@ -444,7 +452,7 @@ void handle_vm_step(GArray *params, void *user_ctx);
void handle_vm_stop(GArray *params, void *user_ctx);
/**
* \brief Handler for all TCP query packets.
- *
+ *
* Calls \ref process_string_cmd with all query functions in the
* mcd_query_cmds_table. \ref process_string_cmd then selects the correct one.
* This function just passes on the TCP packet data string from the parameters.
@@ -453,19 +461,19 @@ void handle_vm_stop(GArray *params, void *user_ctx);
void handle_gen_query(GArray *params, void *user_ctx);
/**
* \brief Returns the internal CPU index plus one.
- *
+ *
* @param[in] cpu CPU of interest.
*/
int mcd_get_cpu_index(CPUState *cpu);
/**
* \brief Returns the CPU the index i_cpu_index.
- *
+ *
* @param[in] cpu_index Index of the desired CPU.
*/
CPUState *mcd_get_cpu(uint32_t cpu_index);
/**
* \brief 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.
* @param[in] params GArray with all TCP packet parameters.
@@ -473,26 +481,26 @@ CPUState *mcd_get_cpu(uint32_t cpu_index);
void handle_query_cores(GArray *params, void *user_ctx);
/**
* \brief Handler for the system query.
- *
+ *
* Sends the system name, which is "qemu-system".
* @param[in] params GArray with all TCP packet parameters.
*/
void handle_query_system(GArray *params, void *user_ctx);
/**
* \brief Returns the first CPU in the provided process.
- *
+ *
* @param[in] process The process to look in.
*/
CPUState *get_first_cpu_in_process(MCDProcess *process);
/**
* \brief Returns the CPU with an index equal to the thread_id.
- *
+ *
* @param[in] thread_id ID of the desired CPU.
*/
CPUState *find_cpu(uint32_t thread_id);
/**
* \brief 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,
@@ -503,14 +511,14 @@ CPUState *find_cpu(uint32_t thread_id);
void handle_open_core(GArray *params, void *user_ctx);
/**
* \brief Handler for the first reset query.
- *
+ *
* This function sends the first reset name and ID.
* @param[in] params GArray with all TCP packet parameters.
*/
void handle_query_reset_f(GArray *params, void *user_ctx);
/**
* \brief 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.
* @param[in] params GArray with all TCP packet parameters.
@@ -518,7 +526,7 @@ void handle_query_reset_f(GArray *params, void *user_ctx);
void handle_query_reset_c(GArray *params, void *user_ctx);
/**
* \brief Handler for closing the MCD server.
- *
+ *
* This function detaches the debugger (process) and frees up memory.
* Then it start the QEMU VM with \ref mcd_vm_start.
* @param[in] params GArray with all TCP packet parameters.
@@ -526,7 +534,7 @@ void handle_query_reset_c(GArray *params, void *user_ctx);
void handle_close_server(GArray *params, void *user_ctx);
/**
* \brief Handler for closing a core.
- *
+ *
* Frees all memory allocated for core specific information. This includes
* memory spaces, register groups and registers.
* @param[in] params GArray with all TCP packet parameters.
@@ -534,7 +542,7 @@ void handle_close_server(GArray *params, void *user_ctx);
void handle_close_core(GArray *params, void *user_ctx);
/**
* \brief Handler for trigger query.
- *
+ *
* Sends data on the different types of trigger and their options and actions.
* @param[in] params GArray with all TCP packet parameters.
*/
@@ -545,13 +553,13 @@ void handle_query_trigger(GArray *params, void *user_ctx);
void mcd_vm_start(void);
/**
* \brief Starts the selected CPU with the cpu_resume function.
- *
+ *
* @param[in] cpu The CPU about to be started.
*/
void mcd_cpu_start(CPUState *cpu);
/**
* \brief 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.
* @param[in] cpu The CPU about to be stepped.
@@ -563,14 +571,14 @@ int mcd_cpu_sstep(CPUState *cpu);
void mcd_vm_stop(void);
/**
* \brief Handler for the first register group query.
- *
+ *
* This function sends the first register group name and ID.
* @param[in] params GArray with all TCP packet parameters.
*/
void handle_query_reg_groups_f(GArray *params, void *user_ctx);
/**
* \brief 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.
* @param[in] params GArray with all TCP packet parameters.
@@ -578,7 +586,7 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx);
void handle_query_reg_groups_c(GArray *params, void *user_ctx);
/**
* \brief Handler for the first memory space query.
- *
+ *
* This function sends the first memory space name, ID, type and accessing
* options.
* @param[in] params GArray with all TCP packet parameters.
@@ -586,7 +594,7 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx);
void handle_query_mem_spaces_f(GArray *params, void *user_ctx);
/**
* \brief 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
@@ -596,14 +604,14 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx);
void handle_query_mem_spaces_c(GArray *params, void *user_ctx);
/**
* \brief Handler for the first register query.
- *
+ *
* This function sends the first register with all its information.
* @param[in] params GArray with all TCP packet parameters.
*/
void handle_query_regs_f(GArray *params, void *user_ctx);
/**
* \brief 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.
@@ -612,7 +620,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx);
void handle_query_regs_c(GArray *params, void *user_ctx);
/**
* \brief 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 \ref init_resets and
* \reg init_trigger functions. It also send the \c TCP_HANDSHAKE_SUCCESS
@@ -623,14 +631,14 @@ void handle_query_regs_c(GArray *params, void *user_ctx);
void handle_open_server(GArray *params, void *user_ctx);
/**
* \brief Handler for performing resets.
- *
+ *
* This function is currently not in use.
* @param[in] params GArray with all TCP packet parameters.
*/
void handle_reset(GArray *params, void *user_ctx);
/**
* \brief 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.
@@ -639,7 +647,7 @@ void handle_reset(GArray *params, void *user_ctx);
void handle_query_state(GArray *params, void *user_ctx);
/**
* \brief Handler for reading a register.
- *
+ *
* This function calls \ref 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 \ref mcd_memtohex and then send.
@@ -648,7 +656,7 @@ void handle_query_state(GArray *params, void *user_ctx);
void handle_read_register(GArray *params, void *user_ctx);
/**
* \brief Handler for writing a register.
- *
+ *
* This function converts the incoming hex string data into a byte array with
* \ref mcd_hextomem. Then it calls \ref mcd_write_register to write to the
* register.
@@ -657,7 +665,7 @@ void handle_read_register(GArray *params, void *user_ctx);
void handle_write_register(GArray *params, void *user_ctx);
/**
* \brief Handler for reading memory.
- *
+ *
* First, this function checks whether reading a secure memory space is
* requested and changes the access mode with \ref arm_mcd_set_scr.
* Then it calls \ref mcd_read_memory to read memory. The collected
@@ -668,7 +676,7 @@ void handle_write_register(GArray *params, void *user_ctx);
void handle_read_memory(GArray *params, void *user_ctx);
/**
* \brief Handler for writing memory.
- *
+ *
* First, this function checks whether reading a secure memory space is
* requested and changes the access mode with \ref arm_mcd_set_scr.
* Then it converts the incoming hex string data into a byte array with
@@ -679,7 +687,7 @@ void handle_read_memory(GArray *params, void *user_ctx);
void handle_write_memory(GArray *params, void *user_ctx);
/**
* \brief 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 \ref arm_mcd_read_register.
@@ -690,7 +698,7 @@ void handle_write_memory(GArray *params, void *user_ctx);
int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg);
/**
* \brief 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 \ref arm_mcd_write_register.
@@ -701,7 +709,7 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg);
/**
* \brief Reads memory data and stores it into the buf.
- *
+ *
* This function calls cpu_memory_rw_debug or if available
* memory_rw_debug in read mode and passes on all parameters.
* @param[in] cpu CPU to which the memory belongs.
@@ -712,7 +720,7 @@ int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg);
int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
/**
* \brief Writes data from the buf into the memory.
- *
+ *
* This function calls cpu_memory_rw_debug or if available
* memory_rw_debug in write mode and passes on all parameters.
* @param[in] cpu CPU to which the memory belongs.
@@ -723,7 +731,7 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
/**
* \brief Handler for inserting a break- or watchpoint.
- *
+ *
* This function extracts the CPU, breakpoint type and address from the
* parameters and calls \ref mcd_breakpoint_insert to insert the breakpoint.
* @param[in] params GArray with all TCP packet parameters.
@@ -731,7 +739,7 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len);
void handle_breakpoint_insert(GArray *params, void *user_ctx);
/**
* \brief Handler for inserting a break- or watchpoint.
- *
+ *
* This function extracts the CPU, breakpoint type and address from the
* parameters and calls \ref mcd_breakpoint_remove to insert the breakpoint.
* @param[in] params GArray with all TCP packet parameters.
@@ -739,7 +747,7 @@ void handle_breakpoint_insert(GArray *params, void *user_ctx);
void handle_breakpoint_remove(GArray *params, void *user_ctx);
/**
* \brief 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
@@ -751,7 +759,7 @@ void handle_breakpoint_remove(GArray *params, void *user_ctx);
int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr);
/**
* \brief 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
new file mode 100644
@@ -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 */
@@ -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;
@@ -7,6 +7,7 @@
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
+#include "qemu/debug.h"
#include "exec/mcdstub.h"
#include "mcdstub/syscalls.h"
#include "hw/cpu/cluster.h"
@@ -67,6 +68,14 @@ void mcd_init_mcdserver_state(void)
.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)
@@ -1804,19 +1813,22 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len)
void handle_read_memory(GArray *params, void *user_ctx)
{
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;
CPUState *cpu = mcd_get_cpu(cpu_id);
- /* check if the mem space is secure */
- 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);
- if (arm_mcd_set_scr(cpu, space.is_secure)) {
- mcd_put_packet(TCP_EXECUTION_ERROR);
- return;
- }
+ /*
+ * TODO: select to correct address space
+ * uint32_t mem_space_id = get_param(params, 1)->data_uint32_t;
+ * 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);
+ * if (arm_mcd_set_scr(cpu, space.is_secure)) {
+ * mcd_put_packet(TCP_EXECUTION_ERROR);
+ * return;
+ * }
+ */
/* read memory */
g_byte_array_set_size(mcdserver_state.mem_buf, len);
if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data,
@@ -1832,18 +1844,21 @@ void handle_read_memory(GArray *params, void *user_ctx)
void handle_write_memory(GArray *params, void *user_ctx)
{
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;
CPUState *cpu = mcd_get_cpu(cpu_id);
- /* check if the mem space is secure */
- 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);
- if (arm_mcd_set_scr(cpu, space.is_secure)) {
- mcd_put_packet(TCP_EXECUTION_ERROR);
- return;
- }
+ /*
+ * TODO: select to correct address space
+ * uint32_t mem_space_id = get_param(params, 1)->data_uint32_t;
+ * 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);
+ * if (arm_mcd_set_scr(cpu, space.is_secure)) {
+ * mcd_put_packet(TCP_EXECUTION_ERROR);
+ * return;
+ * }
+ */
/* write memory */
mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len);
if (mcd_write_memory(cpu, mem_address,
@@ -4,7 +4,7 @@
mcd_system_ss = ss.source_set()
# only system emulation is supported over mcd
-mcd_system_ss.add(files('mcdstub.c'))
+mcd_system_ss.add(files('mcdstub.c', '../debug/debug-mcd.c'))
mcd_system_ss = mcd_system_ss.apply(config_host, strict: false)
@@ -16,4 +16,4 @@ libmcd_softmmu = static_library('mcd_softmmu',
mcd_softmmu = declare_dependency(link_whole: libmcd_softmmu)
system_ss.add(mcd_softmmu)
-common_ss.add(files('mcd_syscalls.c'))
+common_ss.add(files('../debug/debug-common.c', 'mcd_syscalls.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,10 +307,13 @@ void cpu_handle_guest_debug(CPUState *cpu)
cpu_single_step(cpu, 0);
}
} else {
- /*
- * TODO: was gdb_set_stop_cpu(cpu), need to abstract options to
- * a QOM class.
- */
+ 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;
}
@@ -4,6 +4,7 @@
#include "sysemu/tcg.h"
#include "internals.h"
#include "cpregs.h"
+#include "qemu/debug.h"
#include "mcdstub/arm_mcdstub.h"
@@ -332,20 +333,6 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n)
return 0;
}
-int arm_mcd_set_scr(CPUState *cs, bool secure)
-{
- /* switches between secure and non secure mode */
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
- /* set bit 0 to 1 if non secure, to 0 if secure*/
- if (secure) {
- env->cp15.scr_el3 &= 0xFFFFFFFE;
- } else {
- env->cp15.scr_el3 |= 1;
- }
- return 0;
-}
-
int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces)
{
int nr_address_spaces = cpu->num_ases;
@@ -379,7 +366,7 @@ int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces)
.is_secure = false,
};
g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1);
- if(nr_address_spaces > 1) {
+ if (nr_address_spaces > 1) {
mem_space_id++;
mcd_mem_space_st secure = {
.name = "Secure",
From: neder <nicolas.eder@lauterbach.com> --- MAINTAINERS | 3 + debug/debug-common.c | 42 ++++++++++++ debug/debug-gdb.c | 24 +++++++ debug/debug-mcd.c | 25 +++++++ gdbstub/meson.build | 4 +- gdbstub/softmmu.c | 4 ++ gdbstub/user.c | 2 + include/exec/gdbstub.h | 5 ++ include/hw/boards.h | 1 + include/mcdstub/arm_mcdstub.h | 25 +++---- include/mcdstub/mcdstub.h | 122 ++++++++++++++++++---------------- include/qemu/debug.h | 19 ++++++ include/qemu/typedefs.h | 2 + mcdstub/mcdstub.c | 51 +++++++++----- mcdstub/meson.build | 4 +- softmmu/cpus.c | 12 ++-- target/arm/mcdstub.c | 17 +---- 17 files changed, 247 insertions(+), 115 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