diff mbox series

[v4,11/11] target/loongarch: Add loongarch32 cpu la132

Message ID 20230808015506.1705140-12-c@jia.je
State New
Headers show
Series Add la32 & va32 mode for loongarch64-softmmu | expand

Commit Message

Jiajie Chen Aug. 8, 2023, 1:54 a.m. UTC
Add la132 as a loongarch32 cpu type and allow virt machine to be used
with la132 instead of la464.

Refactor common init logic out as loongarch_cpu_initfn_common.

Signed-off-by: Jiajie Chen <c@jia.je>
---
 hw/loongarch/virt.c    |  5 ----
 target/loongarch/cpu.c | 54 ++++++++++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 18 deletions(-)

Comments

Jiajie Chen Aug. 8, 2023, 1:59 a.m. UTC | #1
On 2023/8/8 09:54, Jiajie Chen wrote:
> Add la132 as a loongarch32 cpu type and allow virt machine to be used
> with la132 instead of la464.
>
> Refactor common init logic out as loongarch_cpu_initfn_common.
>
> Signed-off-by: Jiajie Chen <c@jia.je>
> ---
>   hw/loongarch/virt.c    |  5 ----
>   target/loongarch/cpu.c | 54 ++++++++++++++++++++++++++++++++----------
>   2 files changed, 41 insertions(+), 18 deletions(-)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index e19b042ce8..af15bf5aaa 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -798,11 +798,6 @@ static void loongarch_init(MachineState *machine)
>           cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
>       }
>   
> -    if (!strstr(cpu_model, "la464")) {
> -        error_report("LoongArch/TCG needs cpu type la464");
> -        exit(1);
> -    }
> -
>       if (ram_size < 1 * GiB) {
>           error_report("ram_size must be greater than 1G.");
>           exit(1);
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 13d4fccbd3..341176817e 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -356,30 +356,18 @@ static bool loongarch_cpu_has_work(CPUState *cs)
>   #endif
>   }
>   
> -static void loongarch_la464_initfn(Object *obj)
> +static void loongarch_cpu_initfn_common(CPULoongArchState *env)
>   {
> -    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> -    CPULoongArchState *env = &cpu->env;
>       int i;
>   
>       for (i = 0; i < 21; i++) {
>           env->cpucfg[i] = 0x0;
>       }
>   
> -    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
> -    env->cpucfg[0] = 0x14c010;  /* PRID */
> -
>       uint32_t data = 0;
> -    data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
>       data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
>       data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
> -    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
> -    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
>       data = FIELD_DP32(data, CPUCFG1, UAL, 1);
> -    data = FIELD_DP32(data, CPUCFG1, RI, 1);
> -    data = FIELD_DP32(data, CPUCFG1, EP, 1);
> -    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
> -    data = FIELD_DP32(data, CPUCFG1, HP, 1);
Sorry, this line should not be removed.
>       data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
>       env->cpucfg[1] = data;
>   
> @@ -439,6 +427,45 @@ static void loongarch_la464_initfn(Object *obj)
>       env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
>   }
>   
> +static void loongarch_la464_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    loongarch_cpu_initfn_common(env);
> +
> +    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
> +    env->cpucfg[0] = 0x14c010;  /* PRID */
> +
> +    uint32_t data = env->cpucfg[1];
> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 2); /* LA64 */
> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); /* 48 bits */
> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); /* 48 bits */
> +    data = FIELD_DP32(data, CPUCFG1, RI, 1);
> +    data = FIELD_DP32(data, CPUCFG1, EP, 1);
> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
> +    env->cpucfg[1] = data;
> +}
> +
> +static void loongarch_la132_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    loongarch_cpu_initfn_common(env);
> +
> +    cpu->dtb_compatible = "loongarch,Loongson-1C103";
> +
> +    uint32_t data = env->cpucfg[1];
> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
> +    data = FIELD_DP32(data, CPUCFG1, RI, 0);
> +    data = FIELD_DP32(data, CPUCFG1, EP, 0);
> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
> +    env->cpucfg[1] = data;
> +}
> +
>   static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
>   {
>       const char *typename = object_class_get_name(OBJECT_CLASS(data));
> @@ -784,5 +811,6 @@ static const TypeInfo loongarch32_cpu_type_infos[] = {
>           .class_size = sizeof(LoongArchCPUClass),
>           .class_init = loongarch32_cpu_class_init,
>       },
> +    DEFINE_LOONGARCH32_CPU_TYPE("la132", loongarch_la132_initfn),
>   };
>   DEFINE_TYPES(loongarch32_cpu_type_infos)
Richard Henderson Aug. 8, 2023, 7:26 p.m. UTC | #2
On 8/7/23 18:54, Jiajie Chen wrote:
> +static void loongarch_la464_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    loongarch_cpu_initfn_common(env);
> +
> +    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
> +    env->cpucfg[0] = 0x14c010;  /* PRID */
> +
> +    uint32_t data = env->cpucfg[1];
> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 2); /* LA64 */
> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); /* 48 bits */
> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); /* 48 bits */
> +    data = FIELD_DP32(data, CPUCFG1, RI, 1);
> +    data = FIELD_DP32(data, CPUCFG1, EP, 1);
> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
> +    env->cpucfg[1] = data;
> +}
> +
> +static void loongarch_la132_initfn(Object *obj)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +    CPULoongArchState *env = &cpu->env;
> +
> +    loongarch_cpu_initfn_common(env);
> +
> +    cpu->dtb_compatible = "loongarch,Loongson-1C103";
> +
> +    uint32_t data = env->cpucfg[1];
> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
> +    data = FIELD_DP32(data, CPUCFG1, RI, 0);
> +    data = FIELD_DP32(data, CPUCFG1, EP, 0);
> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
> +    env->cpucfg[1] = data;
> +}

The use of the loongarch_cpu_initfn_common function is not going to scale.
Compare the set of *_initfn in target/arm/tcg/cpu32.c

In general, you want to copy data in bulk from the processor manual, so that the reviewer 
can simply read through the table and see that the code is correct, without having to 
check between multiple functions to see that the combination is correct.

For our existing la464, that table is Table 54 in the 3A5000 manual.

Is there a public specification for the la132?  I could not find one in 
https://www.loongson.cn/EN/product/, but perhaps that's just the english view.


r~
Jiajie Chen Aug. 9, 2023, 7:31 a.m. UTC | #3
On 2023/8/9 03:26, Richard Henderson wrote:
> On 8/7/23 18:54, Jiajie Chen wrote:
>> +static void loongarch_la464_initfn(Object *obj)
>> +{
>> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>> +    CPULoongArchState *env = &cpu->env;
>> +
>> +    loongarch_cpu_initfn_common(env);
>> +
>> +    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
>> +    env->cpucfg[0] = 0x14c010;  /* PRID */
>> +
>> +    uint32_t data = env->cpucfg[1];
>> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 2); /* LA64 */
>> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); /* 48 bits */
>> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); /* 48 bits */
>> +    data = FIELD_DP32(data, CPUCFG1, RI, 1);
>> +    data = FIELD_DP32(data, CPUCFG1, EP, 1);
>> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
>> +    env->cpucfg[1] = data;
>> +}
>> +
>> +static void loongarch_la132_initfn(Object *obj)
>> +{
>> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>> +    CPULoongArchState *env = &cpu->env;
>> +
>> +    loongarch_cpu_initfn_common(env);
>> +
>> +    cpu->dtb_compatible = "loongarch,Loongson-1C103";
>> +
>> +    uint32_t data = env->cpucfg[1];
>> +    data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
>> +    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
>> +    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
>> +    data = FIELD_DP32(data, CPUCFG1, RI, 0);
>> +    data = FIELD_DP32(data, CPUCFG1, EP, 0);
>> +    data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
>> +    env->cpucfg[1] = data;
>> +}
>
> The use of the loongarch_cpu_initfn_common function is not going to 
> scale.
> Compare the set of *_initfn in target/arm/tcg/cpu32.c
>
> In general, you want to copy data in bulk from the processor manual, 
> so that the reviewer can simply read through the table and see that 
> the code is correct, without having to check between multiple 
> functions to see that the combination is correct.
>
> For our existing la464, that table is Table 54 in the 3A5000 manual.
>
> Is there a public specification for the la132?  I could not find one 
> in https://www.loongson.cn/EN/product/, but perhaps that's just the 
> english view.


There seems no, even from the chinese view.


>
>
> r~
diff mbox series

Patch

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e19b042ce8..af15bf5aaa 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -798,11 +798,6 @@  static void loongarch_init(MachineState *machine)
         cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
     }
 
-    if (!strstr(cpu_model, "la464")) {
-        error_report("LoongArch/TCG needs cpu type la464");
-        exit(1);
-    }
-
     if (ram_size < 1 * GiB) {
         error_report("ram_size must be greater than 1G.");
         exit(1);
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 13d4fccbd3..341176817e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -356,30 +356,18 @@  static bool loongarch_cpu_has_work(CPUState *cs)
 #endif
 }
 
-static void loongarch_la464_initfn(Object *obj)
+static void loongarch_cpu_initfn_common(CPULoongArchState *env)
 {
-    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
-    CPULoongArchState *env = &cpu->env;
     int i;
 
     for (i = 0; i < 21; i++) {
         env->cpucfg[i] = 0x0;
     }
 
-    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
-    env->cpucfg[0] = 0x14c010;  /* PRID */
-
     uint32_t data = 0;
-    data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
     data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
     data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
-    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
-    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
     data = FIELD_DP32(data, CPUCFG1, UAL, 1);
-    data = FIELD_DP32(data, CPUCFG1, RI, 1);
-    data = FIELD_DP32(data, CPUCFG1, EP, 1);
-    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
-    data = FIELD_DP32(data, CPUCFG1, HP, 1);
     data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
     env->cpucfg[1] = data;
 
@@ -439,6 +427,45 @@  static void loongarch_la464_initfn(Object *obj)
     env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
 }
 
+static void loongarch_la464_initfn(Object *obj)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+    CPULoongArchState *env = &cpu->env;
+
+    loongarch_cpu_initfn_common(env);
+
+    cpu->dtb_compatible = "loongarch,Loongson-3A5000";
+    env->cpucfg[0] = 0x14c010;  /* PRID */
+
+    uint32_t data = env->cpucfg[1];
+    data = FIELD_DP32(data, CPUCFG1, ARCH, 2); /* LA64 */
+    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); /* 48 bits */
+    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); /* 48 bits */
+    data = FIELD_DP32(data, CPUCFG1, RI, 1);
+    data = FIELD_DP32(data, CPUCFG1, EP, 1);
+    data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
+    env->cpucfg[1] = data;
+}
+
+static void loongarch_la132_initfn(Object *obj)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+    CPULoongArchState *env = &cpu->env;
+
+    loongarch_cpu_initfn_common(env);
+
+    cpu->dtb_compatible = "loongarch,Loongson-1C103";
+
+    uint32_t data = env->cpucfg[1];
+    data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
+    data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
+    data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
+    data = FIELD_DP32(data, CPUCFG1, RI, 0);
+    data = FIELD_DP32(data, CPUCFG1, EP, 0);
+    data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
+    env->cpucfg[1] = data;
+}
+
 static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
 {
     const char *typename = object_class_get_name(OBJECT_CLASS(data));
@@ -784,5 +811,6 @@  static const TypeInfo loongarch32_cpu_type_infos[] = {
         .class_size = sizeof(LoongArchCPUClass),
         .class_init = loongarch32_cpu_class_init,
     },
+    DEFINE_LOONGARCH32_CPU_TYPE("la132", loongarch_la132_initfn),
 };
 DEFINE_TYPES(loongarch32_cpu_type_infos)