[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 04/37] gdbstub: introduce GDB processes
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 04/37] gdbstub: introduce GDB processes |
Date: |
Mon, 7 Jan 2019 16:30:44 +0000 |
From: Luc Michel <address@hidden>
Add a structure GDBProcess that represents processes from the GDB
semantic point of view.
CPUs can be split into different processes, by grouping them under
different cpu-cluster objects. Each occurrence of a cpu-cluster object
implies the existence of the corresponding process in the GDB stub. The
GDB process ID is derived from the corresponding cluster ID as follows:
GDB PID = cluster ID + 1
This is because PIDs -1 and 0 are reserved in GDB and cannot be used by
processes.
A default process is created to handle CPUs that are not in a cluster.
This process gets the PID of the last process PID + 1.
Signed-off-by: Luc Michel <address@hidden>
Acked-by: Alistair Francis <address@hidden>
Reviewed-by: Edgar E. Iglesias <address@hidden>
Reviewed-by: Philippe Mathieu-Daudé <address@hidden>
Message-id: address@hidden
[PMM: fixed checkpatch nit about block comment style]
Signed-off-by: Peter Maydell <address@hidden>
---
gdbstub.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/gdbstub.c b/gdbstub.c
index c4e4f9f0821..9ac6f19a186 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -29,6 +29,7 @@
#include "chardev/char-fe.h"
#include "sysemu/sysemu.h"
#include "exec/gdbstub.h"
+#include "hw/cpu/cluster.h"
#endif
#define MAX_PACKET_LENGTH 4096
@@ -296,6 +297,11 @@ typedef struct GDBRegisterState {
struct GDBRegisterState *next;
} GDBRegisterState;
+typedef struct GDBProcess {
+ uint32_t pid;
+ bool attached;
+} GDBProcess;
+
enum RSState {
RS_INACTIVE,
RS_IDLE,
@@ -324,6 +330,9 @@ typedef struct GDBState {
CharBackend chr;
Chardev *mon_chr;
#endif
+ bool multiprocess;
+ GDBProcess *processes;
+ int process_num;
char syscall_buf[256];
gdb_syscall_complete_cb current_syscall_cb;
} GDBState;
@@ -1751,6 +1760,30 @@ void gdb_exit(CPUArchState *env, int code)
#endif
}
+/*
+ * Create the process that will contain all the "orphan" CPUs (that are not
+ * part of a CPU cluster). Note that if this process contains no CPUs, it won't
+ * be attachable and thus will be invisible to the user.
+ */
+static void create_default_process(GDBState *s)
+{
+ GDBProcess *process;
+ int max_pid = 0;
+
+ if (s->process_num) {
+ max_pid = s->processes[s->process_num - 1].pid;
+ }
+
+ s->processes = g_renew(GDBProcess, 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;
+}
+
#ifdef CONFIG_USER_ONLY
int
gdb_handlesig(CPUState *cpu, int sig)
@@ -1848,6 +1881,7 @@ static bool gdb_accept(void)
s = g_malloc0(sizeof(GDBState));
s->c_cpu = first_cpu;
s->g_cpu = first_cpu;
+ create_default_process(s);
s->fd = fd;
gdb_has_xml = false;
@@ -2004,6 +2038,65 @@ static const TypeInfo char_gdb_type_info = {
.class_init = char_gdb_class_init,
};
+static int find_cpu_clusters(Object *child, void *opaque)
+{
+ if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) {
+ GDBState *s = (GDBState *) opaque;
+ CPUClusterState *cluster = CPU_CLUSTER(child);
+ GDBProcess *process;
+
+ s->processes = g_renew(GDBProcess, s->processes, ++s->process_num);
+
+ process = &s->processes[s->process_num - 1];
+
+ /*
+ * GDB process IDs -1 and 0 are reserved. To avoid subtle errors at
+ * runtime, we enforce here that the machine does not use a cluster ID
+ * that would lead to PID 0.
+ */
+ assert(cluster->cluster_id != UINT32_MAX);
+ process->pid = cluster->cluster_id + 1;
+ process->attached = false;
+
+ return 0;
+ }
+
+ return object_child_foreach(child, find_cpu_clusters, opaque);
+}
+
+static int pid_order(const void *a, const void *b)
+{
+ GDBProcess *pa = (GDBProcess *) a;
+ GDBProcess *pb = (GDBProcess *) b;
+
+ if (pa->pid < pb->pid) {
+ return -1;
+ } else if (pa->pid > pb->pid) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void create_processes(GDBState *s)
+{
+ object_child_foreach(object_get_root(), find_cpu_clusters, s);
+
+ if (s->processes) {
+ /* Sort by PID */
+ qsort(s->processes, s->process_num, sizeof(s->processes[0]),
pid_order);
+ }
+
+ create_default_process(s);
+}
+
+static void cleanup_processes(GDBState *s)
+{
+ g_free(s->processes);
+ s->process_num = 0;
+ s->processes = NULL;
+}
+
int gdbserver_start(const char *device)
{
trace_gdbstub_op_start(device);
@@ -2060,11 +2153,15 @@ int gdbserver_start(const char *device)
} else {
qemu_chr_fe_deinit(&s->chr, true);
mon_chr = s->mon_chr;
+ cleanup_processes(s);
memset(s, 0, sizeof(GDBState));
s->mon_chr = mon_chr;
}
s->c_cpu = first_cpu;
s->g_cpu = first_cpu;
+
+ create_processes(s);
+
if (chr) {
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
--
2.19.2
- [Qemu-devel] [PULL 00/37] target-arm queue, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 02/37] target/arm: SVE brk[ab] merging does not have s bit, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 03/37] hw/cpu: introduce CPU clusters, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 01/37] target/arm: Convert ARM_TBFLAG_* to FIELDs, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 04/37] gdbstub: introduce GDB processes,
Peter Maydell <=
- [Qemu-devel] [PULL 05/37] gdbstub: add multiprocess support to '?' packets, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 06/37] gdbstub: add multiprocess support to 'H' and 'T' packets, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 07/37] gdbstub: add multiprocess support to vCont packets, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 09/37] gdbstub: add multiprocess support to (f|s)ThreadInfo and ThreadExtraInfo, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 08/37] gdbstub: add multiprocess support to 'sC' packets, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 10/37] gdbstub: add multiprocess support to Xfer:features:read:, Peter Maydell, 2019/01/07
- [Qemu-devel] [PULL 11/37] gdbstub: add multiprocess support to gdb_vm_state_change(), Peter Maydell, 2019/01/07