Skip to content

Commit 936c3f4

Browse files
committed
target/loongarch: Use auto method with LSX feature
Like LBT feature, add type OnOffAuto for LSX feature setting. Also add LSX feature detection with new VM ioctl command, fallback to old method if it is not supported. Signed-off-by: Bibo Mao <[email protected]> Reviewed-by: Bibo Mao <[email protected]>
1 parent b360109 commit 936c3f4

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

target/loongarch/cpu.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ static void loongarch_la464_initfn(Object *obj)
379379
{
380380
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
381381
CPULoongArchState *env = &cpu->env;
382+
uint32_t data = 0;
382383
int i;
383384

384385
for (i = 0; i < 21; i++) {
@@ -388,7 +389,6 @@ static void loongarch_la464_initfn(Object *obj)
388389
cpu->dtb_compatible = "loongarch,Loongson-3A5000";
389390
env->cpucfg[0] = 0x14c010; /* PRID */
390391

391-
uint32_t data = 0;
392392
data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
393393
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
394394
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
@@ -477,7 +477,7 @@ static void loongarch_la132_initfn(Object *obj)
477477
{
478478
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
479479
CPULoongArchState *env = &cpu->env;
480-
480+
uint32_t data = 0;
481481
int i;
482482

483483
for (i = 0; i < 21; i++) {
@@ -487,7 +487,6 @@ static void loongarch_la132_initfn(Object *obj)
487487
cpu->dtb_compatible = "loongarch,Loongson-1C103";
488488
env->cpucfg[0] = 0x148042; /* PRID */
489489

490-
uint32_t data = 0;
491490
data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
492491
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
493492
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
@@ -615,27 +614,30 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
615614

616615
static bool loongarch_get_lsx(Object *obj, Error **errp)
617616
{
618-
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
619-
bool ret;
620-
621-
if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
622-
ret = true;
623-
} else {
624-
ret = false;
625-
}
626-
return ret;
617+
return LOONGARCH_CPU(obj)->lsx != ON_OFF_AUTO_OFF;
627618
}
628619

629620
static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
630621
{
631622
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
623+
uint32_t val;
632624

633-
if (value) {
634-
cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
635-
} else {
636-
cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0);
637-
cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
625+
cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
626+
if (kvm_enabled()) {
627+
/* kvm feature detection in function kvm_arch_init_vcpu */
628+
return;
638629
}
630+
631+
/* LSX feature detection in TCG mode */
632+
val = cpu->env.cpucfg[2];
633+
if (cpu->lsx == ON_OFF_AUTO_ON) {
634+
if (FIELD_EX32(val, CPUCFG2, LSX) == 0) {
635+
error_setg(errp, "Failed to enable LSX in TCG mode");
636+
return;
637+
}
638+
}
639+
640+
cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value);
639641
}
640642

641643
static bool loongarch_get_lasx(Object *obj, Error **errp)
@@ -693,6 +695,7 @@ void loongarch_cpu_post_init(Object *obj)
693695
{
694696
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
695697

698+
cpu->lsx = ON_OFF_AUTO_AUTO;
696699
object_property_add_bool(obj, "lsx", loongarch_get_lsx,
697700
loongarch_set_lsx);
698701
object_property_add_bool(obj, "lasx", loongarch_get_lasx,
@@ -713,6 +716,7 @@ void loongarch_cpu_post_init(Object *obj)
713716

714717
} else {
715718
cpu->lbt = ON_OFF_AUTO_OFF;
719+
cpu->pmu = ON_OFF_AUTO_OFF;
716720
}
717721
}
718722

target/loongarch/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ typedef struct LoongArchTLB LoongArchTLB;
283283
#endif
284284

285285
enum loongarch_features {
286+
LOONGARCH_FEATURE_LSX,
286287
LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */
287288
LOONGARCH_FEATURE_PMU,
288289
};
@@ -404,6 +405,7 @@ struct ArchCPU {
404405
uint32_t phy_id;
405406
OnOffAuto lbt;
406407
OnOffAuto pmu;
408+
OnOffAuto lsx;
407409

408410
/* 'compatible' string for this CPU for Linux device trees */
409411
const char *dtb_compatible;

target/loongarch/kvm/kvm.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,35 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
798798
{
799799
int ret;
800800
struct kvm_device_attr attr;
801+
uint64_t val;
801802

802803
switch (feature) {
804+
case LOONGARCH_FEATURE_LSX:
805+
attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
806+
attr.attr = KVM_LOONGARCH_VM_FEAT_LSX;
807+
ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
808+
if (ret == 0) {
809+
return true;
810+
}
811+
812+
/* Fallback to old kernel detect interface */
813+
val = 0;
814+
attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
815+
/* Cpucfg2 */
816+
attr.attr = 2;
817+
attr.addr = (uint64_t)&val;
818+
ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
819+
if (!ret) {
820+
ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
821+
if (ret) {
822+
return false;
823+
}
824+
825+
ret = FIELD_EX32((uint32_t)val, CPUCFG2, LSX);
826+
return (ret != 0);
827+
}
828+
return false;
829+
803830
case LOONGARCH_FEATURE_LBT:
804831
/*
805832
* Return all if all the LBT features are supported such as:
@@ -829,6 +856,28 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
829856
return false;
830857
}
831858

859+
static int kvm_cpu_check_lsx(CPUState *cs, Error **errp)
860+
{
861+
CPULoongArchState *env = cpu_env(cs);
862+
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
863+
bool kvm_supported;
864+
865+
kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LSX);
866+
env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 0);
867+
if (cpu->lsx == ON_OFF_AUTO_ON) {
868+
if (kvm_supported) {
869+
env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
870+
} else {
871+
error_setg(errp, "'lsx' feature not supported by KVM on this host");
872+
return -ENOTSUP;
873+
}
874+
} else if ((cpu->lsx == ON_OFF_AUTO_AUTO) && kvm_supported) {
875+
env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
876+
}
877+
878+
return 0;
879+
}
880+
832881
static int kvm_cpu_check_lbt(CPUState *cs, Error **errp)
833882
{
834883
CPULoongArchState *env = cpu_env(cs);
@@ -889,6 +938,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
889938
brk_insn = val;
890939
}
891940

941+
ret = kvm_cpu_check_lsx(cs, &local_err);
942+
if (ret < 0) {
943+
error_report_err(local_err);
944+
}
945+
892946
ret = kvm_cpu_check_lbt(cs, &local_err);
893947
if (ret < 0) {
894948
error_report_err(local_err);

0 commit comments

Comments
 (0)