diff mbox series

[RFC,v2,1/2] target/loongarch: Add loongson binary translation feature

Message ID 20240527083501.844854-2-maobibo@loongson.cn
State New
Headers show
Series target/loongarch: Add loongson binary translation feature | expand

Commit Message

maobibo May 27, 2024, 8:35 a.m. UTC
Loongson Binary Translation (LBT) is used to accelerate binary
translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
eflags (eflags) and x87 fpu stack pointer (ftop).

Now LBT feature is added in kvm mode, not supported in TCG mode since
it is not emulated. There are two feature flags such as forced_features
and default_features for each vcpu, the real feature is still in cpucfg.
Flag forced_features is parsed from command line, default_features is
parsed from cpu type.

Flag forced_features has higher priority than flag default_features,
default_features will be used if there is no command line option for LBT
feature. If the feature is not supported with KVM host, it reports error
and exits if forced_features is set, else it disables feature and continues
if default_features is set.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 target/loongarch/cpu.c                | 69 +++++++++++++++++++++++++++
 target/loongarch/cpu.h                | 12 +++++
 target/loongarch/kvm/kvm.c            | 26 ++++++++++
 target/loongarch/kvm/kvm_loongarch.h  | 16 +++++++
 target/loongarch/loongarch-qmp-cmds.c |  2 +-
 5 files changed, 124 insertions(+), 1 deletion(-)

Comments

Philippe Mathieu-Daudé May 27, 2024, 10:37 a.m. UTC | #1
Hi Bibo,

On 27/5/24 10:35, Bibo Mao wrote:
> Loongson Binary Translation (LBT) is used to accelerate binary
> translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
> eflags (eflags) and x87 fpu stack pointer (ftop).
> 
> Now LBT feature is added in kvm mode, not supported in TCG mode since
> it is not emulated. There are two feature flags such as forced_features
> and default_features for each vcpu, the real feature is still in cpucfg.
> Flag forced_features is parsed from command line, default_features is
> parsed from cpu type.
> 
> Flag forced_features has higher priority than flag default_features,
> default_features will be used if there is no command line option for LBT
> feature. If the feature is not supported with KVM host, it reports error
> and exits if forced_features is set, else it disables feature and continues
> if default_features is set.
> 
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>   target/loongarch/cpu.c                | 69 +++++++++++++++++++++++++++
>   target/loongarch/cpu.h                | 12 +++++
>   target/loongarch/kvm/kvm.c            | 26 ++++++++++
>   target/loongarch/kvm/kvm_loongarch.h  | 16 +++++++
>   target/loongarch/loongarch-qmp-cmds.c |  2 +-
>   5 files changed, 124 insertions(+), 1 deletion(-)


> +static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
> +{
> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
> +
> +    if (!kvm_enabled()) {

Either set errp, ...

> +        return;
> +    }
> +
> +    if (value) {
> +        /* Enable binary translation for all architectures */
> +        cpu->env.forced_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
> +    } else {
> +        /* Disable default features also */
> +        cpu->env.default_features &= ~BIT_ULL(LOONGARCH_FEATURE_LBT);
> +    }
> +}
> +
>   void loongarch_cpu_post_init(Object *obj)
>   {
>       object_property_add_bool(obj, "lsx", loongarch_get_lsx,
>                                loongarch_set_lsx);
>       object_property_add_bool(obj, "lasx", loongarch_get_lasx,
>                                loongarch_set_lasx);

... or only add the property if KVM is enabled:

    if (kvm_enabled()) {

> +    object_property_add_bool(obj, "lbt", loongarch_get_lbt,
> +                             loongarch_set_lbt);
>   }
maobibo May 28, 2024, 1:07 a.m. UTC | #2
Hi Philippe,

Thanks for reviewing my patch.
I reply inline.

On 2024/5/27 下午6:37, Philippe Mathieu-Daudé wrote:
> Hi Bibo,
> 
> On 27/5/24 10:35, Bibo Mao wrote:
>> Loongson Binary Translation (LBT) is used to accelerate binary
>> translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
>> eflags (eflags) and x87 fpu stack pointer (ftop).
>>
>> Now LBT feature is added in kvm mode, not supported in TCG mode since
>> it is not emulated. There are two feature flags such as forced_features
>> and default_features for each vcpu, the real feature is still in cpucfg.
>> Flag forced_features is parsed from command line, default_features is
>> parsed from cpu type.
>>
>> Flag forced_features has higher priority than flag default_features,
>> default_features will be used if there is no command line option for LBT
>> feature. If the feature is not supported with KVM host, it reports error
>> and exits if forced_features is set, else it disables feature and 
>> continues
>> if default_features is set.
>>
>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>> ---
>>   target/loongarch/cpu.c                | 69 +++++++++++++++++++++++++++
>>   target/loongarch/cpu.h                | 12 +++++
>>   target/loongarch/kvm/kvm.c            | 26 ++++++++++
>>   target/loongarch/kvm/kvm_loongarch.h  | 16 +++++++
>>   target/loongarch/loongarch-qmp-cmds.c |  2 +-
>>   5 files changed, 124 insertions(+), 1 deletion(-)
> 
> 
>> +static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
>> +{
>> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>> +
>> +    if (!kvm_enabled()) {
> 
> Either set errp, ...
> 
>> +        return;
>> +    }
>> +
>> +    if (value) {
>> +        /* Enable binary translation for all architectures */
>> +        cpu->env.forced_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
>> +    } else {
>> +        /* Disable default features also */
>> +        cpu->env.default_features &= ~BIT_ULL(LOONGARCH_FEATURE_LBT);
>> +    }
>> +}
>> +
>>   void loongarch_cpu_post_init(Object *obj)
>>   {
>>       object_property_add_bool(obj, "lsx", loongarch_get_lsx,
>>                                loongarch_set_lsx);
>>       object_property_add_bool(obj, "lasx", loongarch_get_lasx,
>>                                loongarch_set_lasx);
> 
> ... or only add the property if KVM is enabled:
> 
>     if (kvm_enabled()) {
Sure, will do. I think this method is better.

By the way bitmap method forced_features/default_feature is variant
of OnOffAuto method. Bitmap method uses two bit, OnOffAuto method uses 
separate feature variable. We do not know which method is better or 
which is the future trend.

Regards
Bibo Mao
> 
>> +    object_property_add_bool(obj, "lbt", loongarch_get_lbt,
>> +                             loongarch_set_lbt);
>>   }
gaosong May 28, 2024, 12:56 p.m. UTC | #3
在 2024/5/28 上午9:07, maobibo 写道:
> Hi Philippe,
>
> Thanks for reviewing my patch.
> I reply inline.
>
> On 2024/5/27 下午6:37, Philippe Mathieu-Daudé wrote:
>> Hi Bibo,
>>
>> On 27/5/24 10:35, Bibo Mao wrote:
>>> Loongson Binary Translation (LBT) is used to accelerate binary
>>> translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
>>> eflags (eflags) and x87 fpu stack pointer (ftop).
>>>
>>> Now LBT feature is added in kvm mode, not supported in TCG mode since
>>> it is not emulated. There are two feature flags such as forced_features
>>> and default_features for each vcpu, the real feature is still in 
>>> cpucfg.
>>> Flag forced_features is parsed from command line, default_features is
>>> parsed from cpu type.
>>>
>>> Flag forced_features has higher priority than flag default_features,
>>> default_features will be used if there is no command line option for 
>>> LBT
>>> feature. If the feature is not supported with KVM host, it reports 
>>> error
>>> and exits if forced_features is set, else it disables feature and 
>>> continues
>>> if default_features is set.
>>>
>>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>>> ---
>>>   target/loongarch/cpu.c                | 69 
>>> +++++++++++++++++++++++++++
>>>   target/loongarch/cpu.h                | 12 +++++
>>>   target/loongarch/kvm/kvm.c            | 26 ++++++++++
>>>   target/loongarch/kvm/kvm_loongarch.h  | 16 +++++++
>>>   target/loongarch/loongarch-qmp-cmds.c |  2 +-
>>>   5 files changed, 124 insertions(+), 1 deletion(-)
>>
>>
>>> +static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
>>> +{
>>> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>>> +
>>> +    if (!kvm_enabled()) {
>>
>> Either set errp, ...
>>
>>> +        return;
>>> +    }
>>> +
>>> +    if (value) {
>>> +        /* Enable binary translation for all architectures */
>>> +        cpu->env.forced_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
>>> +    } else {
>>> +        /* Disable default features also */
>>> +        cpu->env.default_features &= ~BIT_ULL(LOONGARCH_FEATURE_LBT);
>>> +    }
>>> +}
>>> +
>>>   void loongarch_cpu_post_init(Object *obj)
>>>   {
>>>       object_property_add_bool(obj, "lsx", loongarch_get_lsx,
>>>                                loongarch_set_lsx);
>>>       object_property_add_bool(obj, "lasx", loongarch_get_lasx,
>>>                                loongarch_set_lasx);
>>
>> ... or only add the property if KVM is enabled:
>>
>>     if (kvm_enabled()) {
> Sure, will do. I think this method is better.
>
> By the way bitmap method forced_features/default_feature is variant
> of OnOffAuto method. Bitmap method uses two bit, OnOffAuto method uses 
> separate feature variable. We do not know which method is better or 
> which is the future trend.
>
I think the OnOffAuto variable is better.

The default_features is just a copy of cpucfg, and is not required.

Thanks.
Song Gao
> Regards
> Bibo Mao
>>
>>> +    object_property_add_bool(obj, "lbt", loongarch_get_lbt,
>>> +                             loongarch_set_lbt);
>>>   }
maobibo May 29, 2024, 8:18 a.m. UTC | #4
On 2024/5/28 下午8:56, gaosong wrote:
> 在 2024/5/28 上午9:07, maobibo 写道:
>> Hi Philippe,
>>
>> Thanks for reviewing my patch.
>> I reply inline.
>>
>> On 2024/5/27 下午6:37, Philippe Mathieu-Daudé wrote:
>>> Hi Bibo,
>>>
>>> On 27/5/24 10:35, Bibo Mao wrote:
>>>> Loongson Binary Translation (LBT) is used to accelerate binary
>>>> translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
>>>> eflags (eflags) and x87 fpu stack pointer (ftop).
>>>>
>>>> Now LBT feature is added in kvm mode, not supported in TCG mode since
>>>> it is not emulated. There are two feature flags such as forced_features
>>>> and default_features for each vcpu, the real feature is still in 
>>>> cpucfg.
>>>> Flag forced_features is parsed from command line, default_features is
>>>> parsed from cpu type.
>>>>
>>>> Flag forced_features has higher priority than flag default_features,
>>>> default_features will be used if there is no command line option for 
>>>> LBT
>>>> feature. If the feature is not supported with KVM host, it reports 
>>>> error
>>>> and exits if forced_features is set, else it disables feature and 
>>>> continues
>>>> if default_features is set.
>>>>
>>>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>>>> ---
>>>>   target/loongarch/cpu.c                | 69 
>>>> +++++++++++++++++++++++++++
>>>>   target/loongarch/cpu.h                | 12 +++++
>>>>   target/loongarch/kvm/kvm.c            | 26 ++++++++++
>>>>   target/loongarch/kvm/kvm_loongarch.h  | 16 +++++++
>>>>   target/loongarch/loongarch-qmp-cmds.c |  2 +-
>>>>   5 files changed, 124 insertions(+), 1 deletion(-)
>>>
>>>
>>>> +static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
>>>> +{
>>>> +    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>>>> +
>>>> +    if (!kvm_enabled()) {
>>>
>>> Either set errp, ...
>>>
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    if (value) {
>>>> +        /* Enable binary translation for all architectures */
>>>> +        cpu->env.forced_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
>>>> +    } else {
>>>> +        /* Disable default features also */
>>>> +        cpu->env.default_features &= ~BIT_ULL(LOONGARCH_FEATURE_LBT);
>>>> +    }
>>>> +}
>>>> +
>>>>   void loongarch_cpu_post_init(Object *obj)
>>>>   {
>>>>       object_property_add_bool(obj, "lsx", loongarch_get_lsx,
>>>>                                loongarch_set_lsx);
>>>>       object_property_add_bool(obj, "lasx", loongarch_get_lasx,
>>>>                                loongarch_set_lasx);
>>>
>>> ... or only add the property if KVM is enabled:
>>>
>>>     if (kvm_enabled()) {
>> Sure, will do. I think this method is better.
>>
>> By the way bitmap method forced_features/default_feature is variant
>> of OnOffAuto method. Bitmap method uses two bit, OnOffAuto method uses 
>> separate feature variable. We do not know which method is better or 
>> which is the future trend.
>>
> I think the OnOffAuto variable is better.
> 
> The default_features is just a copy of cpucfg, and is not required.
No, it is not copy of cpucfg. If so, OnOffAuto is also copy of cpucfg.

Combination of forced_features/default_feature bitmap is another 
implementation of OnOffAuto variable.

   Forced_features  Default_features
      1                   x             == ON_OFF_AUTO_ON
      0                   0             == ON_OFF_AUTO_OFF
      0                   1             == ON_OFF_AUTO_AUTO

Maybe we can rename Default_features with Hint_features.

Regards
Bibo Mao

> 
> Thanks.
> Song Gao
>> Regards
>> Bibo Mao
>>>
>>>> +    object_property_add_bool(obj, "lbt", loongarch_get_lbt,
>>>> +                             loongarch_set_lbt);
>>>>   }
>
diff mbox series

Patch

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index b5c1ec94af..d9d601da07 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -380,6 +380,8 @@  static void loongarch_la464_initfn(Object *obj)
     CPULoongArchState *env = &cpu->env;
     int i;
 
+    env->default_features = 0;
+    env->forced_features  = 0;
     for (i = 0; i < 21; i++) {
         env->cpucfg[i] = 0x0;
     }
@@ -413,6 +415,7 @@  static void loongarch_la464_initfn(Object *obj)
     data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
     data = FIELD_DP32(data, CPUCFG2, LAM, 1);
     env->cpucfg[2] = data;
+    env->default_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
 
     env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
 
@@ -571,6 +574,35 @@  static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
     info->print_insn = print_insn_loongarch;
 }
 
+static void loongarch_cpu_check_lbt(CPUState *cs, Error **errp)
+{
+    CPULoongArchState *env = cpu_env(cs);
+    enum loongarch_features feature;
+    bool kvm_supported;
+
+    feature = LOONGARCH_FEATURE_LBT;
+    kvm_supported = kvm_feature_supported(cs, feature);
+    if (env->forced_features & BIT_ULL(feature)) {
+        if (kvm_supported) {
+            env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
+        } else {
+            error_setg(errp, "'lbt' feature not supported by KVM on this host");
+            return;
+        }
+    } else if (env->default_features & BIT_ULL(feature)) {
+        if (kvm_supported) {
+            env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
+        }
+    }
+}
+
+static void loongarch_cpu_feature_realize(CPUState *cs, Error **errp)
+{
+    if (kvm_enabled()) {
+        loongarch_cpu_check_lbt(cs, errp);
+    }
+}
+
 static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
@@ -584,6 +616,11 @@  static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
     }
 
     loongarch_cpu_register_gdb_regs_for_features(cs);
+    loongarch_cpu_feature_realize(cs, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
 
     cpu_reset(cs);
     qemu_init_vcpu(cs);
@@ -643,12 +680,44 @@  static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
     }
 }
 
+static bool loongarch_get_lbt(Object *obj, Error **errp)
+ {
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+    bool ret;
+
+    ret = false;
+    /* lbt is enabled only in kvm mode, not supported in tcg mode */
+    if (cpu->env.forced_features & BIT_ULL(LOONGARCH_FEATURE_LBT)) {
+        ret = true;
+     }
+    return ret;
+}
+
+static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+    if (!kvm_enabled()) {
+        return;
+    }
+
+    if (value) {
+        /* Enable binary translation for all architectures */
+        cpu->env.forced_features |= BIT_ULL(LOONGARCH_FEATURE_LBT);
+    } else {
+        /* Disable default features also */
+        cpu->env.default_features &= ~BIT_ULL(LOONGARCH_FEATURE_LBT);
+    }
+}
+
 void loongarch_cpu_post_init(Object *obj)
 {
     object_property_add_bool(obj, "lsx", loongarch_get_lsx,
                              loongarch_set_lsx);
     object_property_add_bool(obj, "lasx", loongarch_get_lasx,
                              loongarch_set_lasx);
+    object_property_add_bool(obj, "lbt", loongarch_get_lbt,
+                             loongarch_set_lbt);
 }
 
 static void loongarch_cpu_init(Object *obj)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 41b8e6d96d..36fb160a8c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -152,6 +152,7 @@  FIELD(CPUCFG2, LLFTP_VER, 15, 3)
 FIELD(CPUCFG2, LBT_X86, 18, 1)
 FIELD(CPUCFG2, LBT_ARM, 19, 1)
 FIELD(CPUCFG2, LBT_MIPS, 20, 1)
+FIELD(CPUCFG2, LBT_ALL, 18, 3)
 FIELD(CPUCFG2, LSPW, 21, 1)
 FIELD(CPUCFG2, LAM, 22, 1)
 
@@ -280,6 +281,10 @@  struct LoongArchTLB {
 typedef struct LoongArchTLB LoongArchTLB;
 #endif
 
+enum loongarch_features {
+    LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */
+};
+
 typedef struct CPUArchState {
     uint64_t gpr[32];
     uint64_t pc;
@@ -289,6 +294,13 @@  typedef struct CPUArchState {
     uint32_t fcsr0;
 
     uint32_t cpucfg[21];
+    /*
+     * Features not specified from command line
+     * Comes from cpu type and kvm host capability
+     */
+    uint64_t default_features;
+    /* features parsed from command line, such as lbt=on */
+    uint64_t forced_features;
 
     /* LoongArch CSRs */
     uint64_t CSR_CRMD;
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 8e6e27c8bf..55e85eff15 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -780,6 +780,32 @@  int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
     return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
 }
 
+bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
+{
+    int ret;
+    struct kvm_device_attr attr;
+
+    switch (feature) {
+    case LOONGARCH_FEATURE_LBT:
+        /*
+         * Return all if all the LBT features are supported such as:
+         *  KVM_LOONGARCH_VM_FEAT_X86BT
+         *  KVM_LOONGARCH_VM_FEAT_ARMBT
+         *  KVM_LOONGARCH_VM_FEAT_MIPSBT
+         */
+        attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
+        attr.attr = KVM_LOONGARCH_VM_FEAT_X86BT;
+        ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+        attr.attr = KVM_LOONGARCH_VM_FEAT_ARMBT;
+        ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+        attr.attr = KVM_LOONGARCH_VM_FEAT_MIPSBT;
+        ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
+        return (ret == 0);
+    default:
+        return false;
+    }
+}
+
 void kvm_arch_accel_class_init(ObjectClass *oc)
 {
 }
diff --git a/target/loongarch/kvm/kvm_loongarch.h b/target/loongarch/kvm/kvm_loongarch.h
index d945b6bb82..bdb4f180eb 100644
--- a/target/loongarch/kvm/kvm_loongarch.h
+++ b/target/loongarch/kvm/kvm_loongarch.h
@@ -13,4 +13,20 @@ 
 int  kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
 void kvm_arch_reset_vcpu(CPULoongArchState *env);
 
+#ifdef CONFIG_KVM
+/*
+ * kvm_feature_supported:
+ *
+ * Returns: true if KVM supports specified feature
+ * and false otherwise.
+ */
+bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature);
+#else
+static inline bool kvm_feature_supported(CPUState *cs,
+                                         enum loongarch_features feature)
+{
+    return false;
+}
+#endif
+
 #endif
diff --git a/target/loongarch/loongarch-qmp-cmds.c b/target/loongarch/loongarch-qmp-cmds.c
index 8721a5eb13..c6f6e1ef85 100644
--- a/target/loongarch/loongarch-qmp-cmds.c
+++ b/target/loongarch/loongarch-qmp-cmds.c
@@ -40,7 +40,7 @@  CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 }
 
 static const char *cpu_model_advertised_features[] = {
-    "lsx", "lasx", NULL
+    "lsx", "lasx", "lbt", NULL
 };
 
 CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,