@@ -110,6 +110,8 @@ static ARMPlatformBusSystemParams platform_bus_params;
#define RAMLIMIT_GB 255
#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024)
+static MemoryRegion *secure_sysmem;
+
/* Addresses and sizes of our components.
* 0..128MB is space for a flash device so we can run bootrom code such as UEFI.
* 128MB..256MB is used for miscellaneous device I/O.
@@ -415,6 +417,116 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
}
}
+static void virt_new_cpu(MachineState *ms, int id, Error **errp)
+{
+ const char *typename;
+ char **cpustr;
+ int node_id;
+
+ ObjectClass *oc;
+ CPUClass *cc;
+ CPUState *cs;
+ Object *cpuobj;
+ const CPUArchIdList *possible_cpus;
+
+ Error *err = NULL;
+ const char *cpu_model = ms->cpu_model;
+ MemoryRegion *sysmem = get_system_memory();
+
+ VirtMachineState *vms = VIRT_MACHINE(ms);
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(ms);
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+ CPU_FOREACH(cs) {
+ if (cs->cpu_index == id) {
+ error_report("CPU %d has been created.", id);
+ return;
+ }
+ }
+ possible_cpus = mc->possible_cpu_arch_ids(ms);
+ /* Separate the actual CPU model name from any appended features */
+ cpustr = g_strsplit(cpu_model, ",", 2);
+ if (!cpuname_valid(cpustr[0])) {
+ error_report("mach-virt: CPU %s not supported", cpustr[0]);
+ goto out;
+ }
+ oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
+ if (!oc) {
+ error_report("Unable to find CPU definition");
+ goto out;
+ }
+
+ typename = object_class_get_name(oc);
+
+ cc = CPU_CLASS(oc);
+ cc->parse_features(typename, cpustr[1], &err);
+ if (err) {
+ error_report_err(err);
+ goto out;
+ }
+
+ cpuobj = object_new(typename);
+ object_property_set_int(cpuobj, possible_cpus->cpus[id].arch_id,
+ "mp-affinity", NULL);
+ cs = CPU(cpuobj);
+ cs->cpu_index = id;
+
+ node_id = possible_cpus->cpus[cs->cpu_index].props.node_id;
+ if (!possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
+ /* by default CPUState::numa_node was 0 if it's not set via CLI
+ * keep it this way for now but in future we probably should
+ * refuse to start up with incomplete numa mapping */
+ node_id = 0;
+ }
+ if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) {
+ cs->numa_node = node_id;
+ } else {
+ /* CPU isn't device_add compatible yet, this shouldn't happen */
+ error_setg(&error_abort, "user set node-id not implemented");
+ }
+
+ if (!vms->secure) {
+ object_property_set_bool(cpuobj, false, "has_el3", NULL);
+ }
+
+ if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
+ object_property_set_bool(cpuobj, false, "has_el2", NULL);
+ }
+
+ if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
+ object_property_set_int(cpuobj, vms->psci_conduit,
+ "psci-conduit", NULL);
+ /* Secondary CPUs start in PSCI powered-down state */
+ if (id > 0) {
+ object_property_set_bool(cpuobj, true, "start-powered-off", NULL);
+ }
+ }
+
+ if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
+ object_property_set_bool(cpuobj, false, "pmu", NULL);
+ }
+
+ if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+ object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base,
+ "reset-cbar", &error_abort);
+ }
+
+ object_property_set_link(cpuobj, OBJECT(sysmem), "memory", &error_abort);
+
+ if (vms->secure) {
+ object_property_set_link(cpuobj, OBJECT(secure_sysmem),
+ "secure-memory", &error_abort);
+ }
+
+ object_property_set_int(cpuobj, id, "id", NULL);
+ object_property_set_bool(cpuobj, true, "realized", NULL);
+ object_unref(cpuobj);
+
+out:
+ g_strfreev(cpustr);
+ error_propagate(errp, err);
+}
+
static void fdt_add_its_gic_node(VirtMachineState *vms)
{
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
@@ -1237,35 +1349,29 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
static void machvirt_init(MachineState *machine)
{
VirtMachineState *vms = VIRT_MACHINE(machine);
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
MachineClass *mc = MACHINE_GET_CLASS(machine);
const CPUArchIdList *possible_cpus;
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
- MemoryRegion *secure_sysmem = NULL;
int n, virt_max_cpus;
MemoryRegion *ram = g_new(MemoryRegion, 1);
const char *cpu_model = machine->cpu_model;
- 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) {
- cpu_model = "cortex-a15";
+ cpu_model = kvm_enabled() ? "host" : "cortex-a15";
+ machine->cpu_model = cpu_model;
}
/* We can probe only here because during property set
* KVM is not available yet
*/
+ if (!vms->gic_version && !kvm_enabled()) {
+ error_report("gic-version=host requires KVM");
+ exit(1);
+ }
if (!vms->gic_version) {
- if (!kvm_enabled()) {
- error_report("gic-version=host requires KVM");
- exit(1);
- }
-
vms->gic_version = kvm_arm_vgic_probe();
if (!vms->gic_version) {
error_report("Unable to determine GIC version supported by host");
@@ -1273,14 +1379,6 @@ static void machvirt_init(MachineState *machine)
}
}
- /* Separate the actual CPU model name from any appended features */
- cpustr = g_strsplit(cpu_model, ",", 2);
-
- if (!cpuname_valid(cpustr[0])) {
- error_report("mach-virt: CPU %s not supported", cpustr[0]);
- exit(1);
- }
-
/* If we have an EL3 boot ROM then the assumption is that it will
* implement PSCI itself, so disable QEMU's internal implementation
* so it doesn't get in the way. Instead of starting secondary
@@ -1328,12 +1426,12 @@ static void machvirt_init(MachineState *machine)
exit(1);
}
- if (vms->secure) {
- if (kvm_enabled()) {
- error_report("mach-virt: KVM does not support Security extensions");
- exit(1);
- }
+ if (vms->secure && kvm_enabled()) {
+ error_report("mach-virt: KVM does not support Security extensions");
+ exit(1);
+ }
+ if (vms->secure) {
/* The Secure view of the world is the same as the NonSecure,
* but with a few extra devices. Create it as a container region
* containing the system memory at low priority; any secure-only
@@ -1347,91 +1445,18 @@ static void machvirt_init(MachineState *machine)
create_fdt(vms);
- 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);
-
- /* 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);
- }
-
possible_cpus = mc->possible_cpu_arch_ids(machine);
for (n = 0; n < possible_cpus->len; n++) {
- Object *cpuobj;
- CPUState *cs;
- int node_id;
-
if (n >= smp_cpus) {
break;
}
-
- cpuobj = object_new(typename);
- object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,
- "mp-affinity", NULL);
-
- cs = CPU(cpuobj);
- cs->cpu_index = n;
-
- node_id = possible_cpus->cpus[cs->cpu_index].props.node_id;
- if (!possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
- /* by default CPUState::numa_node was 0 if it's not set via CLI
- * keep it this way for now but in future we probably should
- * refuse to start up with incomplete numa mapping */
- node_id = 0;
- }
- if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) {
- cs->numa_node = node_id;
- } else {
- /* CPU isn't device_add compatible yet, this shouldn't happen */
- error_setg(&error_abort, "user set node-id not implemented");
- }
-
- if (!vms->secure) {
- object_property_set_bool(cpuobj, false, "has_el3", NULL);
- }
-
- if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
- object_property_set_bool(cpuobj, false, "has_el2", NULL);
- }
-
- if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
- object_property_set_int(cpuobj, vms->psci_conduit,
- "psci-conduit", NULL);
-
- /* Secondary CPUs start in PSCI powered-down state */
- if (n > 0) {
- object_property_set_bool(cpuobj, true,
- "start-powered-off", NULL);
- }
- }
-
- if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
- object_property_set_bool(cpuobj, false, "pmu", NULL);
- }
-
- if (object_property_find(cpuobj, "reset-cbar", NULL)) {
- object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base,
- "reset-cbar", &error_abort);
- }
-
- object_property_set_link(cpuobj, OBJECT(sysmem), "memory",
- &error_abort);
- if (vms->secure) {
- object_property_set_link(cpuobj, OBJECT(secure_sysmem),
- "secure-memory", &error_abort);
+ virt_new_cpu(machine, n, &err);
+ if (err) {
+ error_report("mach-virt: creating a new cpu failed.");
+ exit(1);
}
-
- object_property_set_bool(cpuobj, true, "realized", NULL);
- object_unref(cpuobj);
}
+
fdt_add_timer_nodes(vms);
fdt_add_cpu_nodes(vms);
fdt_add_psci_node(vms);