diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 3a905cf71d..99594a13a0 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -365,26 +365,35 @@ static void create_fdt(LoongArchVirtMachineState *lvms) static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms) { int num; - const MachineState *ms = MACHINE(lvms); - int smp_cpus = ms->smp.cpus; + MachineState *ms = MACHINE(lvms); + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus; + LoongArchCPU *cpu; + CPUState *cs; + char *nodename, *map_path; qemu_fdt_add_subnode(ms->fdt, "/cpus"); qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1); qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0); /* cpu nodes */ - for (num = smp_cpus - 1; num >= 0; num--) { - char *nodename = g_strdup_printf("/cpus/cpu@%d", num); - LoongArchCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num)); - CPUState *cs = CPU(cpu); + possible_cpus = mc->possible_cpu_arch_ids(ms); + for (num = 0; num < possible_cpus->len; num++) { + cs = possible_cpus->cpus[num].cpu; + if (cs == NULL) { + continue; + } + + nodename = g_strdup_printf("/cpus/cpu@%d", num); + cpu = LOONGARCH_CPU(cs); qemu_fdt_add_subnode(ms->fdt, nodename); qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu"); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", cpu->dtb_compatible); - if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + if (possible_cpus->cpus[num].props.has_node_id) { qemu_fdt_setprop_cell(ms->fdt, nodename, "numa-node-id", - ms->possible_cpus->cpus[cs->cpu_index].props.node_id); + possible_cpus->cpus[num].props.node_id); } qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num); qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", @@ -394,11 +403,13 @@ static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms) /*cpu map */ qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map"); + for (num = 0; num < possible_cpus->len; num++) { + cs = possible_cpus->cpus[num].cpu; + if (cs == NULL) { + continue; + } - for (num = smp_cpus - 1; num >= 0; num--) { - char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num); - char *map_path; - + nodename = g_strdup_printf("/cpus/cpu@%d", num); if (ms->smp.threads > 1) { map_path = g_strdup_printf( "/cpus/cpu-map/socket%d/core%d/thread%d", @@ -412,10 +423,10 @@ static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms) num % ms->smp.cores); } qemu_fdt_add_path(ms->fdt, map_path); - qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", cpu_path); + qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", nodename); g_free(map_path); - g_free(cpu_path); + g_free(nodename); } } @@ -615,12 +626,67 @@ static void virt_build_smbios(LoongArchVirtMachineState *lvms) } } +static void virt_fdt_setup(LoongArchVirtMachineState *lvms) +{ + MachineState *machine = MACHINE(lvms); + uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle; + int i; + + create_fdt(lvms); + fdt_add_cpu_nodes(lvms); + fdt_add_memory_nodes(machine); + fdt_add_fw_cfg_node(lvms); + fdt_add_flash_node(lvms); + + /* Add cpu interrupt-controller */ + fdt_add_cpuic_node(lvms, &cpuintc_phandle); + /* Add Extend I/O Interrupt Controller node */ + fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle); + /* Add PCH PIC node */ + fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle); + /* Add PCH MSI node */ + fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle); + /* Add pcie node */ + fdt_add_pcie_node(lvms, &pch_pic_phandle, &pch_msi_phandle); + + /* + * Create uart fdt node in reverse order so that they appear + * in the finished device tree lowest address first + */ + for (i = VIRT_UART_COUNT; i-- > 0;) { + hwaddr base = VIRT_UART_BASE + i * VIRT_UART_SIZE; + int irq = VIRT_UART_IRQ + i - VIRT_GSI_BASE; + fdt_add_uart_node(lvms, &pch_pic_phandle, base, irq, i == 0); + } + + fdt_add_rtc_node(lvms, &pch_pic_phandle); + fdt_add_ged_reset(lvms); + platform_bus_add_all_fdt_nodes(machine->fdt, "/platic", + VIRT_PLATFORM_BUS_BASEADDRESS, + VIRT_PLATFORM_BUS_SIZE, + VIRT_PLATFORM_BUS_IRQ); + + /* + * Since lowmem region starts from 0 and Linux kernel legacy start address + * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer + * access. FDT size limit with 1 MiB. + * Put the FDT into the memory map as a ROM image: this will ensure + * the FDT is copied again upon reset, even if addr points into RAM. + */ + qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size); + rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE, + &address_space_memory); + qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds, + rom_ptr_for_as(&address_space_memory, FDT_BASE, lvms->fdt_size)); +} + static void virt_done(Notifier *notifier, void *data) { LoongArchVirtMachineState *lvms = container_of(notifier, LoongArchVirtMachineState, machine_done); virt_build_smbios(lvms); loongarch_acpi_setup(lvms); + virt_fdt_setup(lvms); } static void virt_powerdown_req(Notifier *notifier, void *opaque) @@ -699,9 +765,7 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic) } static void virt_devices_init(DeviceState *pch_pic, - LoongArchVirtMachineState *lvms, - uint32_t *pch_pic_phandle, - uint32_t *pch_msi_phandle) + LoongArchVirtMachineState *lvms) { MachineClass *mc = MACHINE_GET_CLASS(lvms); DeviceState *gpex_dev; @@ -747,9 +811,6 @@ static void virt_devices_init(DeviceState *pch_pic, gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i); } - /* Add pcie node */ - fdt_add_pcie_node(lvms, pch_pic_phandle, pch_msi_phandle); - /* * Create uart fdt node in reverse order so that they appear * in the finished device tree lowest address first @@ -760,7 +821,6 @@ static void virt_devices_init(DeviceState *pch_pic, serial_mm_init(get_system_memory(), base, 0, qdev_get_gpio_in(pch_pic, irq), 115200, serial_hd(i), DEVICE_LITTLE_ENDIAN); - fdt_add_uart_node(lvms, pch_pic_phandle, base, irq, i == 0); } /* Network init */ @@ -774,8 +834,6 @@ static void virt_devices_init(DeviceState *pch_pic, sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE, qdev_get_gpio_in(pch_pic, VIRT_RTC_IRQ - VIRT_GSI_BASE)); - fdt_add_rtc_node(lvms, pch_pic_phandle); - fdt_add_ged_reset(lvms); /* acpi ged */ lvms->acpi_ged = create_acpi_ged(pch_pic, lvms); @@ -793,7 +851,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) CPULoongArchState *env; CPUState *cpu_state; int cpu, pin, i, start, num; - uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle; /* * Extended IRQ model. @@ -850,9 +907,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR, sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1)); - /* Add cpu interrupt-controller */ - fdt_add_cpuic_node(lvms, &cpuintc_phandle); - for (cpu = 0; cpu < ms->smp.cpus; cpu++) { cpu_state = qemu_get_cpu(cpu); cpudev = DEVICE(cpu_state); @@ -891,9 +945,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) } } - /* Add Extend I/O Interrupt Controller node */ - fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle); - pch_pic = qdev_new(TYPE_LOONGARCH_PIC); num = VIRT_PCH_PIC_IRQ_NUM; qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num); @@ -913,9 +964,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i)); } - /* Add PCH PIC node */ - fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle); - pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI); start = num; num = EXTIOI_IRQS - start; @@ -930,10 +978,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) qdev_get_gpio_in(extioi, i + start)); } - /* Add PCH MSI node */ - fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle); - - virt_devices_init(pch_pic, lvms, &pch_pic_phandle, &pch_msi_phandle); + virt_devices_init(pch_pic, lvms); } static void virt_firmware_init(LoongArchVirtMachineState *lvms) @@ -1151,8 +1196,6 @@ static void virt_init(MachineState *machine) cpu_model = LOONGARCH_CPU_TYPE_NAME("la464"); } - create_fdt(lvms); - /* Create IOCSR space */ memory_region_init_io(&lvms->system_iocsr, OBJECT(machine), NULL, machine, "iocsr", UINT64_MAX); @@ -1171,8 +1214,6 @@ static void virt_init(MachineState *machine) lacpu = LOONGARCH_CPU(cpu); lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id; } - fdt_add_cpu_nodes(lvms); - fdt_add_memory_nodes(machine); fw_cfg_add_memory(machine); /* Node0 memory */ @@ -1224,34 +1265,15 @@ static void virt_init(MachineState *machine) memmap_table, sizeof(struct memmap_entry) * (memmap_entries)); } - fdt_add_fw_cfg_node(lvms); - fdt_add_flash_node(lvms); /* Initialize the IO interrupt subsystem */ virt_irq_init(lvms); - platform_bus_add_all_fdt_nodes(machine->fdt, "/platic", - VIRT_PLATFORM_BUS_BASEADDRESS, - VIRT_PLATFORM_BUS_SIZE, - VIRT_PLATFORM_BUS_IRQ); lvms->machine_done.notify = virt_done; qemu_add_machine_init_done_notifier(&lvms->machine_done); /* connect powerdown request */ lvms->powerdown_notifier.notify = virt_powerdown_req; qemu_register_powerdown_notifier(&lvms->powerdown_notifier); - /* - * Since lowmem region starts from 0 and Linux kernel legacy start address - * at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer - * access. FDT size limit with 1 MiB. - * Put the FDT into the memory map as a ROM image: this will ensure - * the FDT is copied again upon reset, even if addr points into RAM. - */ - qemu_fdt_dumpdtb(machine->fdt, lvms->fdt_size); - rom_add_blob_fixed_as("fdt", machine->fdt, lvms->fdt_size, FDT_BASE, - &address_space_memory); - qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds, - rom_ptr_for_as(&address_space_memory, FDT_BASE, lvms->fdt_size)); - lvms->bootinfo.ram_size = ram_size; loongarch_load_kernel(machine, &lvms->bootinfo); } diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 58415ffe99..d611a60470 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -379,6 +379,7 @@ static void loongarch_la464_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); CPULoongArchState *env = &cpu->env; + uint32_t data = 0; int i; for (i = 0; i < 21; i++) { @@ -388,7 +389,6 @@ static void loongarch_la464_initfn(Object *obj) 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); @@ -477,7 +477,7 @@ static void loongarch_la132_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); CPULoongArchState *env = &cpu->env; - + uint32_t data = 0; int i; for (i = 0; i < 21; i++) { @@ -487,7 +487,6 @@ static void loongarch_la132_initfn(Object *obj) cpu->dtb_compatible = "loongarch,Loongson-1C103"; env->cpucfg[0] = 0x148042; /* PRID */ - uint32_t data = 0; data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */ data = FIELD_DP32(data, CPUCFG1, PGMMU, 1); data = FIELD_DP32(data, CPUCFG1, IOCSR, 1); @@ -615,54 +614,74 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) static bool loongarch_get_lsx(Object *obj, Error **errp) { - LoongArchCPU *cpu = LOONGARCH_CPU(obj); - bool ret; - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { - ret = true; - } else { - ret = false; - } - return ret; + return LOONGARCH_CPU(obj)->lsx != ON_OFF_AUTO_OFF; } static void loongarch_set_lsx(Object *obj, bool value, Error **errp) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); + uint32_t val; - if (value) { - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1); - } else { - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0); - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0); + cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + if (cpu->lsx == ON_OFF_AUTO_OFF) { + cpu->lasx = ON_OFF_AUTO_OFF; + if (cpu->lasx == ON_OFF_AUTO_ON) { + error_setg(errp, "Failed to disable LSX since LASX is enabled"); + return; + } } + + if (kvm_enabled()) { + /* kvm feature detection in function kvm_arch_init_vcpu */ + return; + } + + /* LSX feature detection in TCG mode */ + val = cpu->env.cpucfg[2]; + if (cpu->lsx == ON_OFF_AUTO_ON) { + if (FIELD_EX32(val, CPUCFG2, LSX) == 0) { + error_setg(errp, "Failed to enable LSX in TCG mode"); + return; + } + } else { + cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, 0); + val = cpu->env.cpucfg[2]; + } + + cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value); } static bool loongarch_get_lasx(Object *obj, Error **errp) { - LoongArchCPU *cpu = LOONGARCH_CPU(obj); - bool ret; - - if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) { - ret = true; - } else { - ret = false; - } - return ret; + return LOONGARCH_CPU(obj)->lasx != ON_OFF_AUTO_OFF; } static void loongarch_set_lasx(Object *obj, bool value, Error **errp) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); + uint32_t val; - if (value) { - if (!FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1); - } - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 1); - } else { - cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0); + cpu->lasx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + if ((cpu->lsx == ON_OFF_AUTO_OFF) && (cpu->lasx == ON_OFF_AUTO_ON)) { + error_setg(errp, "Failed to enable LASX since lSX is disabled"); + return; } + + if (kvm_enabled()) { + /* kvm feature detection in function kvm_arch_init_vcpu */ + return; + } + + /* LASX feature detection in TCG mode */ + val = cpu->env.cpucfg[2]; + if (cpu->lasx == ON_OFF_AUTO_ON) { + if (FIELD_EX32(val, CPUCFG2, LASX) == 0) { + error_setg(errp, "Failed to enable LASX in TCG mode"); + return; + } + } + + cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value); } static bool loongarch_get_lbt(Object *obj, Error **errp) @@ -693,6 +712,8 @@ void loongarch_cpu_post_init(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); + cpu->lsx = ON_OFF_AUTO_AUTO; + cpu->lasx = ON_OFF_AUTO_AUTO; object_property_add_bool(obj, "lsx", loongarch_get_lsx, loongarch_set_lsx); object_property_add_bool(obj, "lasx", loongarch_get_lasx, @@ -713,6 +734,7 @@ void loongarch_cpu_post_init(Object *obj) } else { cpu->lbt = ON_OFF_AUTO_OFF; + cpu->pmu = ON_OFF_AUTO_OFF; } } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 86c86c6c95..8eee49a984 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -283,6 +283,8 @@ typedef struct LoongArchTLB LoongArchTLB; #endif enum loongarch_features { + LOONGARCH_FEATURE_LSX, + LOONGARCH_FEATURE_LASX, LOONGARCH_FEATURE_LBT, /* loongson binary translation extension */ LOONGARCH_FEATURE_PMU, }; @@ -404,6 +406,8 @@ struct ArchCPU { uint32_t phy_id; OnOffAuto lbt; OnOffAuto pmu; + OnOffAuto lsx; + OnOffAuto lasx; /* 'compatible' string for this CPU for Linux device trees */ const char *dtb_compatible; diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index 3c86f5ffb9..a3f55155b0 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -798,8 +798,61 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature) { int ret; struct kvm_device_attr attr; + uint64_t val; switch (feature) { + case LOONGARCH_FEATURE_LSX: + attr.group = KVM_LOONGARCH_VM_FEAT_CTRL; + attr.attr = KVM_LOONGARCH_VM_FEAT_LSX; + ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr); + if (ret == 0) { + return true; + } + + /* Fallback to old kernel detect interface */ + val = 0; + attr.group = KVM_LOONGARCH_VCPU_CPUCFG; + /* Cpucfg2 */ + attr.attr = 2; + attr.addr = (uint64_t)&val; + ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr); + if (!ret) { + ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr); + if (ret) { + return false; + } + + ret = FIELD_EX32((uint32_t)val, CPUCFG2, LSX); + return (ret != 0); + } + return false; + + case LOONGARCH_FEATURE_LASX: + attr.group = KVM_LOONGARCH_VM_FEAT_CTRL; + attr.attr = KVM_LOONGARCH_VM_FEAT_LASX; + ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr); + if (ret == 0) { + return true; + } + + /* Fallback to old kernel detect interface */ + val = 0; + attr.group = KVM_LOONGARCH_VCPU_CPUCFG; + /* Cpucfg2 */ + attr.attr = 2; + attr.addr = (uint64_t)&val; + ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr); + if (!ret) { + ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr); + if (ret) { + return false; + } + + ret = FIELD_EX32((uint32_t)val, CPUCFG2, LASX); + return (ret != 0); + } + return false; + case LOONGARCH_FEATURE_LBT: /* * Return all if all the LBT features are supported such as: @@ -829,6 +882,50 @@ static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature) return false; } +static int kvm_cpu_check_lsx(CPUState *cs, Error **errp) +{ + CPULoongArchState *env = cpu_env(cs); + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + bool kvm_supported; + + kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LSX); + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 0); + if (cpu->lsx == ON_OFF_AUTO_ON) { + if (kvm_supported) { + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1); + } else { + error_setg(errp, "'lsx' feature not supported by KVM on this host"); + return -ENOTSUP; + } + } else if ((cpu->lsx == ON_OFF_AUTO_AUTO) && kvm_supported) { + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1); + } + + return 0; +} + +static int kvm_cpu_check_lasx(CPUState *cs, Error **errp) +{ + CPULoongArchState *env = cpu_env(cs); + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + bool kvm_supported; + + kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LASX); + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 0); + if (cpu->lasx == ON_OFF_AUTO_ON) { + if (kvm_supported) { + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1); + } else { + error_setg(errp, "'lasx' feature not supported by KVM on host"); + return -ENOTSUP; + } + } else if ((cpu->lasx == ON_OFF_AUTO_AUTO) && kvm_supported) { + env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1); + } + + return 0; +} + static int kvm_cpu_check_lbt(CPUState *cs, Error **errp) { CPULoongArchState *env = cpu_env(cs); @@ -889,6 +986,16 @@ int kvm_arch_init_vcpu(CPUState *cs) brk_insn = val; } + ret = kvm_cpu_check_lsx(cs, &local_err); + if (ret < 0) { + error_report_err(local_err); + } + + ret = kvm_cpu_check_lasx(cs, &local_err); + if (ret < 0) { + error_report_err(local_err); + } + ret = kvm_cpu_check_lbt(cs, &local_err); if (ret < 0) { error_report_err(local_err); diff --git a/target/loongarch/tcg/insn_trans/trans_vec.c.inc b/target/loongarch/tcg/insn_trans/trans_vec.c.inc index 92b1d22e28..dff92772ad 100644 --- a/target/loongarch/tcg/insn_trans/trans_vec.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_vec.c.inc @@ -3480,7 +3480,7 @@ static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm) break; case 1: /* data: {2{16'0, imm[7:0], 8'0}} */ - data = (t << 24) | (t << 8); + data = (t << 40) | (t << 8); break; case 2: /* data: {2{8'0, imm[7:0], 16'0}} */ @@ -5126,7 +5126,7 @@ static bool do_vbsrl_v(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz) { int i, ofs; - if (!check_vec(ctx, 32)) { + if (!check_vec(ctx, oprsz)) { return true; }