Last active
December 12, 2025 17:24
-
-
Save andyvand/26ca76b8e37953f5be894074ce62532d to your computer and use it in GitHub Desktop.
QEMU Windows RT ARM (8.1/10) patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff -Nur qemu-10.1.3/hw/arm/virt-acpi-build.c qemu-10.1.3-winrt/hw/arm/virt-acpi-build.c | |
| --- qemu-10.1.3/hw/arm/virt-acpi-build.c 2025-12-06 16:26:44 | |
| +++ qemu-10.1.3-winrt/hw/arm/virt-acpi-build.c 2025-12-12 18:19:56 | |
| @@ -139,6 +139,58 @@ | |
| aml_append(table, scope); | |
| } | |
| +static void acpi_dsdt_add_ehci(Aml *scope, const MemMapEntry *ehci_memmap, | |
| + uint32_t ehci_irq) | |
| +{ | |
| + Aml *dev = aml_device("USB0"); | |
| + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0D20"))); | |
| + aml_append(dev, aml_name_decl("_UID", aml_int(0))); | |
| + | |
| + Aml *crs = aml_resource_template(); | |
| + aml_append(crs, | |
| + aml_memory32_fixed(ehci_memmap->base, | |
| + ehci_memmap->size, AML_READ_WRITE)); | |
| + aml_append(crs, | |
| + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, | |
| + AML_EXCLUSIVE, &ehci_irq, 1)); | |
| + aml_append(dev, aml_name_decl("_CRS", crs)); | |
| + aml_append(scope, dev); | |
| +} | |
| + | |
| +static void acpi_dsdt_add_mmci(Aml *scope, const MemMapEntry *sdhci_memmap, | |
| + uint32_t sdhci_irq) | |
| +{ | |
| + Aml *dev = aml_device("SDC1"); | |
| + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0D40"))); | |
| + aml_append(dev, aml_name_decl("_UID", aml_int(0))); | |
| + | |
| + Aml *crs = aml_resource_template(); | |
| + aml_append(crs, | |
| + aml_memory32_fixed(sdhci_memmap->base, | |
| + sdhci_memmap->size, AML_READ_WRITE)); | |
| + aml_append(crs, | |
| + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, | |
| + AML_EXCLUSIVE, &sdhci_irq, 1)); | |
| + aml_append(dev, aml_name_decl("_CRS", crs)); | |
| + | |
| + /* Add a child device that represents the SD card, | |
| + which is marked as non-removable */ | |
| + Aml *carddev = aml_device("SDMM"); | |
| + | |
| + Aml *adr = aml_method("_ADR", 0, AML_NOTSERIALIZED); | |
| + aml_append(adr, aml_return(aml_int(0))); | |
| + | |
| + Aml *rmv = aml_method("_RMV", 0, AML_NOTSERIALIZED); | |
| + aml_append(rmv, aml_return(aml_int(0))); | |
| + | |
| + aml_append(carddev, adr); | |
| + aml_append(carddev, rmv); | |
| + aml_append(dev, carddev); | |
| + | |
| + aml_append(scope, dev); | |
| +} | |
| + | |
| +#ifdef USE_ARM_PCI | |
| static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, | |
| uint32_t irq, VirtMachineState *vms) | |
| { | |
| @@ -176,6 +228,7 @@ | |
| build_acpi0017(scope); | |
| } | |
| } | |
| +#endif | |
| static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, | |
| uint32_t gpio_irq) | |
| @@ -932,7 +985,14 @@ | |
| virtio_acpi_dsdt_add(scope, memmap[VIRT_MMIO].base, memmap[VIRT_MMIO].size, | |
| (irqmap[VIRT_MMIO] + ARM_SPI_BASE), | |
| 0, NUM_VIRTIO_TRANSPORTS); | |
| + | |
| +#ifdef USE_ARM_PCI | |
| acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); | |
| +#endif | |
| + | |
| + 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) { | |
| build_ged_aml(scope, "\\_SB."GED_DEVICE, | |
| HOTPLUG_HANDLER(vms->acpi_dev), | |
| @@ -955,6 +1015,7 @@ | |
| } | |
| acpi_dsdt_add_power_button(scope); | |
| + | |
| #ifdef CONFIG_TPM | |
| acpi_dsdt_add_tpm(scope, vms); | |
| #endif | |
| diff -Nur qemu-10.1.3/hw/arm/virt.c qemu-10.1.3-winrt/hw/arm/virt.c | |
| --- qemu-10.1.3/hw/arm/virt.c 2025-12-06 16:26:44 | |
| +++ qemu-10.1.3-winrt/hw/arm/virt.c 2025-12-12 18:19:19 | |
| @@ -91,6 +91,8 @@ | |
| #include "hw/cxl/cxl.h" | |
| #include "hw/cxl/cxl_host.h" | |
| #include "qemu/guest-random.h" | |
| +#include "hw/sd/sdhci.h" | |
| +#include "hw/usb/hcd-ehci.h" | |
| static GlobalProperty arm_virt_compat[] = { | |
| { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" }, | |
| @@ -187,7 +189,11 @@ | |
| [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, | |
| [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, | |
| [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, | |
| +#ifdef USE_ARM_PCI | |
| [VIRT_ACPI_PCIHP] = { 0x090c0000, ACPI_PCIHP_SIZE }, | |
| +#endif | |
| + [VIRT_EHCI] = { 0x090c0000, 0x00001000 }, | |
| + [VIRT_SDHCI] = { 0x090d0000, 0x00000100 }, | |
| [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, | |
| /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ | |
| [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, | |
| @@ -239,6 +245,8 @@ | |
| [VIRT_GPIO] = 7, | |
| [VIRT_UART1] = 8, | |
| [VIRT_ACPI_GED] = 9, | |
| + [VIRT_EHCI] = 11, | |
| + [VIRT_SDHCI] = 12, | |
| [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ | |
| [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ | |
| [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ | |
| @@ -691,7 +699,9 @@ | |
| SysBusDevice *sbdev; | |
| int irq = vms->irqmap[VIRT_ACPI_GED]; | |
| uint32_t event = ACPI_GED_PWR_DOWN_EVT; | |
| +#ifdef USE_ARM_PCI | |
| bool acpi_pcihp; | |
| +#endif | |
| if (ms->ram_slots) { | |
| event |= ACPI_GED_MEM_HOTPLUG_EVT; | |
| @@ -711,6 +721,7 @@ | |
| sysbus_mmio_map_name(sbdev, ACPI_MEMHP_REGION_NAME, | |
| vms->memmap[VIRT_PCDIMM_ACPI].base); | |
| +#ifdef USE_ARM_PCI | |
| acpi_pcihp = object_property_get_bool(OBJECT(dev), | |
| ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, NULL); | |
| @@ -721,6 +732,7 @@ | |
| vms->memmap[VIRT_ACPI_PCIHP].base); | |
| assert(pcihp_region_index >= 0); | |
| } | |
| +#endif | |
| sysbus_connect_irq(sbdev, 0, qdev_get_gpio_in(vms->gic, irq)); | |
| @@ -1443,6 +1455,45 @@ | |
| 0x7 /* PCI irq */); | |
| } | |
| +static void create_ehci(const VirtMachineState *vms, int ehci) | |
| +{ | |
| + sysbus_create_simple(TYPE_PLATFORM_EHCI, vms->memmap[ehci].base, | |
| + qdev_get_gpio_in(vms->gic, vms->irqmap[ehci])); | |
| +} | |
| + | |
| +static void create_sdhci(const VirtMachineState *vms) | |
| +{ | |
| + | |
| + hwaddr base = vms->memmap[VIRT_SDHCI].base; | |
| + int irq = vms->irqmap[VIRT_SDHCI]; | |
| + DeviceState *dev; | |
| + SysBusDevice *busdev; | |
| + DriveInfo *di; | |
| + BlockBackend *blk; | |
| + DeviceState *carddev; | |
| + BusState *bus; | |
| + | |
| + dev = qdev_new(TYPE_SYSBUS_SDHCI); | |
| + qdev_prop_set_uint8(dev, "sd-spec-version", 2); | |
| + qdev_prop_set_uint64(dev, "capareg", VIRT_SDHCI_CAPABILITIES); | |
| + | |
| + busdev = SYS_BUS_DEVICE(dev); | |
| + sysbus_realize_and_unref(busdev, &error_fatal); | |
| + sysbus_mmio_map(busdev, 0, base); | |
| + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(vms->gic, irq)); | |
| + | |
| + di = drive_get(IF_SD, 0, 0); | |
| + blk = di ? blk_by_legacy_dinfo(di) : NULL; | |
| + bus = qdev_get_child_bus(dev, "sd-bus"); | |
| + if (bus == NULL) { | |
| + error_report("No SD bus found"); | |
| + exit(1); | |
| + } | |
| + carddev = qdev_new(TYPE_SD_CARD); | |
| + qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); | |
| + qdev_realize_and_unref(carddev, bus, &error_fatal); | |
| +} | |
| + | |
| static void create_smmu(const VirtMachineState *vms, | |
| PCIBus *bus) | |
| { | |
| @@ -2310,9 +2361,9 @@ | |
| aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); | |
| - if (!vms->secure) { | |
| - object_property_set_bool(cpuobj, "has_el3", false, 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->virt && object_property_find(cpuobj, "has_el2")) { | |
| object_property_set_bool(cpuobj, "has_el2", false, NULL); | |
| @@ -2465,6 +2516,7 @@ | |
| create_rtc(vms); | |
| create_pcie(vms); | |
| + | |
| create_cxl_host_reg_region(vms); | |
| if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { | |
| @@ -2486,6 +2538,12 @@ | |
| * no backend is created the transport will just sit harmlessly idle. | |
| */ | |
| create_virtio_devices(vms); | |
| + | |
| + /* Create platform EHCI controller device */ | |
| + create_ehci(vms, VIRT_EHCI); | |
| + | |
| + /* Create platform SD host controller device */ | |
| + create_sdhci(vms); | |
| vms->fw_cfg = create_fw_cfg(vms, &address_space_memory); | |
| rom_set_fw(vms->fw_cfg); | |
| diff -Nur qemu-10.1.3/hw/intc/arm_gicv2m.c qemu-10.1.3-winrt/hw/intc/arm_gicv2m.c | |
| --- qemu-10.1.3/hw/intc/arm_gicv2m.c 2025-12-06 16:26:44 | |
| +++ qemu-10.1.3-winrt/hw/intc/arm_gicv2m.c 2025-12-12 15:57:16 | |
| @@ -155,7 +155,13 @@ | |
| sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->spi[i]); | |
| } | |
| +#ifdef USE_ARM_GPIO | |
| msi_nonbroken = true; | |
| +#else | |
| + fprintf(stderr, "%s: Disable MSI-X for Windows 10 ARM64 on KVM\n", __func__); | |
| + msi_nonbroken = false; | |
| +#endif | |
| + | |
| kvm_gsi_direct_mapping = true; | |
| kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); | |
| } | |
| diff -Nur qemu-10.1.3/include/hw/acpi/acpi-defs.h qemu-10.1.3-winrt/include/hw/acpi/acpi-defs.h | |
| --- qemu-10.1.3/include/hw/acpi/acpi-defs.h 2025-12-06 16:26:45 | |
| +++ qemu-10.1.3-winrt/include/hw/acpi/acpi-defs.h 2025-12-12 16:04:44 | |
| @@ -98,6 +98,45 @@ | |
| uint64_t addr; /* Address */ | |
| } AcpiGas; | |
| +#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ | |
| + uint32_t signature; /* ACPI signature (4 ASCII characters) */ \ | |
| + uint32_t length; /* Length of table, in bytes, including header */ \ | |
| + uint8_t revision; /* ACPI Specification minor version # */ \ | |
| + uint8_t checksum; /* To make sum of entire table == 0 */ \ | |
| + uint8_t oem_id[6] \ | |
| + QEMU_NONSTRING; /* OEM identification */ \ | |
| + uint8_t oem_table_id[8] \ | |
| + QEMU_NONSTRING; /* OEM table identification */ \ | |
| + uint32_t oem_revision; /* OEM revision number */ \ | |
| + uint8_t asl_compiler_id[4] \ | |
| + QEMU_NONSTRING; /* ASL compiler vendor ID */ \ | |
| + uint32_t asl_compiler_revision; /* ASL compiler revision number */ | |
| + | |
| +struct AcpiDebugPort2 { | |
| + ACPI_TABLE_HEADER_DEF | |
| + uint32_t debug_devices_offset; | |
| + uint32_t number_debug_devices; | |
| + struct { | |
| + uint8_t revision; | |
| + uint16_t length; | |
| + uint8_t number_generic_address_registers; | |
| + uint16_t namespace_string_length; | |
| + uint16_t namespace_string_offset; | |
| + uint16_t oem_data_length; | |
| + uint16_t oem_data_offset; | |
| + uint16_t port_type; | |
| + uint16_t port_subtype; | |
| + uint8_t reserved1[2]; | |
| + uint16_t base_address_register_offset; | |
| + uint16_t address_size_offset; | |
| + struct AcpiGenericAddress base_address[1]; | |
| + uint32_t address_size[1]; | |
| + uint8_t namespace_string[2]; | |
| + } QEMU_PACKED debug_devices[1]; | |
| +} QEMU_PACKED; | |
| +typedef struct AcpiDebugPort2 | |
| + AcpiDebugPort2; | |
| + | |
| /* SPCR (Serial Port Console Redirection table) */ | |
| typedef struct AcpiSpcrData { | |
| uint8_t interface_type; | |
| diff -Nur qemu-10.1.3/include/hw/arm/virt.h qemu-10.1.3-winrt/include/hw/arm/virt.h | |
| --- qemu-10.1.3/include/hw/arm/virt.h 2025-12-06 16:26:45 | |
| +++ qemu-10.1.3-winrt/include/hw/arm/virt.h 2025-12-12 17:30:11 | |
| @@ -64,6 +64,8 @@ | |
| VIRT_GIC_REDIST, | |
| VIRT_SMMU, | |
| VIRT_UART0, | |
| + VIRT_EHCI, | |
| + VIRT_SDHCI, | |
| VIRT_MMIO, | |
| VIRT_RTC, | |
| VIRT_FW_CFG, | |
| @@ -182,6 +184,8 @@ | |
| }; | |
| #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) | |
| + | |
| +#define VIRT_SDHCI_CAPABILITIES 0x057834b4 | |
| #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") | |
| OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment