diff options
| -rw-r--r-- | hw/loongarch/virt.c | 50 | ||||
| -rw-r--r-- | include/hw/loongarch/virt.h | 14 | ||||
| -rw-r--r-- | target/loongarch/cpu.c | 29 | ||||
| -rw-r--r-- | target/loongarch/cpu.h | 1 |
4 files changed, 94 insertions, 0 deletions
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index bd5cff1f1e..256af63d73 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -48,6 +48,30 @@ #include "qemu/error-report.h" #include "kvm/kvm_loongarch.h" +static void virt_get_dmsi(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj); + OnOffAuto dmsi = lvms->dmsi; + + visit_type_OnOffAuto(v, name, &dmsi, errp); + +} +static void virt_set_dmsi(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj); + + visit_type_OnOffAuto(v, name, &lvms->dmsi, errp); + + if (lvms->dmsi == ON_OFF_AUTO_OFF) { + lvms->misc_feature &= ~BIT(IOCSRF_DMSI); + lvms->misc_status &= ~BIT_ULL(IOCSRM_DMSI_EN); + } else if (lvms->dmsi == ON_OFF_AUTO_ON) { + lvms->misc_feature = BIT(IOCSRF_DMSI); + } +} + static void virt_get_veiointc(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -683,6 +707,25 @@ static void fw_cfg_add_memory(MachineState *ms) } } +static void virt_check_dmsi(MachineState *machine) +{ + LoongArchCPU *cpu; + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine); + + cpu = LOONGARCH_CPU(first_cpu); + if (lvms->dmsi == ON_OFF_AUTO_AUTO) { + if (cpu->msgint != ON_OFF_AUTO_OFF) { + lvms->misc_feature = BIT(IOCSRF_DMSI); + } + } + + if (lvms->dmsi == ON_OFF_AUTO_ON && cpu->msgint == ON_OFF_AUTO_OFF) { + error_report("Fail to enable dmsi , cpu msgint is off " + "pleass add cpu feature mesgint=on."); + exit(EXIT_FAILURE); + } +} + static void virt_init(MachineState *machine) { const char *cpu_model = machine->cpu_type; @@ -717,6 +760,7 @@ static void virt_init(MachineState *machine) } qdev_realize_and_unref(DEVICE(cpuobj), NULL, &error_fatal); } + virt_check_dmsi(machine); fw_cfg_add_memory(machine); /* Node0 memory */ @@ -847,6 +891,8 @@ static void virt_initfn(Object *obj) if (tcg_enabled()) { lvms->veiointc = ON_OFF_AUTO_OFF; } + + lvms->dmsi = ON_OFF_AUTO_AUTO; lvms->acpi = ON_OFF_AUTO_AUTO; lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); @@ -1241,6 +1287,10 @@ static void virt_class_init(ObjectClass *oc, const void *data) NULL, NULL); object_class_property_set_description(oc, "v-eiointc", "Enable Virt Extend I/O Interrupt Controller."); + object_class_property_add(oc, "dmsi", "OnOffAuto", + virt_get_dmsi, virt_set_dmsi, NULL, NULL); + object_class_property_set_description(oc, "dmsi", + "Enable direct Message-interrupts Controller."); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS); #ifdef CONFIG_TPM diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 7120b46714..98e9bf0737 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -23,6 +23,7 @@ #define IOCSRF_DVFSV1 7 #define IOCSRF_GMOD 9 #define IOCSRF_VM 11 +#define IOCSRF_DMSI 15 #define VERSION_REG 0x0 #define FEATURE_REG 0x8 @@ -31,6 +32,7 @@ #define MISC_FUNC_REG 0x420 #define IOCSRM_EXTIOI_EN 48 #define IOCSRM_EXTIOI_INT_ENCODE 49 +#define IOCSRM_DMSI_EN 51 #define LOONGARCH_MAX_CPUS 256 @@ -69,6 +71,7 @@ struct LoongArchVirtMachineState { Notifier powerdown_notifier; OnOffAuto acpi; OnOffAuto veiointc; + OnOffAuto dmsi; char *oem_id; char *oem_table_id; DeviceState *acpi_ged; @@ -84,6 +87,8 @@ struct LoongArchVirtMachineState { DeviceState *extioi; struct memmap_entry *memmap_table; unsigned int memmap_entries; + uint64_t misc_feature; + uint64_t misc_status; }; #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt") @@ -91,6 +96,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE) void virt_acpi_setup(LoongArchVirtMachineState *lvms); void virt_fdt_setup(LoongArchVirtMachineState *lvms); +static inline bool virt_has_dmsi(LoongArchVirtMachineState *lvms) +{ + if (!(lvms->misc_feature & BIT(IOCSRF_DMSI))) { + return false; + } + + return true; +} + static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms) { if (lvms->veiointc == ON_OFF_AUTO_OFF) { diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 55ee317bf2..993602fb8c 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -495,6 +495,25 @@ static void loongarch_set_lasx(Object *obj, bool value, Error **errp) cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value); } +static bool loongarch_get_msgint(Object *obj, Error **errp) +{ + return LOONGARCH_CPU(obj)->msgint != ON_OFF_AUTO_OFF; +} + +static void loongarch_set_msgint(Object *obj, bool value, Error **errp) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + + cpu->msgint = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + + if (kvm_enabled()) { + /* kvm feature detection in function kvm_arch_init_vcpu */ + return; + } + + cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, value); +} + static void loongarch_cpu_post_init(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); @@ -507,6 +526,8 @@ static void loongarch_cpu_post_init(Object *obj) loongarch_set_lsx); object_property_add_bool(obj, "lasx", loongarch_get_lasx, loongarch_set_lasx); + object_property_add_bool(obj, "msgint", loongarch_get_msgint, + loongarch_set_msgint); /* lbt is enabled only in kvm mode, not supported in tcg mode */ if (kvm_enabled()) { kvm_loongarch_cpu_post_init(cpu); @@ -614,6 +635,7 @@ static void loongarch_la464_initfn(Object *obj) env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); + cpu->msgint = ON_OFF_AUTO_OFF; loongarch_la464_init_csr(obj); loongarch_cpu_post_init(obj); } @@ -644,12 +666,19 @@ static void loongarch_la132_initfn(Object *obj) data = FIELD_DP32(data, CPUCFG1, HP, 1); data = FIELD_DP32(data, CPUCFG1, CRC, 1); env->cpucfg[1] = data; + cpu->msgint = ON_OFF_AUTO_OFF; } static void loongarch_max_initfn(Object *obj) { + LoongArchCPU *cpu = LOONGARCH_CPU(obj); /* '-cpu max' for TCG: we use cpu la464. */ loongarch_la464_initfn(obj); + + if (tcg_enabled()) { + cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1); + cpu->msgint = ON_OFF_AUTO_AUTO; + } } static void loongarch_cpu_reset_hold(Object *obj, ResetType type) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 8c35bf120a..19e00325ca 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -392,6 +392,7 @@ struct ArchCPU { OnOffAuto pmu; OnOffAuto lsx; OnOffAuto lasx; + OnOffAuto msgint; OnOffAuto kvm_pv_ipi; OnOffAuto kvm_steal_time; int32_t socket_id; /* socket-id of this CPU */ |