qemu-riscv
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH v4 2/4] Adding basic custom/vendor CSR handling mechanism


From: Bin Meng
Subject: Re: [RFC PATCH v4 2/4] Adding basic custom/vendor CSR handling mechanism
Date: Fri, 6 Aug 2021 11:35:36 +0800

+Alistair

On Fri, Aug 6, 2021 at 1:58 AM Ruinland Chuan-Tzu Tsai
<ruinland@andestech.com> wrote:
>
> From: Ruinalnd ChuanTzu Tsai <ruinland@andestech.com>
>
> For now we add a custom CSR handling mechanism to handle non-standard CSR read
> or write.
>
> The write_stub() and read_zero() are provided for quick placeholder usage if
> such CSRs' behavior are expected to fail-over in its user code.
>
> Signed-off-by: Dylan Jhong <dylan@andestech.com>
> ---
>  target/riscv/cpu.c             | 23 ++++++++++
>  target/riscv/cpu.h             | 31 ++++++++++++-
>  target/riscv/cpu_bits.h        |  4 ++
>  target/riscv/csr.c             | 83 ++++++++++++++++++++++++++++------
>  target/riscv/custom_cpu_bits.h |  8 ++++
>  5 files changed, 134 insertions(+), 15 deletions(-)
>  create mode 100644 target/riscv/custom_cpu_bits.h
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 7401325..3a638b5 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -144,6 +144,29 @@ static void set_resetvec(CPURISCVState *env, 
> target_ulong resetvec)
>  #endif
>  }
>
> +#if defined(CONFIG_RISCV_CUSTOM)
> +static void setup_custom_csr(CPURISCVState *env,
> +                             riscv_custom_csr_operations csr_map_struct[]
> +                             ) {

{ should be put to the next line, per QEMU coding convention. Please
fix this globally in this series.

> +
> +    env->custom_csr_map = g_hash_table_new_full(g_direct_hash, \
> +                                                g_direct_equal, \
> +                                                NULL, NULL);

Is it possible to juse use g_hash_table_new() directly, with both 2
parameters being NULL, given you don't provide the destroy hooks?
like:

    env->custom_csr_map = g_hash_table_new(NULL, NULL);

> +
> +
> +    int i;

nits: please move this to the beginning of this function.

> +    for (i = 0; i < MAX_CUSTOM_CSR_NUM; i++) {
> +        if (csr_map_struct[i].csrno != 0) {
> +            g_hash_table_insert(env->custom_csr_map,
> +                GINT_TO_POINTER(csr_map_struct[i].csrno),
> +                &csr_map_struct[i].csr_opset);
> +        } else {
> +            break;

break? I think we should continue the loop.

> +        }
> +    }
> +}
> +#endif
> +
>  static void riscv_any_cpu_init(Object *obj)
>  {
>      CPURISCVState *env = &RISCV_CPU(obj)->env;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 0edb282..52df9bb 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -239,6 +239,16 @@ struct CPURISCVState {
>
>      /* Fields from here on are preserved across CPU reset. */
>      QEMUTimer *timer; /* Internal timer */
> +
> +    /*
> +     * The reason why we have an opset map for custom CSRs and a seperated
> +     * storage map is that we might have heterogeneous architecture, in which
> +     * different harts have different custom CSRs.
> +     * Custom CSR opset map
> +     */
> +    GHashTable *custom_csr_map;
> +    /* Custom CSR val holder */
> +    void *custom_csr_val;
>  };
>
>  OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
> @@ -485,17 +495,36 @@ typedef struct {
>      riscv_csr_op_fn op;
>  } riscv_csr_operations;
>
> +typedef struct {
> +    int csrno;
> +    riscv_csr_operations csr_opset;
> +    } riscv_custom_csr_operations;

} should be put in the beginning without space. Please fix this
globally in this series.

> +
> +/*
> + * The reason why we have an abstraction here is that : We could have CSR
> + * number M on hart A is an alias of CSR number N on hart B. So we make a
> + * CSR number to value address map.
> + */
> +typedef struct  {
> +    int csrno;
> +    target_ulong val;
> +    } riscv_custom_csr_vals;
> +

It looks this struct is not used by any patch in this series?

>  /* CSR function table constants */
>  enum {
> -    CSR_TABLE_SIZE = 0x1000
> +    CSR_TABLE_SIZE = 0x1000,
> +    MAX_CUSTOM_CSR_NUM = 100

To be consistent, name this to be: CUSTOM_CSR_TABLE_SIZE

>  };
>
>  /* CSR function table */
> +extern int andes_custom_csr_size;
> +extern riscv_custom_csr_operations 
> andes_custom_csr_table[MAX_CUSTOM_CSR_NUM];

The above 2 should not be in this patch.

>  extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
>
>  void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
>  void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
>
> +

This is unnecessary.

>  void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
>
>  #endif /* RISCV_CPU_H */
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index caf4599..de77242 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -593,3 +593,7 @@
>  #define MIE_SSIE                           (1 << IRQ_S_SOFT)
>  #define MIE_USIE                           (1 << IRQ_U_SOFT)
>  #endif
> +
> +#if defined(CONFIG_RISCV_CUSTOM)
> +#include "custom_cpu_bits.h"
> +#endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index fd2e636..1c4dc94 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -137,7 +137,8 @@ static int ctr32(CPURISCVState *env, int csrno)
>      return ctr(env, csrno);
>  }
>
> -#if !defined(CONFIG_USER_ONLY)
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wunused-function"

Use __attribute__((__unused__)), so we don't need to use GCC push/pop

>  static int any(CPURISCVState *env, int csrno)
>  {
>      return 0;
> @@ -152,6 +153,25 @@ static int any32(CPURISCVState *env, int csrno)
>      return any(env, csrno);
>
>  }
> +#pragma GCC diagnostic pop
> +
> +/* Machine Information Registers */
> +static int read_zero(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    return *val = 0;
> +}
> +
> +/*
> + * XXX: This is just a write stub for developing custom CSR handler,

Remove XXX

> + * if the behavior of writting such CSR is not presentable in QEMU and 
> doesn't

typo: writing.

Is that present, or presentable?

> + * affect the functionality, just stub it.
> + */
> +static int write_stub(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    return 0;
> +}
> +
> +#if !defined(CONFIG_USER_ONLY)
>
>  static int smode(CPURISCVState *env, int csrno)
>  {
> @@ -435,11 +455,6 @@ static const char valid_vm_1_10_64[16] = {
>      [VM_1_10_SV57] = 1
>  };
>
> -/* Machine Information Registers */
> -static int read_zero(CPURISCVState *env, int csrno, target_ulong *val)
> -{
> -    return *val = 0;
> -}
>
>  static int read_mhartid(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> @@ -1264,6 +1279,18 @@ static int write_pmpaddr(CPURISCVState *env, int 
> csrno, target_ulong val)
>
>  #endif
>
> +
> +#if defined(CONFIG_RISCV_CUSTOM)
> +/* Custom CSR related routines and data structures */
> +
> +static gpointer is_custom_csr(CPURISCVState *env, int csrno)

The function name suggests that the return value should be of bool
type. Suggest we do:

static bool is_custom_csr(CPURISCVState *env, int csrno,
riscv_custom_csr_operations *custom_csr_ops)

> +{
> +    gpointer ret;
> +    ret = g_hash_table_lookup(env->custom_csr_map, GINT_TO_POINTER(csrno));
> +    return ret;
> +}
> +#endif
> +
>  /*
>   * riscv_csrrw - read and/or update control and status register
>   *
> @@ -1273,12 +1300,19 @@ static int write_pmpaddr(CPURISCVState *env, int 
> csrno, target_ulong val)
>   * csrrc  <->  riscv_csrrw(env, csrno, ret_value, 0, value);
>   */
>
> +
> +

Unnecessary changes

>  int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
>                  target_ulong new_value, target_ulong write_mask)
>  {
>      int ret;
>      target_ulong old_value;
>      RISCVCPU *cpu = env_archcpu(env);
> +    #if !defined(CONFIG_RISCV_CUSTOM)

Please make sure #if starts from the beginning of this line, without space ahead

> +    riscv_csr_operations *csrop = &csr_ops[csrno];

nits: name this variable to csr_ops

> +    #else
> +    riscv_csr_operations *csrop;
> +    #endif
>
>      /* check privileges and return -1 if check fails */
>  #if !defined(CONFIG_USER_ONLY)
> @@ -1300,6 +1334,7 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
> target_ulong *ret_value,
>          (!env->debugger && (effective_priv < get_field(csrno, 0x300)))) {
>          return -RISCV_EXCP_ILLEGAL_INST;
>      }
> +
>  #endif
>
>      /* ensure the CSR extension is enabled. */
> @@ -1307,27 +1342,43 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
> target_ulong *ret_value,
>          return -RISCV_EXCP_ILLEGAL_INST;
>      }
>
> +    /* try handle_custom_csr */
> +
> +    #if defined(CONFIG_RISCV_CUSTOM)
> +    if (unlikely(env->custom_csr_map != NULL)) {
> +        riscv_csr_operations *custom_csr_opset = (riscv_csr_operations *)
> +            is_custom_csr(env, csrno);
> +        if (NULL != custom_csr_opset) {
> +            csrop = custom_csr_opset;
> +            } else {
> +            csrop = &csr_ops[csrno];
> +            }
> +        } else {
> +        csrop = &csr_ops[csrno];
> +        }
> +    #endif
> +
>      /* check predicate */
> -    if (!csr_ops[csrno].predicate) {
> +    if (!csrop->predicate) {
>          return -RISCV_EXCP_ILLEGAL_INST;
>      }
> -    ret = csr_ops[csrno].predicate(env, csrno);
> +    ret = csrop->predicate(env, csrno);
>      if (ret < 0) {
>          return ret;
>      }
>
>      /* execute combined read/write operation if it exists */
> -    if (csr_ops[csrno].op) {
> -        return csr_ops[csrno].op(env, csrno, ret_value, new_value, 
> write_mask);
> +    if (csrop->op) {
> +        return csrop->op(env, csrno, ret_value, new_value, write_mask);
>      }
>
>      /* if no accessor exists then return failure */
> -    if (!csr_ops[csrno].read) {
> +    if (!csrop->read) {
>          return -RISCV_EXCP_ILLEGAL_INST;
>      }
>
>      /* read old value */
> -    ret = csr_ops[csrno].read(env, csrno, &old_value);
> +    ret = csrop->read(env, csrno, &old_value);
>      if (ret < 0) {
>          return ret;
>      }
> @@ -1335,8 +1386,8 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
> target_ulong *ret_value,
>      /* write value if writable and write mask set, otherwise drop writes */
>      if (write_mask) {
>          new_value = (old_value & ~write_mask) | (new_value & write_mask);
> -        if (csr_ops[csrno].write) {
> -            ret = csr_ops[csrno].write(env, csrno, new_value);
> +        if (csrop->write) {
> +            ret = csrop->write(env, csrno, new_value);
>              if (ret < 0) {
>                  return ret;
>              }
> @@ -1369,6 +1420,10 @@ int riscv_csrrw_debug(CPURISCVState *env, int csrno, 
> target_ulong *ret_value,
>      return ret;
>  }
>
> +#if defined(CONFIG_RISCV_CUSTOM)
> +/* Include the custom CSR table here. */

nits: remove the ending .

> +#endif
> +
>  /* Control and Status Register function table */
>  riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>      /* User Floating-Point CSRs */
> diff --git a/target/riscv/custom_cpu_bits.h b/target/riscv/custom_cpu_bits.h
> new file mode 100644
> index 0000000..5df31f8
> --- /dev/null
> +++ b/target/riscv/custom_cpu_bits.h
> @@ -0,0 +1,8 @@
> +/*
> + * RISC-V cpu bits for custom CSR logic.
> + *
> + * Copyright (c) 2021 Andes Technology Corp.
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +/* This file is intentionally left blank at this commit. */

nits: remove the ending .

%s/at/in

Regards,
Bin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]