aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/virt.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm/virt.c')
-rw-r--r--hw/arm/virt.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 769afa0600..6c9e8985bf 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -443,6 +443,11 @@ static void fdt_add_gic_node(VirtMachineState *vms)
2, vms->memmap[VIRT_GIC_DIST].size,
2, vms->memmap[VIRT_GIC_REDIST].base,
2, vms->memmap[VIRT_GIC_REDIST].size);
+ if (vms->virt) {
+ qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
+ GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+ }
} else {
/* 'cortex-a15-gic' means 'GIC v2' */
qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
@@ -1239,10 +1244,15 @@ static void machvirt_init(MachineState *machine)
* so it doesn't get in the way. Instead of starting secondary
* CPUs in PSCI powerdown state we will start them all running and
* let the boot ROM sort them out.
- * The usual case is that we do use QEMU's PSCI implementation.
+ * The usual case is that we do use QEMU's PSCI implementation;
+ * if the guest has EL2 then we will use SMC as the conduit,
+ * and otherwise we will use HVC (for backwards compatibility and
+ * because if we're using KVM then we must use HVC).
*/
if (vms->secure && firmware_loaded) {
vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
+ } else if (vms->virt) {
+ vms->psci_conduit = QEMU_PSCI_CONDUIT_SMC;
} else {
vms->psci_conduit = QEMU_PSCI_CONDUIT_HVC;
}
@@ -1272,6 +1282,12 @@ static void machvirt_init(MachineState *machine)
exit(1);
}
+ if (vms->virt && kvm_enabled()) {
+ error_report("mach-virt: KVM does not support providing "
+ "Virtualization extensions to the guest CPU");
+ exit(1);
+ }
+
if (vms->secure) {
if (kvm_enabled()) {
error_report("mach-virt: KVM does not support Security extensions");
@@ -1328,7 +1344,7 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, false, "has_el3", NULL);
}
- if (object_property_find(cpuobj, "has_el2", NULL)) {
+ if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
object_property_set_bool(cpuobj, false, "has_el2", NULL);
}
@@ -1434,6 +1450,20 @@ static void virt_set_secure(Object *obj, bool value, Error **errp)
vms->secure = value;
}
+static bool virt_get_virt(Object *obj, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ return vms->virt;
+}
+
+static void virt_set_virt(Object *obj, bool value, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ vms->virt = value;
+}
+
static bool virt_get_highmem(Object *obj, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1521,6 +1551,16 @@ static void virt_2_9_instance_init(Object *obj)
"Security Extensions (TrustZone)",
NULL);
+ /* EL2 is also disabled by default, for similar reasons */
+ vms->virt = false;
+ object_property_add_bool(obj, "virtualization", virt_get_virt,
+ virt_set_virt, NULL);
+ object_property_set_description(obj, "virtualization",
+ "Set on/off to enable/disable emulating a "
+ "guest CPU which implements the ARM "
+ "Virtualization Extensions",
+ NULL);
+
/* High memory is enabled by default */
vms->highmem = true;
object_property_add_bool(obj, "highmem", virt_get_highmem,