diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index e67e7f0f7c50d..c942c725feda1 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -184,6 +184,15 @@ dtb-randomness dtb-kaslr-seed A deprecated synonym for dtb-randomness. +pci + Set ``on``/``off`` to enable/disable PCI bus. The default is ``on`` + +force_el3 + Set ``on``/``off`` to enable/disable EL3 without secure. The default is ``off`` + +force_psci + Set ``on``/``off`` to enable/disable builtin PSCI emulation even when EL3 is enabled. The default is ``off`` + Linux guest kernel configuration """""""""""""""""""""""""""""""" diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 6d8195781679a..b48fc9c2f297d 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1270,10 +1270,10 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) boot_el = arm_feature(env, ARM_FEATURE_EL2) ? 2 : 1; } - if ((info->psci_conduit == QEMU_PSCI_CONDUIT_HVC && boot_el >= 2) || - (info->psci_conduit == QEMU_PSCI_CONDUIT_SMC && boot_el == 3)) { - // Enable QEMU's builtin PSCI emulation even when EL3 is enabled, for Windows on ARM 32-Bit - // info->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; + if (!info->force_psci && + ((info->psci_conduit == QEMU_PSCI_CONDUIT_HVC && boot_el >= 2) || + (info->psci_conduit == QEMU_PSCI_CONDUIT_SMC && boot_el == 3))) { + info->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; } if (info->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 613cd446cd5cc..054efaabb6f68 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -886,7 +886,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) virtio_acpi_dsdt_add(scope, memmap[VIRT_MMIO].base, memmap[VIRT_MMIO].size, (irqmap[VIRT_MMIO] + ARM_SPI_BASE), 0, NUM_VIRTIO_TRANSPORTS); - acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); + if (vms->pci) { + acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); + } acpi_dsdt_add_ehci(scope, &memmap[VIRT_EHCI], irqmap[VIRT_EHCI] + ARM_SPI_BASE); acpi_dsdt_add_mmci(scope, &memmap[VIRT_SDHCI], irqmap[VIRT_SDHCI] + ARM_SPI_BASE); if (vms->acpi_dev) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d7536999fc42f..7539d001ce524 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2279,9 +2279,9 @@ static void machvirt_init(MachineState *machine) aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); - /* Enable EL3 even when secure=false, for Windows on ARM 32-Bit - Note: proper TrustZone with ATF+EDK2 does not work as of now */ - object_property_set_bool(cpuobj, "has_el3", true, NULL); + if (!vms->secure && !vms->force_el3) { + object_property_set_bool(cpuobj, "has_el3", true, NULL); + } if (!vms->virt && object_property_find(cpuobj, "has_el2")) { object_property_set_bool(cpuobj, "has_el2", false, NULL); @@ -2475,6 +2475,7 @@ static void machvirt_init(MachineState *machine) vms->bootinfo.skip_dtb_autoload = true; vms->bootinfo.firmware_loaded = firmware_loaded; vms->bootinfo.psci_conduit = vms->psci_conduit; + vms->bootinfo.force_psci = vms->force_psci; arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo); vms->machine_done.notify = virt_machine_done; @@ -2786,6 +2787,48 @@ static void virt_set_default_bus_bypass_iommu(Object *obj, bool value, vms->default_bus_bypass_iommu = value; } +static bool virt_get_pci(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->pci; +} + +static void virt_set_pci(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->pci = value; +} + +static bool virt_get_force_el3(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->force_el3; +} + +static void virt_set_force_el3(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->force_el3 = value; +} + +static bool virt_get_force_psci(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->force_psci; +} + +static void virt_set_force_psci(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->force_psci = value; +} + static CpuInstanceProperties virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index) { @@ -3267,7 +3310,26 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) "Override the default value of field OEM Table ID " "in ACPI table header." "The string may be up to 8 bytes in size"); - + + object_class_property_add_bool(oc, "pci", + virt_get_pci, + virt_set_pci); + object_class_property_set_description(oc, "pci", + "Enable PCI bus"); + + + object_class_property_add_bool(oc, "force-el3", + virt_get_force_el3, + virt_set_force_el3); + object_class_property_set_description(oc, "force-el3", + "Force enable EL3 even when secure is false"); + + + object_class_property_add_bool(oc, "force-psci", + virt_get_force_psci, + virt_set_force_psci); + object_class_property_set_description(oc, "force-psci", + "Enable QEMU's builtin PSCI emulation even when EL3 is enabled"); } static void virt_instance_init(Object *obj) @@ -3327,6 +3389,10 @@ static void virt_instance_init(Object *obj) vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); + + vms->pci = true; + vms->force_el3 = false; + vms->force_psci = false; } static const TypeInfo virt_machine_info = { diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h index 80c492d7421e8..e701618b35dd4 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h @@ -132,6 +132,7 @@ struct arm_boot_info { bool secure_board_setup; arm_endianness endianness; + bool force_psci; }; /** diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 7b3989ea34149..476259541aa84 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -154,6 +154,9 @@ struct VirtMachineState { bool mte; bool dtb_randomness; bool second_ns_uart_present; + bool pci; + bool force_el3; + bool force_psci; OnOffAuto acpi; VirtGICType gic_version; VirtIOMMUType iommu; diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index bd20a3310c31f..9191f8ac41e24 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -59,7 +59,7 @@ static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr) /* Stage 2 translation enabled: memory type in PTE. */ return false; } - return false; + return true; #endif } @@ -160,7 +160,9 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, int el = arm_current_el(env); uint64_t sctlr = arm_sctlr(env, el); - if (aprofile_require_alignment(env, el, sctlr)) { + // Rollback enforced memory alignment to run Windows on ARM 32-bit + // if (aprofile_require_alignment(env, el, sctlr)) { + if (sctlr & SCTLR_A) { DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); }