On 23/12/24 23:16, Phil Dennis-Jordan wrote:
> From: Alexander Graf <graf@amazon.com>
>
> Apple defines a new "vmapple" machine type as part of its proprietary
> macOS Virtualization.Framework vmm. This machine type is similar to the
> virt one, but with subtle differences in base devices, a few special
> vmapple device additions and a vastly different boot chain.
>
> This patch reimplements this machine type in QEMU. To use it, you
> have to have a readily installed version of macOS for VMApple,
> run on macOS with -accel hvf, pass the Virtualization.Framework
> boot rom (AVPBooter) in via -bios, pass the aux and root volume as pflash
> and pass aux and root volume as virtio drives. In addition, you also
> need to find the machine UUID and pass that as -M vmapple,uuid= parameter:
>
> $ qemu-system-aarch64 -accel hvf -M vmapple,uuid=0x1234 -m 4G \
> -bios /System/Library/Frameworks/Virtualization.framework/Versions/A/Resources/AVPBooter.vmapple2.bin
> -drive file=aux,if=pflash,format=raw \
> -drive file=root,if=pflash,format=raw \
> -drive file=aux,if=none,id=aux,format=raw \
> -device vmapple-virtio-blk-pci,variant=aux,drive=aux \
> -drive file=root,if=none,id=root,format=raw \
> -device vmapple-virtio-blk-pci,variant=root,drive=root
>
> With all these in place, you should be able to see macOS booting
> successfully.
>
> Known issues:
> - Keyboard and mouse/tablet input is laggy. The reason for this is
> that macOS's XHCI driver seems to expect interrupter mapping to
> be disabled when MSI/MSI-X is unavailable. I have found a
> workaround but discovered a bunch of other XHCI spec non-compliance
> in the process, so I'm fixing all of those in a separate patch
> set.
> - Currently only macOS 12 guests are supported. The boot process for
> 13+ will need further investigation and adjustment.
>
> Signed-off-by: Alexander Graf <graf@amazon.com>
> Co-authored-by: Phil Dennis-Jordan <phil@philjordan.eu>
> Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
> Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> Tested-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
> diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
> index bcd1be63e3..6a4c4a7fa2 100644
> --- a/hw/vmapple/Kconfig
> +++ b/hw/vmapple/Kconfig
> @@ -10,3 +10,23 @@ config VMAPPLE_CFG
> config VMAPPLE_VIRTIO_BLK
> bool
>
> +config VMAPPLE
> + bool
> + depends on ARM
> + depends on HVF
> + default y if ARM
> + imply PCI_DEVICES
> + select ARM_GIC
Hmmm I'm getting ...:
qemu-system-aarch64: unknown type 'arm-gicv3'
> + select PLATFORM_BUS
> + select PCI_EXPRESS
> + select PCI_EXPRESS_GENERIC_BRIDGE
> + select PL011 # UART
> + select PL031 # RTC
> + select PL061 # GPIO
> + select GPIO_PWR
> + select PVPANIC_MMIO
> + select VMAPPLE_AES
> + select VMAPPLE_BDIF
> + select VMAPPLE_CFG
> + select MAC_PVG_MMIO
> + select VMAPPLE_VIRTIO_BLK
> +static void create_gic(VMAppleMachineState *vms, MemoryRegion *mem)
> +{
> + MachineState *ms = MACHINE(vms);
> + /* We create a standalone GIC */
> + SysBusDevice *gicbusdev;
> + QList *redist_region_count;
> + int i;
> + unsigned int smp_cpus = ms->smp.cpus;
> +
> + vms->gic = qdev_new(gicv3_class_name());
... I suppose due to this call ^^^.
$ git grep arm-gicv3
hw/intc/arm_gicv3_kvm.c:45:#define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
include/hw/intc/arm_gicv3.h:18:#define TYPE_ARM_GICV3 "arm-gicv3"
$ git grep TYPE_ARM_GICV3
hw/intc/arm_gicv3.c:466: .name = TYPE_ARM_GICV3,
$ git grep -FW arm_gicv3.c
hw/intc/meson.build=9=system_ss.add(when: 'CONFIG_ARM_GICV3_TCG',
if_true: files(
hw/intc/meson.build:10: 'arm_gicv3.c',
...
Ahhh, good catch! I suppose this is with —disable-tcg (or equivalent)
I think commit a8a5546798c ("hw/intc/arm_gicv3: Introduce
CONFIG_ARM_GIC_TCG Kconfig selector") is invalid as being
too restrictive.
I can go a bit further with these changes on top (ignoring
renaming ARM_GICV3_TCG -> ARM_GICV3):
-- >8 --
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index dd405bdb5d2..9e06c05b449 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -26 +26 @@ config ARM_GIC
- select ARM_GICV3_TCG if TCG
+ select ARM_GICV3_TCG if TCG || HVF
@@ -32 +32 @@ config ARM_GICV3_TCG
- depends on ARM_GIC && TCG
+ depends on ARM_GIC && (TCG || HVF)
diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
index 6a4c4a7fa2e..374a89f6a8f 100644
--- a/hw/vmapple/Kconfig
+++ b/hw/vmapple/Kconfig
@@ -19 +19 @@ config VMAPPLE
- select ARM_GIC
+ select ARM_GICV3_TCG
Is this last part necessary/advisable? It would seem like the above changes in hw/intc/Kconfig should make ARM_GIC work too?
(The PVG dependency means we currently can’t support anything other than macOS host systems and thus HVF or theoretically TCG anyway, but if QEMU gained support for the HVF-provided GIC implementation, we’d need to change this line again.)
---
> + qdev_prop_set_uint32(vms->gic, "revision", 3);
> + qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
> + /*
> + * Note that the num-irq property counts both internal and external
> + * interrupts; there are always 32 of the former (mandated by GIC spec).
> + */
> + qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
> +
> + uint32_t redist0_capacity =
> + vms->memmap[VMAPPLE_GIC_REDIST].size / GICV3_REDIST_SIZE;
> + uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
> +
> + redist_region_count = qlist_new();
> + qlist_append_int(redist_region_count, redist0_count);
> + qdev_prop_set_array(vms->gic, "redist-region-count", redist_region_count);
> +
> + gicbusdev = SYS_BUS_DEVICE(vms->gic);
> + sysbus_realize_and_unref(gicbusdev, &error_fatal);
> + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VMAPPLE_GIC_DIST].base);
> + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VMAPPLE_GIC_REDIST].base);
> +
> + /*
> + * Wire the outputs from each CPU's generic timer and the GICv3
> + * maintenance interrupt signal to the appropriate GIC PPI inputs,
> + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
> + */
> + for (i = 0; i < smp_cpus; i++) {
> + DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
> +
> + /* Map the virt timer to PPI 27 */
> + qdev_connect_gpio_out(cpudev, GTIMER_VIRT,
> + qdev_get_gpio_in(vms->gic,
> + arm_gic_ppi_index(i, 27)));
> +
> + /* Map the GIC IRQ and FIQ lines to CPU */
> + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> + sysbus_connect_irq(gicbusdev, i + smp_cpus,
> + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> + }
> +}