[Pdbg] [PATCH v2 19/39] gdbserver: use read-modify-write for put_mem that is not 8-byte aligned

Joel Stanley joel at jms.id.au
Tue May 3 17:08:20 AEST 2022


On Wed, 20 Apr 2022 at 06:51, Nicholas Piggin <npiggin at gmail.com> wrote:
>
> Not all targets have memory access that can support arbitrary byte
> writes. Use RMW for put_mem commands that are not 8-byte aligned.
>
> These helpers should possibly be moved into core code and this should
> really either be done in the target accessor, or at least an alignment
> capability should be exposed to the caller. But for now this will allow
> sbefifo mem ops to work to set breakpoints (which requires 4-byte
> writes).
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>

Reviewed-by: Joel Stanley <joel at jms.id.au>

> ---
>  src/pdbgproxy.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 83 insertions(+), 2 deletions(-)
>
> diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
> index 9729eaa1..4c7b4a82 100644
> --- a/src/pdbgproxy.c
> +++ b/src/pdbgproxy.c
> @@ -14,6 +14,7 @@
>  #include <assert.h>
>  #include <getopt.h>
>  #include <errno.h>
> +#include <byteswap.h>
>  #include <ccan/array_size/array_size.h>
>
>  #include <bitutils.h>
> @@ -229,6 +230,86 @@ static uint64_t get_real_addr(uint64_t addr)
>         return addr;
>  }
>
> +/*
> + * TODO: Move write_memory and read_memory into libpdbg helper and advertise
> + * alignment requirement of a target, or have the back-ends use it directly
> + * (latter may have the problem that implicit R-M-W is undesirable at very low
> + * level operations if we only wanted to write).
> + */
> +
> +/* WARNING: _a *MUST* be a power of two */
> +#define ALIGN_UP(_v, _a)       (((_v) + (_a) - 1) & ~((_a) - 1))
> +#define ALIGN_DOWN(_v, _a)     ((_v) & ~((_a) - 1))
> +
> +static int write_memory(uint64_t addr, uint64_t len, void *buf, size_t align)
> +{
> +       uint64_t start_addr, end_addr;
> +       void *tmpbuf = NULL;
> +       void *src;
> +       int err = 0;
> +
> +       start_addr = ALIGN_DOWN(addr, align);
> +       end_addr = ALIGN_UP(addr + len, align);
> +
> +       if (addr != start_addr || (addr + len) != end_addr) {
> +               tmpbuf = malloc(end_addr - start_addr);
> +               if (mem_read(adu_target, start_addr, tmpbuf, end_addr - start_addr, 0, false)) {
> +                       PR_ERROR("Unable to read memory for RMW\n");
> +                       err = -1;
> +                       goto out;
> +               }
> +               memcpy(tmpbuf + (addr - start_addr), buf, len);
> +               src = tmpbuf;
> +       } else {
> +               src = buf;
> +       }
> +
> +       if (mem_write(adu_target, start_addr, src, end_addr - start_addr, 0, false)) {
> +               PR_ERROR("Unable to write memory\n");
> +               err = -1;
> +       }
> +
> +out:
> +       if (tmpbuf)
> +               free(tmpbuf);
> +
> +       return err;
> +}
> +
> +static int read_memory(uint64_t addr, uint64_t len, void *buf, size_t align)
> +{
> +       uint64_t start_addr, end_addr;
> +       void *tmpbuf = NULL;
> +       void *dst;
> +       int err = 0;
> +
> +       start_addr = ALIGN_DOWN(addr, align);
> +       end_addr = ALIGN_UP(addr + len, align);
> +
> +       if (addr != start_addr || (addr + len) != end_addr) {
> +               tmpbuf = malloc(end_addr - start_addr);
> +               dst = tmpbuf;
> +       } else {
> +               dst = buf;
> +       }
> +
> +       if (mem_read(adu_target, start_addr, dst, end_addr - start_addr, 0, false)) {
> +               PR_ERROR("Unable to read memory\n");
> +               err = -1;
> +               goto out;
> +       }
> +
> +       if (addr != start_addr || (addr + len) != end_addr)
> +               memcpy(buf, tmpbuf + (addr - start_addr), len);
> +
> +out:
> +       if (tmpbuf)
> +               free(tmpbuf);
> +
> +       return err;
> +}
> +
> +
>  static void get_mem(uint64_t *stack, void *priv)
>  {
>         uint64_t addr, len, linear_map;
> @@ -252,7 +333,7 @@ static void get_mem(uint64_t *stack, void *priv)
>
>         linear_map = get_real_addr(addr);
>         if (linear_map != -1UL) {
> -               if (mem_read(adu_target, linear_map, (uint8_t *) data, len, 0, false)) {
> +               if (read_memory(linear_map, len, data, 1)) {
>                         PR_ERROR("Unable to read memory\n");
>                         err = 1;
>                 }
> @@ -320,7 +401,7 @@ static void put_mem(uint64_t *stack, void *priv)
>                 }
>         }
>
> -       if (mem_write(adu_target, addr, data, len, 0, false)) {
> +       if (write_memory(addr, len, data, 8)) {
>                 PR_ERROR("Unable to write memory\n");
>                 err = 3;
>         }
> --
> 2.35.1
>
> --
> Pdbg mailing list
> Pdbg at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/pdbg


More information about the Pdbg mailing list