On 23/11/18 10:17, Luc Michel wrote: > Add a structure GDBProcess that represent 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. > > When no such container are found, all the CPUs are put in a unique GDB > process (create_unique_process()). This is also the case when compiled > in user mode, where multi-processes do not make much sense for now. > > Signed-off-by: Luc Michel <luc.mic...@greensocs.com> > Acked-by: Alistair Francis <alistair.fran...@wdc.com> > Reviewed-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> > --- > gdbstub.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 87 insertions(+) > > diff --git a/gdbstub.c b/gdbstub.c > index c4e4f9f082..26f5a7449a 100644 > --- a/gdbstub.c > +++ b/gdbstub.c > @@ -27,10 +27,11 @@ > #include "monitor/monitor.h" > #include "chardev/char.h" > #include "chardev/char-fe.h" > #include "sysemu/sysemu.h" > #include "exec/gdbstub.h" > +#include "hw/cpu/cluster.h" > #endif > > #define MAX_PACKET_LENGTH 4096 > > #include "qemu/sockets.h" > @@ -294,10 +295,15 @@ typedef struct GDBRegisterState { > gdb_reg_cb set_reg; > const char *xml; > struct GDBRegisterState *next; > } GDBRegisterState; > > +typedef struct GDBProcess { > + uint32_t pid; > + bool attached; > +} GDBProcess; > + > enum RSState { > RS_INACTIVE, > RS_IDLE, > RS_GETLINE, > RS_GETLINE_ESC, > @@ -322,10 +328,13 @@ typedef struct GDBState { > int running_state; > #else > 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; > > /* By default use no IRQs and no timers while single stepping so as to > @@ -1749,10 +1758,24 @@ void gdb_exit(CPUArchState *env, int code) > #ifndef CONFIG_USER_ONLY > qemu_chr_fe_deinit(&s->chr, true); > #endif > } > > +/* > + * Create a unique process containing all the CPUs. > + */ > +static void create_unique_process(GDBState *s) > +{ > + GDBProcess *process; > + > + s->processes = g_malloc0(sizeof(GDBProcess));
good place to use: s->processes = g_new0(GDBProcess, 1); Regardless: Reviewed-by: Philippe Mathieu-Daudé <phi...@redhat.com> > + s->process_num = 1; > + process = &s->processes[0]; > + > + process->pid = 1; > +} > + > #ifdef CONFIG_USER_ONLY > int > gdb_handlesig(CPUState *cpu, int sig) > { > GDBState *s; > @@ -1846,10 +1869,11 @@ static bool gdb_accept(void) > } > > s = g_malloc0(sizeof(GDBState)); > s->c_cpu = first_cpu; > s->g_cpu = first_cpu; > + create_unique_process(s); > s->fd = fd; > gdb_has_xml = false; > > gdbserver_state = s; > return true; > @@ -2002,10 +2026,69 @@ static const TypeInfo char_gdb_type_info = { > .name = TYPE_CHARDEV_GDB, > .parent = TYPE_CHARDEV, > .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(process->pid != 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) { > + /* No CPU cluster specified by the machine */ > + create_unique_process(s); > + } else { > + /* Sort by PID */ > + qsort(s->processes, s->process_num, sizeof(s->processes[0]), > pid_order); > + } > +} > + > +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); > > GDBState *s; > @@ -2058,15 +2141,19 @@ int gdbserver_start(const char *device) > NULL, &error_abort); > monitor_init(mon_chr, 0); > } 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, > gdb_chr_event, NULL, NULL, NULL, true); > } >