diff mbox series

[02/22] target/riscv: introduce RISCVCPUDef

Message ID 20250206182711.2420505-3-pbonzini@redhat.com (mailing list archive)
State New
Headers show
Series target/riscv: declarative CPU definitions | expand

Commit Message

Paolo Bonzini Feb. 6, 2025, 6:26 p.m. UTC
Start putting all the CPU definitions in a struct.  Later this will replace
instance_init functions with declarative code, for now just remove the
ugly cast of class_data.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/riscv/cpu.h |  4 ++++
 target/riscv/cpu.c | 26 +++++++++++++++++---------
 2 files changed, 21 insertions(+), 9 deletions(-)

Comments

Richard Henderson Feb. 6, 2025, 9:16 p.m. UTC | #1
On 2/6/25 10:26, Paolo Bonzini wrote:
> Start putting all the CPU definitions in a struct.  Later this will replace
> instance_init functions with declarative code, for now just remove the
> ugly cast of class_data.
...
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ed9da692030..29cfae38b75 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -2955,7 +2955,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
>   {
>       RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
>   
> -    mcc->misa_mxl_max = (uint32_t)(uintptr_t)data;
> +    mcc->misa_mxl_max = ((RISCVCPUDef *)data)->misa_mxl_max;
>       riscv_cpu_validate_misa_mxl(mcc);
>   }
>   
> @@ -3051,40 +3051,48 @@ void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename)
>   }
>   #endif
>   
> -#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max, initfn) \
> +#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max_, initfn) \
>       {                                                       \
>           .name = (type_name),                                \
>           .parent = TYPE_RISCV_DYNAMIC_CPU,                   \
>           .instance_init = (initfn),                          \
>           .class_init = riscv_cpu_class_init,                 \
> -        .class_data = (void *)(misa_mxl_max)                \
> +        .class_data = &((RISCVCPUDef) {                     \
> +             .misa_mxl_max = (misa_mxl_max_),               \
> +        }),                                                 \

Drop the unnecessary ().

It would be nice if this were const, i.e.

   .class_data = (void *) &(const RISCVCPUDef){
       ...
   },

This will in fact create an anonymous object in .rodata.

We have other uses that do the extra casting away const,
e.g. armsse_variants in hw/arm/armsse.c.  Although I suspect
*all* usage of .class_init can and should be with const data.
An unrelated cleanup, to be sure.


r~
Philippe Mathieu-Daudé Feb. 9, 2025, 6:44 p.m. UTC | #2
On 6/2/25 22:16, Richard Henderson wrote:

> It would be nice if this were const, i.e.
> 
>    .class_data = (void *) &(const RISCVCPUDef){
>        ...
>    },
> 
> This will in fact create an anonymous object in .rodata.
> 
> We have other uses that do the extra casting away const,
> e.g. armsse_variants in hw/arm/armsse.c.  Although I suspect
> *all* usage of .class_init can and should be with const data.

The only non-const use I noticed is Xtensa:

static void xtensa_finalize_config(XtensaConfig *config)
{
     if (config->isa_internal) {
         init_libisa(config);
     }

     if (config->gdb_regmap.num_regs == 0 ||
         config->gdb_regmap.num_core_regs == 0) {
         unsigned n_regs = 0;
         unsigned n_core_regs = 0;

         xtensa_count_regs(config, &n_regs, &n_core_regs);
         if (config->gdb_regmap.num_regs == 0) {
             config->gdb_regmap.num_regs = n_regs;
         }
         if (config->gdb_regmap.num_core_regs == 0) {
             config->gdb_regmap.num_core_regs = n_core_regs;
         }
     }
}

static void xtensa_core_class_init(ObjectClass *oc, void *data)
{
     CPUClass *cc = CPU_CLASS(oc);
     XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
     XtensaConfig *config = data;

     xtensa_finalize_config(config);
     ...
Philippe Mathieu-Daudé Feb. 9, 2025, 6:53 p.m. UTC | #3
On 9/2/25 19:44, Philippe Mathieu-Daudé wrote:
> On 6/2/25 22:16, Richard Henderson wrote:
> 
>> It would be nice if this were const, i.e.
>>
>>    .class_data = (void *) &(const RISCVCPUDef){
>>        ...
>>    },
>>
>> This will in fact create an anonymous object in .rodata.
>>
>> We have other uses that do the extra casting away const,
>> e.g. armsse_variants in hw/arm/armsse.c.  Although I suspect
>> *all* usage of .class_init can and should be with const data.
> 
> The only non-const use I noticed is Xtensa:
> 
> static void xtensa_finalize_config(XtensaConfig *config)
> {
>      if (config->isa_internal) {
>          init_libisa(config);
>      }
> 
>      if (config->gdb_regmap.num_regs == 0 ||
>          config->gdb_regmap.num_core_regs == 0) {
>          unsigned n_regs = 0;
>          unsigned n_core_regs = 0;
> 
>          xtensa_count_regs(config, &n_regs, &n_core_regs);
>          if (config->gdb_regmap.num_regs == 0) {
>              config->gdb_regmap.num_regs = n_regs;
>          }
>          if (config->gdb_regmap.num_core_regs == 0) {
>              config->gdb_regmap.num_core_regs = n_core_regs;
>          }
>      }
> }
> 
> static void xtensa_core_class_init(ObjectClass *oc, void *data)
> {
>      CPUClass *cc = CPU_CLASS(oc);
>      XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
>      XtensaConfig *config = data;
> 
>      xtensa_finalize_config(config);
>      ...

Which I suppose can be fixed by calling xtensa_finalize_config()
somewhere within the class register:

void xtensa_register_core(XtensaConfigList *node)
{
     TypeInfo type = {
         .parent = TYPE_XTENSA_CPU,
         .class_init = xtensa_core_class_init,
         .class_data = (void *)node->config,
     };
Philippe Mathieu-Daudé Feb. 9, 2025, 10:20 p.m. UTC | #4
On 9/2/25 19:53, Philippe Mathieu-Daudé wrote:
> On 9/2/25 19:44, Philippe Mathieu-Daudé wrote:
>> On 6/2/25 22:16, Richard Henderson wrote:
>>
>>> It would be nice if this were const, i.e.
>>>
>>>    .class_data = (void *) &(const RISCVCPUDef){
>>>        ...
>>>    },
>>>
>>> This will in fact create an anonymous object in .rodata.
>>>
>>> We have other uses that do the extra casting away const,
>>> e.g. armsse_variants in hw/arm/armsse.c.  Although I suspect
>>> *all* usage of .class_init can and should be with const data.
>>
>> The only non-const use I noticed is Xtensa:

Also the object_class_foreach() callbacks update 'data':

static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
{
     GSList **list = opaque;

     *list = g_slist_prepend(*list, klass);
}

GSList *object_class_get_list(const char *implements_type,
                               bool include_abstract)
{
     GSList *list = NULL;

     object_class_foreach(object_class_get_list_tramp,
                          implements_type, include_abstract, &list);
     return list;
}
Philippe Mathieu-Daudé Feb. 9, 2025, 10:32 p.m. UTC | #5
On 9/2/25 23:20, Philippe Mathieu-Daudé wrote:
> On 9/2/25 19:53, Philippe Mathieu-Daudé wrote:
>> On 9/2/25 19:44, Philippe Mathieu-Daudé wrote:
>>> On 6/2/25 22:16, Richard Henderson wrote:
>>>
>>>> It would be nice if this were const, i.e.
>>>>
>>>>    .class_data = (void *) &(const RISCVCPUDef){
>>>>        ...
>>>>    },
>>>>
>>>> This will in fact create an anonymous object in .rodata.
>>>>
>>>> We have other uses that do the extra casting away const,
>>>> e.g. armsse_variants in hw/arm/armsse.c.  Although I suspect
>>>> *all* usage of .class_init can and should be with const data.
>>>
>>> The only non-const use I noticed is Xtensa:
> 
> Also the object_class_foreach() callbacks update 'data':

Oops I misread, object_class_foreach() correctly takes non-const data :)
diff mbox series

Patch

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 97713681cbe..b2c9302634d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -517,6 +517,10 @@  struct ArchCPU {
     const GPtrArray *decoders;
 };
 
+typedef struct RISCVCPUDef {
+    RISCVMXL misa_mxl_max;  /* max mxl for this cpu */
+} RISCVCPUDef;
+
 /**
  * RISCVCPUClass:
  * @parent_realize: The parent class' realize handler.
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ed9da692030..29cfae38b75 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -2955,7 +2955,7 @@  static void riscv_cpu_class_init(ObjectClass *c, void *data)
 {
     RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
 
-    mcc->misa_mxl_max = (uint32_t)(uintptr_t)data;
+    mcc->misa_mxl_max = ((RISCVCPUDef *)data)->misa_mxl_max;
     riscv_cpu_validate_misa_mxl(mcc);
 }
 
@@ -3051,40 +3051,48 @@  void riscv_isa_write_fdt(RISCVCPU *cpu, void *fdt, char *nodename)
 }
 #endif
 
-#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max, initfn) \
+#define DEFINE_DYNAMIC_CPU(type_name, misa_mxl_max_, initfn) \
     {                                                       \
         .name = (type_name),                                \
         .parent = TYPE_RISCV_DYNAMIC_CPU,                   \
         .instance_init = (initfn),                          \
         .class_init = riscv_cpu_class_init,                 \
-        .class_data = (void *)(misa_mxl_max)                \
+        .class_data = &((RISCVCPUDef) {                     \
+             .misa_mxl_max = (misa_mxl_max_),               \
+        }),                                                 \
     }
 
-#define DEFINE_VENDOR_CPU(type_name, misa_mxl_max, initfn)  \
+#define DEFINE_VENDOR_CPU(type_name, misa_mxl_max_, initfn) \
     {                                                       \
         .name = (type_name),                                \
         .parent = TYPE_RISCV_VENDOR_CPU,                    \
         .instance_init = (initfn),                          \
         .class_init = riscv_cpu_class_init,                 \
-        .class_data = (void *)(misa_mxl_max)                \
+        .class_data = &((RISCVCPUDef) {                     \
+             .misa_mxl_max = (misa_mxl_max_),               \
+        }),                                                 \
     }
 
-#define DEFINE_BARE_CPU(type_name, misa_mxl_max, initfn)    \
+#define DEFINE_BARE_CPU(type_name, misa_mxl_max_, initfn)   \
     {                                                       \
         .name = (type_name),                                \
         .parent = TYPE_RISCV_BARE_CPU,                      \
         .instance_init = (initfn),                          \
         .class_init = riscv_cpu_class_init,                 \
-        .class_data = (void *)(misa_mxl_max)                \
+        .class_data = &((RISCVCPUDef) {                     \
+             .misa_mxl_max = (misa_mxl_max_),               \
+        }),                                                 \
     }
 
-#define DEFINE_PROFILE_CPU(type_name, misa_mxl_max, initfn) \
+#define DEFINE_PROFILE_CPU(type_name, misa_mxl_max_, initfn) \
     {                                                       \
         .name = (type_name),                                \
         .parent = TYPE_RISCV_BARE_CPU,                      \
         .instance_init = (initfn),                          \
         .class_init = riscv_cpu_class_init,                 \
-        .class_data = (void *)(misa_mxl_max)                \
+        .class_data = &((RISCVCPUDef) {                     \
+             .misa_mxl_max = (misa_mxl_max_),               \
+        }),                                                 \
     }
 
 static const TypeInfo riscv_cpu_type_infos[] = {