diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/arm/virt.c | 41 | ||||
| -rw-r--r-- | hw/core/machine.c | 18 | ||||
| -rw-r--r-- | hw/core/qdev-properties-system.c | 21 | ||||
| -rw-r--r-- | hw/core/qdev-properties.c | 12 | ||||
| -rw-r--r-- | hw/i386/pc.c | 66 |
5 files changed, 105 insertions, 53 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6e098afd1f..4dafd42be8 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1176,6 +1176,10 @@ static void machvirt_init(MachineState *machine) VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); VirtGuestInfo *guest_info = &guest_info_state->info; char **cpustr; + ObjectClass *oc; + const char *typename; + CPUClass *cc; + Error *err = NULL; bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); if (!cpu_model) { @@ -1259,26 +1263,24 @@ static void machvirt_init(MachineState *machine) create_fdt(vbi); - for (n = 0; n < smp_cpus; n++) { - ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]); - CPUClass *cc = CPU_CLASS(oc); - Object *cpuobj; - Error *err = NULL; - char *cpuopts = g_strdup(cpustr[1]); - - if (!oc) { - error_report("Unable to find CPU definition"); - exit(1); - } - cpuobj = object_new(object_class_get_name(oc)); + oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]); + if (!oc) { + error_report("Unable to find CPU definition"); + exit(1); + } + typename = object_class_get_name(oc); - /* Handle any CPU options specified by the user */ - cc->parse_features(CPU(cpuobj), cpuopts, &err); - g_free(cpuopts); - if (err) { - error_report_err(err); - exit(1); - } + /* convert -smp CPU options specified by the user into global props */ + cc = CPU_CLASS(oc); + cc->parse_features(typename, cpustr[1], &err); + g_strfreev(cpustr); + if (err) { + error_report_err(err); + exit(1); + } + + for (n = 0; n < smp_cpus; n++) { + Object *cpuobj = object_new(typename); if (!vms->secure) { object_property_set_bool(cpuobj, false, "has_el3", NULL); @@ -1309,7 +1311,6 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, true, "realized", NULL); } - g_strfreev(cpustr); fdt_add_timer_nodes(vbi, gic_version); fdt_add_cpu_nodes(vbi); fdt_add_psci_node(vbi); diff --git a/hw/core/machine.c b/hw/core/machine.c index 8f943013e5..2fe6ff6f30 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -560,6 +560,24 @@ static void machine_class_finalize(ObjectClass *klass, void *data) } } +void machine_register_compat_props(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + int i; + GlobalProperty *p; + + if (!mc->compat_props) { + return; + } + + for (i = 0; i < mc->compat_props->len; i++) { + p = g_array_index(mc->compat_props, GlobalProperty *, i); + /* Machine compat_props must never cause errors: */ + p->errp = &error_abort; + qdev_prop_register_global(p); + } +} + static const TypeInfo machine_info = { .name = TYPE_MACHINE, .parent = TYPE_OBJECT, diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index df38b8a03b..65d9fa9f53 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -1,5 +1,5 @@ /* - * qdev property parsing and global properties + * qdev property parsing * (parts specific for qemu-system-*) * * This file is based on code from hw/qdev-properties.c from @@ -394,22 +394,3 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) } nd->instantiated = 1; } - -static int qdev_add_one_global(void *opaque, QemuOpts *opts, Error **errp) -{ - GlobalProperty *g; - - g = g_malloc0(sizeof(*g)); - g->driver = qemu_opt_get(opts, "driver"); - g->property = qemu_opt_get(opts, "property"); - g->value = qemu_opt_get(opts, "value"); - g->user_provided = true; - qdev_prop_register_global(g); - return 0; -} - -void qemu_add_globals(void) -{ - qemu_opts_foreach(qemu_find_opts("global"), - qdev_add_one_global, NULL, NULL); -} diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index e3b2184a60..3c20c8e4b2 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1085,10 +1085,14 @@ static void qdev_prop_set_globals_for_type(DeviceState *dev, prop->used = true; object_property_parse(OBJECT(dev), prop->value, prop->property, &err); if (err != NULL) { - assert(prop->user_provided); - error_reportf_err(err, "Warning: global %s.%s=%s ignored: ", - prop->driver, prop->property, prop->value); - return; + error_prepend(&err, "can't apply global %s.%s=%s: ", + prop->driver, prop->property, prop->value); + if (prop->errp) { + error_propagate(prop->errp, err); + } else { + assert(prop->user_provided); + error_reportf_err(err, "Warning: "); + } } } } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index cd1745ebaf..f56e225a99 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1039,21 +1039,17 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu(const char *cpu_model, int64_t apic_id, +static X86CPU *pc_new_cpu(const char *typename, int64_t apic_id, Error **errp) { X86CPU *cpu = NULL; Error *local_err = NULL; - cpu = cpu_x86_create(cpu_model, &local_err); - if (local_err != NULL) { - goto out; - } + cpu = X86_CPU(object_new(typename)); object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); -out: if (local_err) { error_propagate(errp, local_err); object_unref(OBJECT(cpu)); @@ -1065,7 +1061,8 @@ out: void pc_hot_add_cpu(const int64_t id, Error **errp) { X86CPU *cpu; - MachineState *machine = MACHINE(qdev_get_machine()); + ObjectClass *oc; + PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); int64_t apic_id = x86_cpu_apic_id_from_index(id); Error *local_err = NULL; @@ -1093,7 +1090,9 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) return; } - cpu = pc_new_cpu(machine->cpu_model, apic_id, &local_err); + assert(pcms->possible_cpus->cpus[0].cpu); /* BSP is always present */ + oc = OBJECT_CLASS(CPU_GET_CLASS(pcms->possible_cpus->cpus[0].cpu)); + cpu = pc_new_cpu(object_class_get_name(oc), apic_id, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1104,6 +1103,10 @@ void pc_hot_add_cpu(const int64_t id, Error **errp) void pc_cpus_init(PCMachineState *pcms) { int i; + CPUClass *cc; + ObjectClass *oc; + const char *typename; + gchar **model_pieces; X86CPU *cpu = NULL; MachineState *machine = MACHINE(pcms); @@ -1116,6 +1119,22 @@ void pc_cpus_init(PCMachineState *pcms) #endif } + model_pieces = g_strsplit(machine->cpu_model, ",", 2); + if (!model_pieces[0]) { + error_report("Invalid/empty CPU model name"); + exit(1); + } + + oc = cpu_class_by_name(TYPE_X86_CPU, model_pieces[0]); + if (oc == NULL) { + error_report("Unable to find CPU definition: %s", model_pieces[0]); + exit(1); + } + typename = object_class_get_name(oc); + cc = CPU_CLASS(oc); + cc->parse_features(typename, model_pieces[1], &error_fatal); + g_strfreev(model_pieces); + /* Calculates the limit to CPU APIC ID values * * Limit for the APIC ID value, so that all @@ -1136,7 +1155,7 @@ void pc_cpus_init(PCMachineState *pcms) pcms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i); pcms->possible_cpus->len++; if (i < smp_cpus) { - cpu = pc_new_cpu(machine->cpu_model, x86_cpu_apic_id_from_index(i), + cpu = pc_new_cpu(typename, x86_cpu_apic_id_from_index(i), &error_fatal); pcms->possible_cpus->cpus[i].cpu = CPU(cpu); object_unref(OBJECT(cpu)); @@ -1147,6 +1166,34 @@ void pc_cpus_init(PCMachineState *pcms) smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); } +static void pc_build_feature_control_file(PCMachineState *pcms) +{ + X86CPU *cpu = X86_CPU(pcms->possible_cpus->cpus[0].cpu); + CPUX86State *env = &cpu->env; + uint32_t unused, ecx, edx; + uint64_t feature_control_bits = 0; + uint64_t *val; + + cpu_x86_cpuid(env, 1, 0, &unused, &unused, &ecx, &edx); + if (ecx & CPUID_EXT_VMX) { + feature_control_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; + } + + if ((edx & (CPUID_EXT2_MCE | CPUID_EXT2_MCA)) == + (CPUID_EXT2_MCE | CPUID_EXT2_MCA) && + (env->mcg_cap & MCG_LMCE_P)) { + feature_control_bits |= FEATURE_CONTROL_LMCE; + } + + if (!feature_control_bits) { + return; + } + + val = g_malloc(sizeof(*val)); + *val = cpu_to_le64(feature_control_bits | FEATURE_CONTROL_LOCKED); + fw_cfg_add_file(pcms->fw_cfg, "etc/msr_feature_control", val, sizeof(*val)); +} + static void pc_machine_done(Notifier *notifier, void *data) { @@ -1174,6 +1221,7 @@ void pc_machine_done(Notifier *notifier, void *data) acpi_setup(); if (pcms->fw_cfg) { pc_build_smbios(pcms->fw_cfg); + pc_build_feature_control_file(pcms); } } |