diff mbox series

[5/5,v3] RISC-V: Add hooks to use the gdb xml files.

Message ID 20190130025708.12811-1-jimw@sifive.com
State New
Headers show
Series RISC-V: Add gdb xml files and gdbstub support. | expand

Commit Message

Jim Wilson Jan. 30, 2019, 2:57 a.m. UTC
The gdb CSR xml file has registers in documentation order, not numerical
order, so we need a table to map the register numbers.  This also adds
fairly standard gdb hooks to access xml specified registers.

Signed-off-by: Jim Wilson <jimw@sifive.com>
---
 target/riscv/cpu.c     |   9 +-
 target/riscv/cpu.h     |   2 +
 target/riscv/gdbstub.c | 373 +++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 372 insertions(+), 12 deletions(-)

Comments

Alistair Francis Feb. 7, 2019, 12:04 a.m. UTC | #1
On Tue, Jan 29, 2019 at 6:58 PM Jim Wilson <jimw@sifive.com> wrote:
>
> The gdb CSR xml file has registers in documentation order, not numerical
> order, so we need a table to map the register numbers.  This also adds
> fairly standard gdb hooks to access xml specified registers.
>
> Signed-off-by: Jim Wilson <jimw@sifive.com>
> ---
>  target/riscv/cpu.c     |   9 +-
>  target/riscv/cpu.h     |   2 +
>  target/riscv/gdbstub.c | 373 +++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 372 insertions(+), 12 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 28d7e53..c23bd01 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -311,6 +311,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>
> +    riscv_cpu_register_gdb_regs_for_features(cs);
> +
>      qemu_init_vcpu(cs);
>      cpu_reset(cs);
>
> @@ -351,7 +353,12 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
>      cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
>      cc->gdb_read_register = riscv_cpu_gdb_read_register;
>      cc->gdb_write_register = riscv_cpu_gdb_write_register;
> -    cc->gdb_num_core_regs = 65;
> +    cc->gdb_num_core_regs = 33;
> +#if defined(TARGET_RISCV32)
> +    cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
> +#elif defined(TARGET_RISCV64)
> +    cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
> +#endif
>      cc->gdb_stop_before_watchpoint = true;
>      cc->disas_set_info = riscv_cpu_disas_set_info;
>  #ifdef CONFIG_USER_ONLY
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index faa46d0..a7dcdb6 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -327,6 +327,8 @@ typedef struct {
>  void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
>  void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
>
> +void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
> +
>  #include "exec/cpu-all.h"
>
>  #endif /* RISCV_CPU_H */
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index 3cabb21..44e19a2 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -21,6 +21,255 @@
>  #include "exec/gdbstub.h"
>  #include "cpu.h"
>
> +/*
> + * The GDB CSR xml files list them in documentation order, not numerical order,
> + * and are missing entries for unnamed CSRs.  So we need to map the gdb numbers
> + * to the hardware numbers.
> + */
> +
> +static int csr_register_map[] = {
> +    CSR_USTATUS,
> +    CSR_UIE,
> +    CSR_UTVEC,
> +    CSR_USCRATCH,
> +    CSR_UEPC,
> +    CSR_UCAUSE,
> +    CSR_UTVAL,
> +    CSR_UIP,
> +    CSR_FFLAGS,
> +    CSR_FRM,
> +    CSR_FCSR,
> +    CSR_CYCLE,
> +    CSR_TIME,
> +    CSR_INSTRET,
> +    CSR_HPMCOUNTER3,
> +    CSR_HPMCOUNTER4,
> +    CSR_HPMCOUNTER5,
> +    CSR_HPMCOUNTER6,
> +    CSR_HPMCOUNTER7,
> +    CSR_HPMCOUNTER8,
> +    CSR_HPMCOUNTER9,
> +    CSR_HPMCOUNTER10,
> +    CSR_HPMCOUNTER11,
> +    CSR_HPMCOUNTER12,
> +    CSR_HPMCOUNTER13,
> +    CSR_HPMCOUNTER14,
> +    CSR_HPMCOUNTER15,
> +    CSR_HPMCOUNTER16,
> +    CSR_HPMCOUNTER17,
> +    CSR_HPMCOUNTER18,
> +    CSR_HPMCOUNTER19,
> +    CSR_HPMCOUNTER20,
> +    CSR_HPMCOUNTER21,
> +    CSR_HPMCOUNTER22,
> +    CSR_HPMCOUNTER23,
> +    CSR_HPMCOUNTER24,
> +    CSR_HPMCOUNTER25,
> +    CSR_HPMCOUNTER26,
> +    CSR_HPMCOUNTER27,
> +    CSR_HPMCOUNTER28,
> +    CSR_HPMCOUNTER29,
> +    CSR_HPMCOUNTER30,
> +    CSR_HPMCOUNTER31,
> +    CSR_CYCLEH,
> +    CSR_TIMEH,
> +    CSR_INSTRETH,
> +    CSR_HPMCOUNTER3H,
> +    CSR_HPMCOUNTER4H,
> +    CSR_HPMCOUNTER5H,
> +    CSR_HPMCOUNTER6H,
> +    CSR_HPMCOUNTER7H,
> +    CSR_HPMCOUNTER8H,
> +    CSR_HPMCOUNTER9H,
> +    CSR_HPMCOUNTER10H,
> +    CSR_HPMCOUNTER11H,
> +    CSR_HPMCOUNTER12H,
> +    CSR_HPMCOUNTER13H,
> +    CSR_HPMCOUNTER14H,
> +    CSR_HPMCOUNTER15H,
> +    CSR_HPMCOUNTER16H,
> +    CSR_HPMCOUNTER17H,
> +    CSR_HPMCOUNTER18H,
> +    CSR_HPMCOUNTER19H,
> +    CSR_HPMCOUNTER20H,
> +    CSR_HPMCOUNTER21H,
> +    CSR_HPMCOUNTER22H,
> +    CSR_HPMCOUNTER23H,
> +    CSR_HPMCOUNTER24H,
> +    CSR_HPMCOUNTER25H,
> +    CSR_HPMCOUNTER26H,
> +    CSR_HPMCOUNTER27H,
> +    CSR_HPMCOUNTER28H,
> +    CSR_HPMCOUNTER29H,
> +    CSR_HPMCOUNTER30H,
> +    CSR_HPMCOUNTER31H,
> +    CSR_SSTATUS,
> +    CSR_SEDELEG,
> +    CSR_SIDELEG,
> +    CSR_SIE,
> +    CSR_STVEC,
> +    CSR_SCOUNTEREN,
> +    CSR_SSCRATCH,
> +    CSR_SEPC,
> +    CSR_SCAUSE,
> +    CSR_STVAL,
> +    CSR_SIP,
> +    CSR_SATP,
> +    CSR_MVENDORID,
> +    CSR_MARCHID,
> +    CSR_MIMPID,
> +    CSR_MHARTID,
> +    CSR_MSTATUS,
> +    CSR_MISA,
> +    CSR_MEDELEG,
> +    CSR_MIDELEG,
> +    CSR_MIE,
> +    CSR_MTVEC,
> +    CSR_MCOUNTEREN,
> +    CSR_MSCRATCH,
> +    CSR_MEPC,
> +    CSR_MCAUSE,
> +    CSR_MTVAL,
> +    CSR_MIP,
> +    CSR_PMPCFG0,
> +    CSR_PMPCFG1,
> +    CSR_PMPCFG2,
> +    CSR_PMPCFG3,
> +    CSR_PMPADDR0,
> +    CSR_PMPADDR1,
> +    CSR_PMPADDR2,
> +    CSR_PMPADDR3,
> +    CSR_PMPADDR4,
> +    CSR_PMPADDR5,
> +    CSR_PMPADDR6,
> +    CSR_PMPADDR7,
> +    CSR_PMPADDR8,
> +    CSR_PMPADDR9,
> +    CSR_PMPADDR10,
> +    CSR_PMPADDR11,
> +    CSR_PMPADDR12,
> +    CSR_PMPADDR13,
> +    CSR_PMPADDR14,
> +    CSR_PMPADDR15,
> +    CSR_MCYCLE,
> +    CSR_MINSTRET,
> +    CSR_MHPMCOUNTER3,
> +    CSR_MHPMCOUNTER4,
> +    CSR_MHPMCOUNTER5,
> +    CSR_MHPMCOUNTER6,
> +    CSR_MHPMCOUNTER7,
> +    CSR_MHPMCOUNTER8,
> +    CSR_MHPMCOUNTER9,
> +    CSR_MHPMCOUNTER10,
> +    CSR_MHPMCOUNTER11,
> +    CSR_MHPMCOUNTER12,
> +    CSR_MHPMCOUNTER13,
> +    CSR_MHPMCOUNTER14,
> +    CSR_MHPMCOUNTER15,
> +    CSR_MHPMCOUNTER16,
> +    CSR_MHPMCOUNTER17,
> +    CSR_MHPMCOUNTER18,
> +    CSR_MHPMCOUNTER19,
> +    CSR_MHPMCOUNTER20,
> +    CSR_MHPMCOUNTER21,
> +    CSR_MHPMCOUNTER22,
> +    CSR_MHPMCOUNTER23,
> +    CSR_MHPMCOUNTER24,
> +    CSR_MHPMCOUNTER25,
> +    CSR_MHPMCOUNTER26,
> +    CSR_MHPMCOUNTER27,
> +    CSR_MHPMCOUNTER28,
> +    CSR_MHPMCOUNTER29,
> +    CSR_MHPMCOUNTER30,
> +    CSR_MHPMCOUNTER31,
> +    CSR_MCYCLEH,
> +    CSR_MINSTRETH,
> +    CSR_MHPMCOUNTER3H,
> +    CSR_MHPMCOUNTER4H,
> +    CSR_MHPMCOUNTER5H,
> +    CSR_MHPMCOUNTER6H,
> +    CSR_MHPMCOUNTER7H,
> +    CSR_MHPMCOUNTER8H,
> +    CSR_MHPMCOUNTER9H,
> +    CSR_MHPMCOUNTER10H,
> +    CSR_MHPMCOUNTER11H,
> +    CSR_MHPMCOUNTER12H,
> +    CSR_MHPMCOUNTER13H,
> +    CSR_MHPMCOUNTER14H,
> +    CSR_MHPMCOUNTER15H,
> +    CSR_MHPMCOUNTER16H,
> +    CSR_MHPMCOUNTER17H,
> +    CSR_MHPMCOUNTER18H,
> +    CSR_MHPMCOUNTER19H,
> +    CSR_MHPMCOUNTER20H,
> +    CSR_MHPMCOUNTER21H,
> +    CSR_MHPMCOUNTER22H,
> +    CSR_MHPMCOUNTER23H,
> +    CSR_MHPMCOUNTER24H,
> +    CSR_MHPMCOUNTER25H,
> +    CSR_MHPMCOUNTER26H,
> +    CSR_MHPMCOUNTER27H,
> +    CSR_MHPMCOUNTER28H,
> +    CSR_MHPMCOUNTER29H,
> +    CSR_MHPMCOUNTER30H,
> +    CSR_MHPMCOUNTER31H,
> +    CSR_MHPMEVENT3,
> +    CSR_MHPMEVENT4,
> +    CSR_MHPMEVENT5,
> +    CSR_MHPMEVENT6,
> +    CSR_MHPMEVENT7,
> +    CSR_MHPMEVENT8,
> +    CSR_MHPMEVENT9,
> +    CSR_MHPMEVENT10,
> +    CSR_MHPMEVENT11,
> +    CSR_MHPMEVENT12,
> +    CSR_MHPMEVENT13,
> +    CSR_MHPMEVENT14,
> +    CSR_MHPMEVENT15,
> +    CSR_MHPMEVENT16,
> +    CSR_MHPMEVENT17,
> +    CSR_MHPMEVENT18,
> +    CSR_MHPMEVENT19,
> +    CSR_MHPMEVENT20,
> +    CSR_MHPMEVENT21,
> +    CSR_MHPMEVENT22,
> +    CSR_MHPMEVENT23,
> +    CSR_MHPMEVENT24,
> +    CSR_MHPMEVENT25,
> +    CSR_MHPMEVENT26,
> +    CSR_MHPMEVENT27,
> +    CSR_MHPMEVENT28,
> +    CSR_MHPMEVENT29,
> +    CSR_MHPMEVENT30,
> +    CSR_MHPMEVENT31,
> +    CSR_TSELECT,
> +    CSR_TDATA1,
> +    CSR_TDATA2,
> +    CSR_TDATA3,
> +    CSR_DCSR,
> +    CSR_DPC,
> +    CSR_DSCRATCH,
> +    CSR_HSTATUS,
> +    CSR_HEDELEG,
> +    CSR_HIDELEG,
> +    CSR_HIE,
> +    CSR_HTVEC,
> +    CSR_HSCRATCH,
> +    CSR_HEPC,
> +    CSR_HCAUSE,
> +    CSR_HBADADDR,
> +    CSR_HIP,
> +    CSR_MBASE,
> +    CSR_MBOUND,
> +    CSR_MIBASE,
> +    CSR_MIBOUND,
> +    CSR_MDBASE,
> +    CSR_MDBOUND,
> +    CSR_MUCOUNTEREN,
> +    CSR_MSCOUNTEREN,
> +    CSR_MHCOUNTEREN,
> +};
> +
>  int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
>  {
>      RISCVCPU *cpu = RISCV_CPU(cs);
> @@ -30,13 +279,6 @@ int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
>          return gdb_get_regl(mem_buf, env->gpr[n]);
>      } else if (n == 32) {
>          return gdb_get_regl(mem_buf, env->pc);
> -    } else if (n < 65) {
> -        return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
> -    } else if (n < 4096 + 65) {
> -        target_ulong val = 0;
> -        if (riscv_csrrw(env, n - 65, &val, 0, 0) == 0) {
> -            return gdb_get_regl(mem_buf, val);
> -        }
>      }
>      return 0;
>  }
> @@ -55,14 +297,123 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
>      } else if (n == 32) {
>          env->pc = ldtul_p(mem_buf);
>          return sizeof(target_ulong);
> -    } else if (n < 65) {
> -        env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
> +    }
> +    return 0;
> +}
> +
> +static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
> +{
> +    if (n < 32) {
> +        return gdb_get_reg64(mem_buf, env->fpr[n]);
> +    } else if (n < 35) {
> +        target_ulong val = 0;
> +        int result;
> +        /*
> +         * CSR_FFLAGS is 0x001, and gdb says it is FP register 32, so we
> +         * subtract 31 to map the gdb FP register number to the CSR number.
> +         * This also works for CSR_FRM and CSR_FCSR.
> +         */
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = true;
> +#endif

Would it not be easier to add an extra argument to the functions
intstead of setting and unsetting this?

That's what you had in the earlier version of this set.

> +        result = riscv_csrrw(env, n - 31, &val, 0, 0);
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = false;
> +#endif
> +        if (result == 0) {
> +            return gdb_get_regl(mem_buf, val);
> +        }
> +

Extra line here as well.

> +    }
> +    return 0;
> +}
> +
> +static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
> +{
> +    if (n < 32) {
> +        env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */
>          return sizeof(uint64_t);
> -    } else if (n < 4096 + 65) {
> +    } else if (n < 35) {
> +        target_ulong val = ldtul_p(mem_buf);
> +        int result;
> +        /*
> +         * CSR_FFLAGS is 0x001, and gdb says it is FP register 32, so we
> +         * subtract 31 to map the gdb FP register number to the CSR number.
> +         * This also works for CSR_FRM and CSR_FCSR.
> +         */
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = true;
> +#endif
> +        result = riscv_csrrw(env, n - 31, NULL, val, -1);
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = false;
> +#endif
> +        if (result == 0) {
> +            return sizeof(target_ulong);
> +        }
> +    }
> +    return 0;
> +}
> +
> +static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
> +{
> +    if (n < ARRAY_SIZE(csr_register_map)) {
> +        target_ulong val = 0;
> +        int result;
> +
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = true;
> +#endif
> +        result = riscv_csrrw(env, csr_register_map[n], &val, 0, 0);
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = false;
> +#endif
> +        if (result == 0) {
> +            return gdb_get_regl(mem_buf, val);
> +        }
> +    }
> +    return 0;
> +}
> +
> +static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
> +{
> +    if (n < ARRAY_SIZE(csr_register_map)) {
>          target_ulong val = ldtul_p(mem_buf);
> -        if (riscv_csrrw(env, n - 65, NULL, val, -1) == 0) {
> +        int result;
> +
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = true;
> +#endif
> +        result = riscv_csrrw(env, csr_register_map[n], NULL, val, -1);
> +#if !defined(CONFIG_USER_ONLY)
> +        env->debugger = false;
> +#endif
> +        if (result == 0) {
>              return sizeof(target_ulong);
>          }
>      }
>      return 0;
>  }
> +
> +void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(cs);
> +    CPURISCVState *env = &cpu->env;
> +#if defined(TARGET_RISCV32)
> +    if (env->misa & RVF) {
> +        gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
> +                                 35, "riscv-32bit-fpu.xml", 0);
> +    }
> +
> +    gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> +                             4096, "riscv-32bit-csr.xml", 0);
> +#elif defined(TARGET_RISCV64)
> +    if (env->misa & RVF) {
> +        gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
> +                                 35, "riscv-64bit-fpu.xml", 0);
> +    }
> +
> +    gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> +                             4096, "riscv-64bit-csr.xml", 0);
> +#endif

Besides the two comments this looks good :)

Alistair

> +}
> --
> 2.7.4
>
>
Jim Wilson Feb. 7, 2019, 2:05 a.m. UTC | #2
On Wed, Feb 6, 2019 at 4:04 PM Alistair Francis <alistair23@gmail.com> wrote:
> Would it not be easier to add an extra argument to the functions
> intstead of setting and unsetting this?
>
> That's what you had in the earlier version of this set.

The csr support was rewritten, and is now a table of functions.  If I
change the type signature for one function in a table column I have to
change them all.  This means I have to change the type signature of
about 50 functions, the vast majority of which will never use the new
argument.  I was hoping to avoid that, so I added a variable into the
cpu state instead.  In the old patch, before the csr rewrite, I only
had to change the type signature of a couple of functions, most of
which did use the new argument, so that was reasonable at the time.

If I do need to change a lot of type signatures, what about attribute
((unused))?  I see that there is a ATTRIBUTE_UNUSED in the disas dir
but it is apparently not used outside there, and only defined in
include/disas/bfd.h.  I see a few scattered uses of
attribute((unused)) but that seems unwise for portability reasons.
Maybe qemu doesn't care about unused arguments/parameters?

Jim
Richard Henderson Feb. 7, 2019, 12:04 p.m. UTC | #3
On 2/7/19 2:05 AM, Jim Wilson wrote:
> Maybe qemu doesn't care about unused arguments/parameters?

We do not.


r~
Alistair Francis Feb. 8, 2019, 6:16 p.m. UTC | #4
On Wed, Feb 6, 2019 at 6:05 PM Jim Wilson <jimw@sifive.com> wrote:
>
> On Wed, Feb 6, 2019 at 4:04 PM Alistair Francis <alistair23@gmail.com> wrote:
> > Would it not be easier to add an extra argument to the functions
> > intstead of setting and unsetting this?
> >
> > That's what you had in the earlier version of this set.
>
> The csr support was rewritten, and is now a table of functions.  If I
> change the type signature for one function in a table column I have to
> change them all.  This means I have to change the type signature of
> about 50 functions, the vast majority of which will never use the new
> argument.  I was hoping to avoid that, so I added a variable into the
> cpu state instead.  In the old patch, before the csr rewrite, I only
> had to change the type signature of a couple of functions, most of
> which did use the new argument, so that was reasonable at the time.

Ah good point.

Can we just write a wrapper function then that sets and unsets the variable?

Something like this:

riscv_csrrw_debug(...) {
    #if !defined(CONFIG_USER_ONLY)
            env->debugger = true;
    #endif
            result = riscv_csrrw(env, ...);
    #if !defined(CONFIG_USER_ONLY)
            env->debugger = false;
    #endif
}

Alistair

>
> If I do need to change a lot of type signatures, what about attribute
> ((unused))?  I see that there is a ATTRIBUTE_UNUSED in the disas dir
> but it is apparently not used outside there, and only defined in
> include/disas/bfd.h.  I see a few scattered uses of
> attribute((unused)) but that seems unwise for portability reasons.
> Maybe qemu doesn't care about unused arguments/parameters?
>
> Jim
Jim Wilson Feb. 8, 2019, 7:08 p.m. UTC | #5
On Fri, Feb 8, 2019 at 10:17 AM Alistair Francis <alistair23@gmail.com> wrote:
> Can we just write a wrapper function then that sets and unsets the variable?
> Something like this:
>
> riscv_csrrw_debug(...) {
>     #if !defined(CONFIG_USER_ONLY)
>             env->debugger = true;
>     #endif
>             result = riscv_csrrw(env, ...);
>     #if !defined(CONFIG_USER_ONLY)
>             env->debugger = false;
>     #endif
> }

Yes, that would work.  Do you want me to resubmit a fixed part 5 patch?

Jim
Alistair Francis Feb. 8, 2019, 7:28 p.m. UTC | #6
On Fri, Feb 8, 2019 at 11:09 AM Jim Wilson <jimw@sifive.com> wrote:
>
> On Fri, Feb 8, 2019 at 10:17 AM Alistair Francis <alistair23@gmail.com> wrote:
> > Can we just write a wrapper function then that sets and unsets the variable?
> > Something like this:
> >
> > riscv_csrrw_debug(...) {
> >     #if !defined(CONFIG_USER_ONLY)
> >             env->debugger = true;
> >     #endif
> >             result = riscv_csrrw(env, ...);
> >     #if !defined(CONFIG_USER_ONLY)
> >             env->debugger = false;
> >     #endif
> > }
>
> Yes, that would work.  Do you want me to resubmit a fixed part 5 patch?

It's probably best to send out a new version of the whole series.
Include all the Reviewed-by tags and then that should be the last
version and Palmer can apply that series directly.

Alistair

>
> Jim
Palmer Dabbelt Feb. 11, 2019, 6:17 p.m. UTC | #7
On Fri, 08 Feb 2019 11:28:48 PST (-0800), alistair23@gmail.com wrote:
> On Fri, Feb 8, 2019 at 11:09 AM Jim Wilson <jimw@sifive.com> wrote:
>>
>> On Fri, Feb 8, 2019 at 10:17 AM Alistair Francis <alistair23@gmail.com> wrote:
>> > Can we just write a wrapper function then that sets and unsets the variable?
>> > Something like this:
>> >
>> > riscv_csrrw_debug(...) {
>> >     #if !defined(CONFIG_USER_ONLY)
>> >             env->debugger = true;
>> >     #endif
>> >             result = riscv_csrrw(env, ...);
>> >     #if !defined(CONFIG_USER_ONLY)
>> >             env->debugger = false;
>> >     #endif
>> > }
>>
>> Yes, that would work.  Do you want me to resubmit a fixed part 5 patch?
>
> It's probably best to send out a new version of the whole series.
> Include all the Reviewed-by tags and then that should be the last
> version and Palmer can apply that series directly.

Ya, that's the best way to do it.  That way everyone is on the same page about 
exactly what is going in.
diff mbox series

Patch

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 28d7e53..c23bd01 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -311,6 +311,8 @@  static void riscv_cpu_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    riscv_cpu_register_gdb_regs_for_features(cs);
+
     qemu_init_vcpu(cs);
     cpu_reset(cs);
 
@@ -351,7 +353,12 @@  static void riscv_cpu_class_init(ObjectClass *c, void *data)
     cc->synchronize_from_tb = riscv_cpu_synchronize_from_tb;
     cc->gdb_read_register = riscv_cpu_gdb_read_register;
     cc->gdb_write_register = riscv_cpu_gdb_write_register;
-    cc->gdb_num_core_regs = 65;
+    cc->gdb_num_core_regs = 33;
+#if defined(TARGET_RISCV32)
+    cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
+#elif defined(TARGET_RISCV64)
+    cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
+#endif
     cc->gdb_stop_before_watchpoint = true;
     cc->disas_set_info = riscv_cpu_disas_set_info;
 #ifdef CONFIG_USER_ONLY
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index faa46d0..a7dcdb6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -327,6 +327,8 @@  typedef struct {
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
 void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
 
+void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
+
 #include "exec/cpu-all.h"
 
 #endif /* RISCV_CPU_H */
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 3cabb21..44e19a2 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -21,6 +21,255 @@ 
 #include "exec/gdbstub.h"
 #include "cpu.h"
 
+/*
+ * The GDB CSR xml files list them in documentation order, not numerical order,
+ * and are missing entries for unnamed CSRs.  So we need to map the gdb numbers
+ * to the hardware numbers.
+ */
+
+static int csr_register_map[] = {
+    CSR_USTATUS,
+    CSR_UIE,
+    CSR_UTVEC,
+    CSR_USCRATCH,
+    CSR_UEPC,
+    CSR_UCAUSE,
+    CSR_UTVAL,
+    CSR_UIP,
+    CSR_FFLAGS,
+    CSR_FRM,
+    CSR_FCSR,
+    CSR_CYCLE,
+    CSR_TIME,
+    CSR_INSTRET,
+    CSR_HPMCOUNTER3,
+    CSR_HPMCOUNTER4,
+    CSR_HPMCOUNTER5,
+    CSR_HPMCOUNTER6,
+    CSR_HPMCOUNTER7,
+    CSR_HPMCOUNTER8,
+    CSR_HPMCOUNTER9,
+    CSR_HPMCOUNTER10,
+    CSR_HPMCOUNTER11,
+    CSR_HPMCOUNTER12,
+    CSR_HPMCOUNTER13,
+    CSR_HPMCOUNTER14,
+    CSR_HPMCOUNTER15,
+    CSR_HPMCOUNTER16,
+    CSR_HPMCOUNTER17,
+    CSR_HPMCOUNTER18,
+    CSR_HPMCOUNTER19,
+    CSR_HPMCOUNTER20,
+    CSR_HPMCOUNTER21,
+    CSR_HPMCOUNTER22,
+    CSR_HPMCOUNTER23,
+    CSR_HPMCOUNTER24,
+    CSR_HPMCOUNTER25,
+    CSR_HPMCOUNTER26,
+    CSR_HPMCOUNTER27,
+    CSR_HPMCOUNTER28,
+    CSR_HPMCOUNTER29,
+    CSR_HPMCOUNTER30,
+    CSR_HPMCOUNTER31,
+    CSR_CYCLEH,
+    CSR_TIMEH,
+    CSR_INSTRETH,
+    CSR_HPMCOUNTER3H,
+    CSR_HPMCOUNTER4H,
+    CSR_HPMCOUNTER5H,
+    CSR_HPMCOUNTER6H,
+    CSR_HPMCOUNTER7H,
+    CSR_HPMCOUNTER8H,
+    CSR_HPMCOUNTER9H,
+    CSR_HPMCOUNTER10H,
+    CSR_HPMCOUNTER11H,
+    CSR_HPMCOUNTER12H,
+    CSR_HPMCOUNTER13H,
+    CSR_HPMCOUNTER14H,
+    CSR_HPMCOUNTER15H,
+    CSR_HPMCOUNTER16H,
+    CSR_HPMCOUNTER17H,
+    CSR_HPMCOUNTER18H,
+    CSR_HPMCOUNTER19H,
+    CSR_HPMCOUNTER20H,
+    CSR_HPMCOUNTER21H,
+    CSR_HPMCOUNTER22H,
+    CSR_HPMCOUNTER23H,
+    CSR_HPMCOUNTER24H,
+    CSR_HPMCOUNTER25H,
+    CSR_HPMCOUNTER26H,
+    CSR_HPMCOUNTER27H,
+    CSR_HPMCOUNTER28H,
+    CSR_HPMCOUNTER29H,
+    CSR_HPMCOUNTER30H,
+    CSR_HPMCOUNTER31H,
+    CSR_SSTATUS,
+    CSR_SEDELEG,
+    CSR_SIDELEG,
+    CSR_SIE,
+    CSR_STVEC,
+    CSR_SCOUNTEREN,
+    CSR_SSCRATCH,
+    CSR_SEPC,
+    CSR_SCAUSE,
+    CSR_STVAL,
+    CSR_SIP,
+    CSR_SATP,
+    CSR_MVENDORID,
+    CSR_MARCHID,
+    CSR_MIMPID,
+    CSR_MHARTID,
+    CSR_MSTATUS,
+    CSR_MISA,
+    CSR_MEDELEG,
+    CSR_MIDELEG,
+    CSR_MIE,
+    CSR_MTVEC,
+    CSR_MCOUNTEREN,
+    CSR_MSCRATCH,
+    CSR_MEPC,
+    CSR_MCAUSE,
+    CSR_MTVAL,
+    CSR_MIP,
+    CSR_PMPCFG0,
+    CSR_PMPCFG1,
+    CSR_PMPCFG2,
+    CSR_PMPCFG3,
+    CSR_PMPADDR0,
+    CSR_PMPADDR1,
+    CSR_PMPADDR2,
+    CSR_PMPADDR3,
+    CSR_PMPADDR4,
+    CSR_PMPADDR5,
+    CSR_PMPADDR6,
+    CSR_PMPADDR7,
+    CSR_PMPADDR8,
+    CSR_PMPADDR9,
+    CSR_PMPADDR10,
+    CSR_PMPADDR11,
+    CSR_PMPADDR12,
+    CSR_PMPADDR13,
+    CSR_PMPADDR14,
+    CSR_PMPADDR15,
+    CSR_MCYCLE,
+    CSR_MINSTRET,
+    CSR_MHPMCOUNTER3,
+    CSR_MHPMCOUNTER4,
+    CSR_MHPMCOUNTER5,
+    CSR_MHPMCOUNTER6,
+    CSR_MHPMCOUNTER7,
+    CSR_MHPMCOUNTER8,
+    CSR_MHPMCOUNTER9,
+    CSR_MHPMCOUNTER10,
+    CSR_MHPMCOUNTER11,
+    CSR_MHPMCOUNTER12,
+    CSR_MHPMCOUNTER13,
+    CSR_MHPMCOUNTER14,
+    CSR_MHPMCOUNTER15,
+    CSR_MHPMCOUNTER16,
+    CSR_MHPMCOUNTER17,
+    CSR_MHPMCOUNTER18,
+    CSR_MHPMCOUNTER19,
+    CSR_MHPMCOUNTER20,
+    CSR_MHPMCOUNTER21,
+    CSR_MHPMCOUNTER22,
+    CSR_MHPMCOUNTER23,
+    CSR_MHPMCOUNTER24,
+    CSR_MHPMCOUNTER25,
+    CSR_MHPMCOUNTER26,
+    CSR_MHPMCOUNTER27,
+    CSR_MHPMCOUNTER28,
+    CSR_MHPMCOUNTER29,
+    CSR_MHPMCOUNTER30,
+    CSR_MHPMCOUNTER31,
+    CSR_MCYCLEH,
+    CSR_MINSTRETH,
+    CSR_MHPMCOUNTER3H,
+    CSR_MHPMCOUNTER4H,
+    CSR_MHPMCOUNTER5H,
+    CSR_MHPMCOUNTER6H,
+    CSR_MHPMCOUNTER7H,
+    CSR_MHPMCOUNTER8H,
+    CSR_MHPMCOUNTER9H,
+    CSR_MHPMCOUNTER10H,
+    CSR_MHPMCOUNTER11H,
+    CSR_MHPMCOUNTER12H,
+    CSR_MHPMCOUNTER13H,
+    CSR_MHPMCOUNTER14H,
+    CSR_MHPMCOUNTER15H,
+    CSR_MHPMCOUNTER16H,
+    CSR_MHPMCOUNTER17H,
+    CSR_MHPMCOUNTER18H,
+    CSR_MHPMCOUNTER19H,
+    CSR_MHPMCOUNTER20H,
+    CSR_MHPMCOUNTER21H,
+    CSR_MHPMCOUNTER22H,
+    CSR_MHPMCOUNTER23H,
+    CSR_MHPMCOUNTER24H,
+    CSR_MHPMCOUNTER25H,
+    CSR_MHPMCOUNTER26H,
+    CSR_MHPMCOUNTER27H,
+    CSR_MHPMCOUNTER28H,
+    CSR_MHPMCOUNTER29H,
+    CSR_MHPMCOUNTER30H,
+    CSR_MHPMCOUNTER31H,
+    CSR_MHPMEVENT3,
+    CSR_MHPMEVENT4,
+    CSR_MHPMEVENT5,
+    CSR_MHPMEVENT6,
+    CSR_MHPMEVENT7,
+    CSR_MHPMEVENT8,
+    CSR_MHPMEVENT9,
+    CSR_MHPMEVENT10,
+    CSR_MHPMEVENT11,
+    CSR_MHPMEVENT12,
+    CSR_MHPMEVENT13,
+    CSR_MHPMEVENT14,
+    CSR_MHPMEVENT15,
+    CSR_MHPMEVENT16,
+    CSR_MHPMEVENT17,
+    CSR_MHPMEVENT18,
+    CSR_MHPMEVENT19,
+    CSR_MHPMEVENT20,
+    CSR_MHPMEVENT21,
+    CSR_MHPMEVENT22,
+    CSR_MHPMEVENT23,
+    CSR_MHPMEVENT24,
+    CSR_MHPMEVENT25,
+    CSR_MHPMEVENT26,
+    CSR_MHPMEVENT27,
+    CSR_MHPMEVENT28,
+    CSR_MHPMEVENT29,
+    CSR_MHPMEVENT30,
+    CSR_MHPMEVENT31,
+    CSR_TSELECT,
+    CSR_TDATA1,
+    CSR_TDATA2,
+    CSR_TDATA3,
+    CSR_DCSR,
+    CSR_DPC,
+    CSR_DSCRATCH,
+    CSR_HSTATUS,
+    CSR_HEDELEG,
+    CSR_HIDELEG,
+    CSR_HIE,
+    CSR_HTVEC,
+    CSR_HSCRATCH,
+    CSR_HEPC,
+    CSR_HCAUSE,
+    CSR_HBADADDR,
+    CSR_HIP,
+    CSR_MBASE,
+    CSR_MBOUND,
+    CSR_MIBASE,
+    CSR_MIBOUND,
+    CSR_MDBASE,
+    CSR_MDBOUND,
+    CSR_MUCOUNTEREN,
+    CSR_MSCOUNTEREN,
+    CSR_MHCOUNTEREN,
+};
+
 int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
@@ -30,13 +279,6 @@  int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
         return gdb_get_regl(mem_buf, env->gpr[n]);
     } else if (n == 32) {
         return gdb_get_regl(mem_buf, env->pc);
-    } else if (n < 65) {
-        return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
-    } else if (n < 4096 + 65) {
-        target_ulong val = 0;
-        if (riscv_csrrw(env, n - 65, &val, 0, 0) == 0) {
-            return gdb_get_regl(mem_buf, val);
-        }
     }
     return 0;
 }
@@ -55,14 +297,123 @@  int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     } else if (n == 32) {
         env->pc = ldtul_p(mem_buf);
         return sizeof(target_ulong);
-    } else if (n < 65) {
-        env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
+    }
+    return 0;
+}
+
+static int riscv_gdb_get_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 32) {
+        return gdb_get_reg64(mem_buf, env->fpr[n]);
+    } else if (n < 35) {
+        target_ulong val = 0;
+        int result;
+        /*
+         * CSR_FFLAGS is 0x001, and gdb says it is FP register 32, so we
+         * subtract 31 to map the gdb FP register number to the CSR number.
+         * This also works for CSR_FRM and CSR_FCSR.
+         */
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = true;
+#endif
+        result = riscv_csrrw(env, n - 31, &val, 0, 0);
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = false;
+#endif
+        if (result == 0) {
+            return gdb_get_regl(mem_buf, val);
+        }
+
+    }
+    return 0;
+}
+
+static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 32) {
+        env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */
         return sizeof(uint64_t);
-    } else if (n < 4096 + 65) {
+    } else if (n < 35) {
+        target_ulong val = ldtul_p(mem_buf);
+        int result;
+        /*
+         * CSR_FFLAGS is 0x001, and gdb says it is FP register 32, so we
+         * subtract 31 to map the gdb FP register number to the CSR number.
+         * This also works for CSR_FRM and CSR_FCSR.
+         */
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = true;
+#endif
+        result = riscv_csrrw(env, n - 31, NULL, val, -1);
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = false;
+#endif
+        if (result == 0) {
+            return sizeof(target_ulong);
+        }
+    }
+    return 0;
+}
+
+static int riscv_gdb_get_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
+{
+    if (n < ARRAY_SIZE(csr_register_map)) {
+        target_ulong val = 0;
+        int result;
+
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = true;
+#endif
+        result = riscv_csrrw(env, csr_register_map[n], &val, 0, 0);
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = false;
+#endif
+        if (result == 0) {
+            return gdb_get_regl(mem_buf, val);
+        }
+    }
+    return 0;
+}
+
+static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
+{
+    if (n < ARRAY_SIZE(csr_register_map)) {
         target_ulong val = ldtul_p(mem_buf);
-        if (riscv_csrrw(env, n - 65, NULL, val, -1) == 0) {
+        int result;
+
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = true;
+#endif
+        result = riscv_csrrw(env, csr_register_map[n], NULL, val, -1);
+#if !defined(CONFIG_USER_ONLY)
+        env->debugger = false;
+#endif
+        if (result == 0) {
             return sizeof(target_ulong);
         }
     }
     return 0;
 }
+
+void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+#if defined(TARGET_RISCV32)
+    if (env->misa & RVF) {
+        gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
+                                 35, "riscv-32bit-fpu.xml", 0);
+    }
+
+    gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
+                             4096, "riscv-32bit-csr.xml", 0);
+#elif defined(TARGET_RISCV64)
+    if (env->misa & RVF) {
+        gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
+                                 35, "riscv-64bit-fpu.xml", 0);
+    }
+
+    gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
+                             4096, "riscv-64bit-csr.xml", 0);
+#endif
+}