All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luc Michel <luc.michel@greensocs.com>
To: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>
Cc: qemu-devel@nongnu.org, "Peter Maydell" <peter.maydell@linaro.org>,
	"Eduardo Habkost" <ehabkost@redhat.com>,
	alistair@alistair23.me, mark.burton@greensocs.com,
	"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	saipava@xilinx.com, edgari@xilinx.com, qemu-arm@nongnu.org
Subject: Re: [Qemu-devel] [Qemu-arm] [PATCH v5 02/16] gdbstub: introduce GDB processes
Date: Wed, 14 Nov 2018 11:14:31 +0100	[thread overview]
Message-ID: <2785510b-5db5-7ded-2404-7d5653a98764@greensocs.com> (raw)
In-Reply-To: <20181113105216.GG1148@toto>

Hi Edgar,

On 11/13/18 11:52 AM, Edgar E. Iglesias wrote:
> On Sat, Nov 10, 2018 at 09:11:33AM +0100, 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.michel@greensocs.com>
>> Acked-by: Alistair Francis <alistair.francis@wdc.com>
>> ---
>>  gdbstub.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 76 insertions(+)
>>
>> diff --git a/gdbstub.c b/gdbstub.c
>> index c4e4f9f082..0d70b89598 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));
>> +    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,58 @@ 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 */
>> +        process->pid = cluster->cluster_id + 1;
> 
> This may be theoretical but since both pid and cluster_id are uint32_t
> you may end up with 0 here.
> 
> You may want to limit cluster_id's to something like the range 0 - INT32_MAX.
That would be an efficient solution to workaround this problem. However
it seems a bit artificial to limit the cluster_id range in the "generic"
CPU_CLUSTER class, just for the GDB stub code to work correctly.

Another solution could be to add a `gdb_pid' property to the CPU_CLUSTER
type, that would automatically be set to `cpu_cluster + 1' during
realization (and customized by the platform if needed). That way, value
0 could be explicitly forbidden in the CPU_CLUSTER API. However, Peter
was not a big fan of having explicit GDB stuff in the platform.

If somebody comes with a good compromise, I can change this. Otherwise
if we want to be extra safe, maybe we can simply assert that cluster_id
UINT32_MAX is not used in GDB stub.

(snip)
>> +static int pid_order(const void *a, const void *b)
>> +{
>> +    GDBProcess *pa = (GDBProcess *) a;
>> +    GDBProcess *pb = (GDBProcess *) b;
>> +
>> +    return pa->pid - pb->pid;
> 
> Similarly here, is this safe?
> e.g:
> pa->pid = 1
> pb->pid = 0x80000002
To make it safe, I think we can do explicit comparisons:

if (pa->pid < pb->pid) {
    return -1;
} else if (pa->pid > pb->pid) {
    return 1;
} else {
    return 0;
}


Thanks,
Luc

> 
> 
> Otherwise:
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> 
> 
> 
>> +}
>> +
>> +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 +2130,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);
>>      }
>> -- 
>> 2.19.1
>>
>>

  reply	other threads:[~2018-11-14 10:14 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-10  8:11 [Qemu-devel] [PATCH v5 00/16] gdbstub: support for the multiprocess extension Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 01/16] hw/cpu: introduce CPU clusters Luc Michel
2018-11-13 10:38   ` [Qemu-devel] [Qemu-arm] " Edgar E. Iglesias
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 02/16] gdbstub: introduce GDB processes Luc Michel
2018-11-13 10:52   ` [Qemu-devel] [Qemu-arm] " Edgar E. Iglesias
2018-11-14 10:14     ` Luc Michel [this message]
2018-11-14 10:31       ` Edgar E. Iglesias
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 03/16] gdbstub: add multiprocess support to '?' packets Luc Michel
2018-11-13 11:06   ` [Qemu-devel] [Qemu-arm] " Edgar E. Iglesias
2018-11-14  8:43     ` Luc Michel
2018-11-14 10:27       ` Edgar E. Iglesias
2018-11-15  8:00         ` Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 04/16] gdbstub: add multiprocess support to 'H' and 'T' packets Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 05/16] gdbstub: add multiprocess support to vCont packets Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 06/16] gdbstub: add multiprocess support to 'sC' packets Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 07/16] gdbstub: add multiprocess support to (f|s)ThreadInfo and ThreadExtraInfo Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 08/16] gdbstub: add multiprocess support to Xfer:features:read: Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 09/16] gdbstub: add multiprocess support to gdb_vm_state_change() Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 10/16] gdbstub: add multiprocess support to 'D' packets Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 11/16] gdbstub: add support for extended mode packet Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 12/16] gdbstub: add support for vAttach packets Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 13/16] gdbstub: processes initialization on new peer connection Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 14/16] gdbstub: gdb_set_stop_cpu: ignore request when process is not attached Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 15/16] gdbstub: add multiprocess extension support Luc Michel
2018-11-10  8:11 ` [Qemu-devel] [PATCH v5 16/16] arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters Luc Michel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2785510b-5db5-7ded-2404-7d5653a98764@greensocs.com \
    --to=luc.michel@greensocs.com \
    --cc=alistair@alistair23.me \
    --cc=edgar.iglesias@gmail.com \
    --cc=edgari@xilinx.com \
    --cc=ehabkost@redhat.com \
    --cc=f4bug@amsat.org \
    --cc=mark.burton@greensocs.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=saipava@xilinx.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.