#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)
{
}
}
+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;
}
qdev_realize_and_unref(DEVICE(cpuobj), NULL, &error_fatal);
}
+ virt_check_dmsi(machine);
fw_cfg_add_memory(machine);
/* Node0 memory */
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);
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
#define IOCSRF_DVFSV1 7
#define IOCSRF_GMOD 9
#define IOCSRF_VM 11
+#define IOCSRF_DMSI 15
#define VERSION_REG 0x0
#define FEATURE_REG 0x8
#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
Notifier powerdown_notifier;
OnOffAuto acpi;
OnOffAuto veiointc;
+ OnOffAuto dmsi;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
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")
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) {
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);
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);
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);
}
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)